Как правильно настроить считывание клавиш?

Здравствуйте! Помогите, пожалуйста с такой проблемой.
Объясню ситуацию:
у меня есть анимация полёта без нажатия на клавишу атаки, которая состоит из двух анимаций: сам полет и приземление
у меня еще есть анимация атаки в полете, в ней три анимации: переход для полета, атака в полете, приземление с атакой после полета.

Что мне нужно:
когда я нажимаю на левую кнопку мышки и отпускаю ее, у меня активируется атака в полете.
Сам полёт, если я не нажимаю ЛКМ, работает правильно.
На данный момент у меня это работало только с зажатой клавишей мыши(немного другой код), но если я отпущу её, то всё сломается опять. Может быть, нужен другой метод считывания нажатие клавиши? Потому что в данном случае, считывание клавиши вызывается постоянно(fixupdate/update), и, соответственно, если клавиша не нажата в определенном моменте, то соответственно ее значение будет false, и при этом «состояние атаки в падении» обнуляется.

и есть еще один вопрос, как правильно подождать какое то время перед выполнением следующего кода? Например, я хочу чтобы во время бега был рывок: например, на 2 секунды у меня скорость становится sprintspeed*2, а потом автоматически переходит на sprintspeed.

public MovementState state;
    public enum MovementState
    {
        idle,
        walking,
        sprinting,
        crouching,
        air
    }
    bool mousedown = false;
    private void Update()
    {
        Vector3 colliderCenter = capsuleCollider.center;
        Vector3 origin = transform.position;
        // ground check
        grounded = Physics.Raycast(origin, Vector3.down, playerHeight * 0.5f + 1f, whatIsGround);
        Debug.DrawRay(origin, Vector3.down * (playerHeight * 0.5f + 1f), Color.blue); // Рисуем луч
        MyInput();
        SpeedControl();
        UpdateAnimationStates();
        if (Input.GetMouseButtonUp(0))
        {
            animator.SetBool("inAirAttack", true);
        }
        if (grounded)
            rb.drag = groundDrag;
        else
            rb.drag = 0;
        // Дополнительная проверка на отсутствие препятствия над персонажем
        if (!keyDown)
        {
            StandUp(); // Если нет препятствия и персонаж не приседает, то вставляем
        }     
    private void FixedUpdate()
    {
        MovePlayer();
        StateHandler();
        if (Input.GetKeyDown(sprintKey))
        {
            run = true;
        }

        if (Input.GetKeyUp(sprintKey))
        {
            run = false;
        }
        if (Input.GetMouseButtonDown(0))
        {
            mousedown = true;
        }
    }
  
    private void StateHandler()
    {
        RaycastHit hit;
        Vector3 origin = transform.position;
        if (grounded)
        {

            // Mode - Sprinting
            if ((Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0) && Input.GetKey(sprintKey))
            {
                state = MovementState.sprinting;
                moveSpeed = sprintSpeed;
            }
            // Mode - Crouching
            else if (Input.GetKey(crouchKey))
            {
                state = MovementState.crouching;
                moveSpeed = crouchSpeed;
            }
            // Mode - Walking
            else if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)
            {
                state = MovementState.walking;
                moveSpeed = walkSpeed;
            }
            // Mode - Idle
            else
            {
                state = MovementState.idle;
            }
        }
        //Mode - Air
        else if (!Physics.Raycast(origin, Vector3.down, out hit, playerHeight * 0.5f + 3f, whatIsGround))
        {
            state = MovementState.air;
            //Debug.Log("air");
        }
    }

    private void UpdateAnimationStates()
    {
        Vector3 origin = transform.position;
        // Сбрасываем все параметры перед установкой новых значений
        animator.SetBool("IsWalking", false);
        animator.SetBool("IsRunning", false);
        animator.SetBool("IsStanding", false);
        animator.SetBool("inAir", false);
        animator.SetBool("inAirAttack", false);
        // Устанавливаем параметры в аниматоре
        switch (state)
        {
            case MovementState.idle:
                animator.SetBool("IsStanding", true);
                break;
            case MovementState.walking:
                animator.SetBool("IsWalking", true);
                break;
            case MovementState.crouching:
                animator.SetBool("IsSitting", true);
                break;
            case MovementState.sprinting:
                animator.SetBool("IsRunning", true);
                break;
            case MovementState.air:
                animator.SetBool("inAir", true);
                break;
            default:
                break;
        }
    }
}
  • Вопрос задан
  • 271 просмотр
Пригласить эксперта
Ответы на вопрос 2
Vindicar
@Vindicar
RTFM!
Автомат состояний. У тебя его зачаток написан в StateHandler(), хотя и немного корявый.
Нужно так же иметь ввижу, что с персонажем могут быть ассоциированы несколько параллельно работающих автоматов состояний. Например, один связан с движением, другой - с атаками, третий - с абилками и т.д..

Что касается рывка при спринте, просто сделай два состояния. При нажатии клавиши переходишь в состояние рывок, если по прошествию 2 секунд клавиша ещё не отпущена, то переводишь состояние в спринт. При отпускании в любом из двух состояний переходишь в ходьбу.
Ответ написан
@DrRen7
Тут больше надо работать с аниматором. Про состояния а зачем их столько? Чем бег, ходьба и айдл отличаются друг от друга?
Я б оставил только 3 состояния OnGround, OnAir, Crouch это я б единственное, что оставил в Bool в аниматоре. Атаку можно передать как триггер, ну а движение это флот.
И да все инпуты должны быть в Update
Ответ написан
Ваш ответ на вопрос

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

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