На игроке висит скрипт, каждый кадр выполняющий функцию Move()
private void Move()
{
if (Input.GetKeyDown(KeyCode.W))
{
states.currentState.Go();
Debug.Log(states.currentState);
}
if (Input.GetKeyDown(KeyCode.LeftShift))
{
states.currentState.Accelerate();
}
if (Input.GetKeyUp(KeyCode.A))
{
transform.Rotate(new Vector3(0, rotationSpeed * Time.deltaTime, 0));
}
if (Input.GetKeyUp(KeyCode.W))
{
Debug.Log(states.currentState);
states.Reset();
}
if (Input.GetKeyDown(KeyCode.Space))
{
states.currentState.Jump();
}
}
В states находится структура, хранящая состояния игрока и управляющая ими
. Вот она:
public struct PlayerStates
{
public PlayerStates(Rigidbody _rb, Animator _anim)
{
initialState = new InitialPlayerState(_anim, _rb);
currentState = initialState;
walkingState = new WalkingPlayerState(_anim, _rb);
runningState = new RunningPlayerState(_anim, _rb);
jumpingState = new JumpingPlayerState(_anim, _rb);
doubleJumpingState = new DoubleJumpingPlayerState(_anim, _rb);
focusedState = new FocusedPlayerState(_anim, _rb);
states = new IPlayerStates[] { initialState, currentState, walkingState, runningState, jumpingState, doubleJumpingState, focusedState };
foreach (IPlayerStatesDelegates element in states)
{
element.switchToWalk += changeToWalking;
element.switchToFocuse += changeToFocused;
element.switchToJump += changeToJump;
element.switchToRun += changeToRunning;
}
}
public IPlayerStates[] states;
public IPlayerStates currentState { get; set; }
public IPlayerStates initialState;
public IPlayerStates walkingState;
public IPlayerStates runningState;
public IPlayerStates jumpingState;
public IPlayerStates doubleJumpingState;
public IPlayerStates focusedState;
private void changeToFocused()
{
currentState = focusedState;
}
private void changeToWalking()
{
currentState = walkingState;
}
private void changeToRunning()
{
currentState = runningState;
}
private void changeToJump()
{
if (currentState == jumpingState)
currentState = doubleJumpingState;
else if (currentState != doubleJumpingState)
currentState = jumpingState;
}
public void Reset()
{
currentState.Reset();
currentState = initialState;
}
}
Изначально states.currentState = new InitialPlayerState(). В этом классе есть метод выключающий анимацию ходьбы или бега Reset(), который ничего не делает (логично, ведь изначально игрок просто стоит). При нажатии на W игрок начинается двигаться вперёд и states.currentState должно уже стать walkingState = new WalkingPlayerState() (выполняется ивент в классе InitialPlayerState, запускающий метод changeToWalking), а при отпускании W выполняется метод Reset и игрок должен остановиться (ибо в WalkingPlayerState этот метод выключает анимацию). Но он не останавливается! Функция, меняющая currentState выполняется, но в консоль все равно выводится InitialPlayerState.
Вот непосредственно классы состояний:
public abstract class PlayerState : IPlayerStates, IPlayerStatesDelegates
{
protected Animator anim;
protected Rigidbody rb;
protected float jumpSpeed;
protected float walkingSpeed;
protected Transform tr;
public PlayerState(Animator _anim, Rigidbody _rb)
{
Init(_anim, _rb);
}
protected void Init(Animator _anim, Rigidbody _rb)
{
anim = _anim;
rb = _rb;
tr = rb.gameObject.transform;
jumpSpeed = 10;
walkingSpeed = 10;
}
protected void Move(float speed)
{
tr.position += tr.forward * speed * Time.deltaTime;
}
public event ChangeStateToWalking switchToWalk;
public virtual void Go()
{
Move(walkingSpeed);
anim.SetBool("Walk", true);
switchToWalk();
}
public event ChangeStateToFocused switchToFocuse;
public virtual bool Focuse()
{
anim.SetBool("Focuse", true);
switchToFocuse();
return true;
}
public event ChangeStateToRunning switchToRun;
public virtual bool Accelerate()
{
Move(walkingSpeed * 2);
anim.SetBool("Run", true);
anim.SetBool("Walk", false);
switchToRun();
return true;
}
public virtual void Shoot()
{
anim.SetTrigger("Shoot");
}
public virtual void AvoidDefeat()
{
anim.SetTrigger("Bend");
}
public event ChangeStateToJumping switchToJump;
public virtual bool Jump()
{
rb.AddForce(Vector3.up * (jumpSpeed / 2));
anim.SetTrigger("Jump");
switchToJump();
return true;
}
public event Defeated lose;
public virtual void Defeat()
{
anim.SetTrigger("Lose");
lose();
}
public abstract void Reset();
}
public class InitialPlayerState : PlayerState
{
public InitialPlayerState(Animator _anim, Rigidbody _rb) : base(_anim, _rb)
{
Init(_anim, _rb);
}
public override void Reset()
{
}
}
public class WalkingPlayerState : PlayerState
{
public WalkingPlayerState(Animator _anim, Rigidbody _rb) : base(_anim, _rb)
{
Init(_anim, _rb);
}
public override void Go()
{
}
public override void Reset()
{
anim.SetBool("Walk", false);
}
}
+ есть еще проблема, что игрок не двигается вперёд при выполнении метода PlayerState.Move(). Буду очень благодарна если поможете решить эти 2 проблемы.