1.地面和墙面的碰撞检测
player脚本:
[Header("Collision info")]//碰撞的相关定义
[SerializeField] private Transform groundCheck;//玩家对象的一个子对象,负责对碰撞的检测
[SerializeField] private float groundCheckDistance;//地面碰撞检测的距离
[SerializeField] private Transform wallCheck;
[SerializeField] private float wallCheckDistance;//同上
[SerializeField] private LayerMask whatIsground;//图层,需要自己添加一个ground图层并设置平台的图层为Ground
public bool isGroundDetected() => Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsground);//检测bool值的定义,可以在状态里调用
public void OnDrawGizmos()
{
Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));
Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x + wallCheckDistance, wallCheck.position.y));
}//调试功能方便我们确定检测的距离
PlayerGroundedState脚本:
修改函数:
if(Input.GetKeyDown(KeyCode.Space)&&_Player.isGroundDetected())//检测是否在地面
{
_PlayerStateMachine.ChangeState(_Player.jumpState);
}
PlayerAirState脚本:
修改:
if(_Player.isGroundDetected())//当检测在地面时切换为待机状态
{
_PlayerStateMachine.ChangeState(_Player.idleState);
}
那两条白线便是对地面和墙的检测距离的具象化,实践游戏是不显示的。
2.翻转功能
Player脚本:
添加定义:
public int facingDir { get; private set; } = 1;//朝向1和-1表示
private bool facingRight = true;//是否面向右边
构建函数:
public void Flip()//翻转功能
{
facingDir = -facingDir;
facingRight = !facingRight;//取反
transform.Rotate(0, 180, 0);//y轴旋转
}
public void FlipContorller(float _x)//翻转控制函数
{
if(_x>0&&!facingRight)//如果朝向是1但面向左则执行翻转函数
{
Flip();
}
else if(_x<0&&facingRight)
{
Flip();
}
}
修改SetVelocity()函数:
public void SetVelocity(float _xVelocity,float _yVelocity)
{
rb.velocity=new Vector2(_xVelocity, _yVelocity);
FlipContorller(_xVelocity);//实现控制角色的翻转
}
PlayerMoveState脚本:
Update()中:
_Player.SetVelocity(xInput * _Player.moveSpeed, rb.velocity.y);
3.冲刺功能:
主要思路:在PlayerState中设置一个计时器,再创建一个冲刺的状态,进入时我们将计时器设置为冲刺的持续时间并逐帧减小,当计时器小于0时退出,并设置速度为0。
准备好冲刺动画(Dash参数):
Player脚本:
添加定义
public float dashSpeed = 12f;//冲刺速度
public float dashDuration = 0.5f;//持续时间
public PlayerDashState dashState { get; private set; }//定义
Awake()中初始化:
dashState = new PlayerDashState(stateMachine, this, "Dash");
PlayerState脚本中:
protected float stateTimer;//计时器
Update()中:
stateTimer-= Time.deltaTime;//递减
创建PlayerDashState脚本,继承自PlayerState并重写和重构:
public class PlayerDashState : PlayerState
{
public PlayerDashState(PlayerStateMachine _playerStateMachine, Player _player, string _animboolName) : base(_playerStateMachine, _player, _animboolName)
{
}
public override void Enter()
{
base.Enter();
stateTimer = _Player.dashDuration;//进入时设置计时器
}
public override void Exit()
{
base.Exit();
_Player.SetVelocity(0, rb.velocity.y);//退出时重置速度
}
public override void Update()
{
base.Update();
_Player.SetVelocity( _Player.facingDir * _Player.dashSpeed, rb.velocity.y);//冲刺时加快移动
if(stateTimer<0)
{
_PlayerStateMachine.ChangeState(_Player.idleState);//计时器过了则切换至待机状态
}
}
}
PlayerGroundState脚本:
Update()中:
if(Input.GetKeyDown(KeyCode.LeftShift))
{
_PlayerStateMachine.ChangeState(_Player.dashState);//按下左shift进入冲刺状态
}
这样就实现了冲刺的功能了: