new to unity, at first i use Input.GetAxisRaw(“Horizontal”) in one ‘playercontroller’ script to control player’s movement, and everything worked fine, player’s velocity.x only got -1/0/1. But when i use it in a state machine, i got this problem:
when i press a/d , player’s velocity.x set to -1/1 and it’s fine, then i release the button, velocity.x should return to 0 immediately but it first return to some strange number like 8.725659e-15, then to 0
刚学unity,我一开始只用playercontroller一个脚本控制角色所有行动,在这个脚本里用 Input.GetAxisRaw(“Horizontal”)控制玩家左右移动,然后也没什么问题,后来接触到状态机,在对着教程写代码的时候出现了这个问题:
按a/d进行移动时,velocity.x正常被设定为-1/1,但是松开按键后rigidbody里的velocity.x不会立即回到0,而是先回到一个类似8.725659e-15这样莫名其妙的值,然后再回到0。
Player.cs
public class Player : MonoBehaviour
{
[Header("Move Info")]
public float moveSpeed;
#region 定义Unity组件
public Animator anim { get; private set; }
public Rigidbody2D rb { get; private set; }
#endregion
#region 定义States
public PlayerStateMachine stateMachine { get; private set; }
public PlayerIdleState idleState { get; private set; }
public PlayerMoveState moveState { get; private set; }
#endregion
private void Awake()
{
stateMachine = new PlayerStateMachine();
idleState = new PlayerIdleState(this, stateMachine, "Idle");
moveState = new PlayerMoveState(this, stateMachine, "Move");
}
private void Start()
{
anim = GetComponentInChildren<Animator>();
rb = GetComponent<Rigidbody2D>();
stateMachine.Initialize(idleState);
}
private void Update()
{
stateMachine.currentState.Update();
}
public void SetVelocity(float _xVelocity, float _yVelocity)
{
rb.velocity = new Vector2(_xVelocity, _yVelocity);
}
}
PlayerState.cs
//被继承的总类,后面的所以state都需要继承它
//实际上Player并没有进入过这个状态,没有调用此脚本,所有的调用均属于此脚本的子脚本
public class PlayerState
{
protected PlayerStateMachine stateMachine;//创建PlayerStateMachine类,以承接来自Player.cs传过来的东西
protected Player player;//创建Player类,以承接来自Player.cs传过来的东西
#region Unity组件
protected Rigidbody2D rb;//纯简化,将player.rb --> rb
#endregion
private string animBoolName;
protected float xInput;
public PlayerState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName)
{
this.player = _player;
this.stateMachine = _stateMachine;
this.animBoolName = _animBoolName;
}//构造函数,用于传递信息
public virtual void Enter()
{
player.anim.SetBool(animBoolName, true);//通过animator自带的函数,将animator里的Bool值改变为想要的值
rb = player.rb;//纯简化,将player.rb --> rb
}
public virtual void Update()
{
xInput = Input.GetAxisRaw("Horizontal");//对于键盘和游戏杆输入,该值将处于 -1...1 的范围内。 由于未对输入进行平滑处理,键盘输入将始终为 -1、0 或 1。 如果您想自己完成键盘输入的所有平滑处理,这非常有用。
}
public virtual void Exit()
{
player.anim.SetBool(animBoolName, false);
}
}
PlayeyMoveState.cs
public class PlayerMoveState : PlayerState
{
public PlayerMoveState(Player _player, PlayerStateMachine _playerStateMachine, string _animBoolName) : base(_player, _playerStateMachine, _animBoolName)
{
}
public override void Enter()
{
base.Enter();
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
player.SetVelocity(xInput, player.rb.velocity.y);
if (xInput == 0)
stateMachine.ChangeState(player.idleState);
}
}
PlayerStateMachine.cs
public class PlayerStateMachine
{
/// <summary>
/// 用来切换状态
/// </summary>
public PlayerState currentState { get; private set; }
public void Initialize(PlayerState _startState)
{
currentState = _startState;
currentState.Enter();
}
public void ChangeState(PlayerState _newState)
{
currentState.Exit();
currentState = _newState;
currentState.Enter();
}
}
PlayerIdleState.cs
public class PlayerIdleState : PlayerState
{
public PlayerIdleState(Player _player, PlayerStateMachine _playerStateMachine, string _animBoolName) : base(_player, _playerStateMachine, _animBoolName)
{
}
public override void Enter()
{
base.Enter();
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
if (xInput != 0)
stateMachine.ChangeState(player.moveState);
}
}
Just to be clear, that number would be 0.0000000000000087. When your input is controlled by keys on your keyboard, the axis should usually return back to 0. However when you have some kind of game controller with analog sticks, they rarely return back to perfect 0. Note that this is one of the differences between "GetAxis" and "GetAxisRaw". The "Raw" version gives you the unfiltered value. Currently I can't remember if the dead-zone is actually applied to the raw version or not, but I would guess it's not.
– Bunny83thanks for your answer, i've rebuilt my project and it's going well, i might have made some mistakes in building game map, so it could have led to some errors in the physical systems
– Sakuyurixxx