@PyChan

Почему поле класса не изменяется?

На игроке висит скрипт, каждый кадр выполняющий функцию 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 проблемы.
  • Вопрос задан
  • 149 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы