1.创建Player
添加游戏Player和添加游戏场景的物件是一样的,同样需要修改合适的像素点为32,过滤模式为点采样,还有压缩为None。
其次添加刚体与碰撞体。
为玩家设置Player覆盖层级NPC和碰撞层级同名为NPC,并修改Npc与其他物件的物理关系。使它与游戏环境不进行碰撞交互,只有在发生攻击行为是才会产生物理碰撞。如下图所示:
2.添加Player脚本
2.1 添加PlayerController.cs
创建名为PlayerController的脚本,并为玩家挂载这一脚本组件。
2.2 控制Player的基本移动
实现移动
获取刚体组件private Rigidbody2D rb;,定义移动速度为浮点型public float speed;
void Movement()
{
// float horizontalInput = Input.GetAxis("Horizontal"); // 获取的值从-1~1,包括小数
float horizontalInput = Input.GetAxisRaw("Horizontal"); // 获取的值从-1~1,不包含小数
rb.velocity = new Vector2(horizontalInput * speed, rb.velocity.y); // 使用物理向量的速度固定移动速度 y保持不变,x为输入*速度
}
Input.GetAxis("Horizontal")获取的值是-1~1包括小数,所以游戏中当按下方向键的时候,人物的移动速度是由小逐渐变大,有缓冲的效果。使用GetAxisRaw进行快节奏的移动,它是不包含小数字的。
控制翻转
在移动函数内通过修改本地坐标来进行人物翻转,是坐标值等于一个新的三位向量Vector3,因为它拥有x,y,z轴。当输入值horizontalInput为-1,向左移动时为x=-1,horizontalInput=1,向右移动x=1,x与horizontalInput的值是一致的,y和z轴保持不变。
// 修改transform的本地坐标来进行翻转
if (horizontalInput != 0)
transform.localScale = new Vector3(horizontalInput, 1, 1);
2.3 控制Player的跳跃
定义一个辅助函数用来专门收集玩家的输入操作,对输入的按键进行判断,当输入为空格时可以进行跳跃。这里可以先用一个bool型的变量对是否可以进行跳跃进行标记。public bool isCanJump;
辅助函数只用来对按压的键位进行判断。
void CheckInput()
{
if (Input.GetButtonDown("Jump"))
isCanJump = true;
}
跳跃函数
void Jump()
{
if (isCanJump)
{
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
isCanJump = false;
}
}
跳跃的向量需要值得注意的是,x的值保持不变,但是不能写成0,这样会导致player不能向左或者向右移动。跳跃以后需要把按键操作清零,不然会跳跃到顶。
2.4 解决跳跃bug
目前存在的bug
- 跳跃起来的速度和重力下落不舒适不真实,需要通过修改重力比例和跳跃力
- 连续按空格jump时,Player会连续向上跳跃
- 当跳跃后按左或者右方向键时,Player会卡在屏幕上无法运动
贴近墙壁问题
添加物理材质修改摩擦力为0,这样就不会卡在墙壁上而是自然滑落。
无限跳跃和落地手感问题
为了避免人物无限跳跃,就需要检测人物只有在地面的时候才可以使用跳跃。
首先需要检测人物是否在地面,需要一个检测的点。如果在这个点的一定范围之内发现有地面,地面的层级Layer在前面设置的是Ground。那么只需要检测它对应的是Ground,就说明它在地面上了。
让人物获得地面监测点的坐标位置,即它的transform组件的position。找到位子后在他的周围一定的范围之内进行物理碰撞检测,看看是否有属于Ground的Layer。
[Header("Ground Check")]
public Transform groundCheck; // 检测的点
public float checkRadius; // 检测范围
public LayerMask groundLayer; // 选择对应的图层
[Header("States Check")]
public bool isGround; // 状态监测
添加检测函数
// 地面检测函数使用圆形检测
void PhysicsCheck()
{
// 坐标,检测范围,图层
isGround = Physics2D.OverlapCircle(groundCheck.position, checkRadius, groundLayer);
}
我这里设置检测范围是0.5。此时游戏运行时,已解决无限跳跃的问题。
2.5 可视化检测范围
// 可视化检测范围 系统方法,不需要在任何Update里进行调用
public void OnDrawGizmos()
{
// 中心点/检测范围
Gizmos.DrawWireSphere(groundCheck.position, checkRadius);
}
如图所示,会在红色检测点出现一个白色圆圈的检测范围。
2.6 修改重力检测
控制在跳跃时重力修改为4,落地时为1。
if (isGround)
rb.gravityScale = 1;
else
rb.gravityScale = 4;
3.PlayerController.cs
本节中添加的玩家代码。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 游戏玩家控制器,主要包含玩家的基本移动即左右移动和跳跃攻击
public class PlayerController : MonoBehaviour
{
// 获取刚体组件
private Rigidbody2D rb;
public float speed;
public float jumpForce; // 跳跃的力
[Header("Ground Check")] public Transform groundCheck; // 检测的点
public float checkRadius; // 检测范围
public LayerMask groundLayer; // 选择对应的图层
[Header("States Check")] public bool isGround; // 状态监测
public bool isCanJump; // 是否可以跳跃
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
CheckInput();
}
void FixedUpdate()
{
PhysicsCheck(); // 一开始就检测物理
Movement();
Jump();
}
// 执行人物移动的方法 需要获取按键
void Movement()
{
// float horizontalInput = Input.GetAxis("Horizontal"); // 获取的值从-1~1,包括小数
float horizontalInput = Input.GetAxisRaw("Horizontal"); // 获取的值从-1~1,不包含小数
rb.velocity = new Vector2(horizontalInput * speed, rb.velocity.y); // 使用物理向量的速度固定移动速度 y保持不变,x为输入*速度
// 修改transform的本地坐标来进行翻转
if (horizontalInput != 0)
transform.localScale = new Vector3(horizontalInput, 1, 1);
}
// 控制Player跳跃
void Jump()
{
if (isCanJump)
{
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
isCanJump = false;
}
}
// 用来收集Player输入的操作
void CheckInput()
{
// 当按下跳跃按键的时候同时也要检测是否在地面
if (Input.GetButtonDown("Jump") && isGround)
isCanJump = true;
}
// 地面检测函数使用圆形检测
void PhysicsCheck()
{
// 坐标,检测范围,图层
isGround = Physics2D.OverlapCircle(groundCheck.position, checkRadius, groundLayer);
if (isGround)
rb.gravityScale = 1;
else
rb.gravityScale = 4;
}
// 可视化检测范围 系统方法,不需要在任何Update里进行调用
public void OnDrawGizmos()
{
// 中心点/检测范围
Gizmos.DrawWireSphere(groundCheck.position, checkRadius);
}
}