Анимация открытия дверей лифта. Срабатывает позиция этажей одновременно

Нужна помощь. Создал лифт, создал анимацию, но из-за Update(), который постоянно обновляется на этаже, не срабатывает анимация (я так думаю, может и не прав). Вернее постоянно работает. Как правильно организовать в данных условиях корректное закрытие дверей при нажатии кнопки лифта и открытие дверей, когда лифт оказался на этаже? Я понимаю как анимация должна работать, но не могу понять как это сделать в данных условиях. По возможности, объясните подробно, так как 2 недели в unity. Спасибо за ответ.

 using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
 
[RequireComponent(typeof(AudioSource))]
 
public class Elevator_trigger : MonoBehaviour
{
    [Header("Анимации")]
    public Animator anim;
 
 
    [Header("Лифт")]
    public Transform floor_pos_1;
    public Transform floor_pos_2;
    public Transform floor_pos_3;
 
    public GameObject Text_for_use_button;
    public GameObject Elevator;
    private int count_floors;
    private float velocity = 5f;
 
    private bool on_floor;
    private bool on_move;
 
    public int button_used_floor;
 
    void Start()
    {
        anim.Play("DoorOpen");
    }
    public void GetCallFloor(int Calling_floor)
    {
        button_used_floor = Calling_floor;
    }
 
    void FixedUpdate()
    {
        if (on_floor == true)
        {
            Debug.Log("on_floor = true");
            switch (button_used_floor)
            {
                case 1:
                    on_move = true;
                    on_floor = false;  
                    Debug.Log("On 1st floor");
                    break;
                case 2:
                    on_move = true;
                    on_floor = false;
                    Debug.Log("On 2nd floor");
                    break;
                case 3:
                    on_move = true;
                    on_floor = false;
                    Debug.Log("On 3rd floor");
                    break;
            }
        }
 
        if (on_move == true && button_used_floor == 1) //moving first floor
        {
            Elevator.transform.position = Vector3.MoveTowards(Elevator.transform.position, floor_pos_1.position, velocity * Time.deltaTime);
 
            if (Elevator.transform.position.y == floor_pos_1.position.y)
            {
                on_move = false;
                on_floor = true;
            }
        }
 
        else if (on_move == true && button_used_floor == 2) //moving second floor
        {
            Elevator.transform.position = Vector3.MoveTowards(Elevator.transform.position, floor_pos_2.position, velocity * Time.deltaTime);  
            if (Elevator.transform.position.y == floor_pos_2.position.y)
            {
                on_move = false;
                on_floor = true;
            }
        }
        else if (on_move == true && button_used_floor == 3) // moving third floor
        {
            Elevator.transform.position = Vector3.MoveTowards(Elevator.transform.position, floor_pos_3.position, velocity * Time.deltaTime);
 
            if (Elevator.transform.position.y == floor_pos_3.position.y)
            {
                on_move = false;
                on_floor = true;
            }
        }
       
    }
 
    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Player")
        {
            Debug.Log("in trigger");
            on_floor = true;
        }
    }
    private void OnTriggerExit(Collider other)
    {
        if (other.tag == "Player")
        {
            on_floor = false;
        }
    }
}

Ответы (1 шт):

Автор решения: grouptout

Итак. Для решения данной проблемы я создал свой лифт с кнопками и возможностью захода/выхода из него. Заходить и выходить я тоже буду через кнопки но вы можете это заменить триггерами.

Если у вас 2д игра то все то же самое только без третьей координаты. Используйте Update() а не FixedUpdate() для нефизического передвижения (без действий на rigidbody

MonoBehaviour.FixedUpdate has the frequency of the physics system. Источник из документации: https://docs.unity3d.com/ru/current/ScriptReference/MonoBehaviour.FixedUpdate.html )

Для начала создал лифт с дверью введите сюда описание изображения

Создал 2 анимации открытия и закрытия двери в сторону введите сюда описание изображения Снимаем галку с обеих анимашек введите сюда описание изображения В аниматоре создаем пустой прямоугольник и ставим его дефолтным правой кнопкой мыши, 2 наших анимации просто висят в воздухе

введите сюда описание изображения

Поместил лифт на сцену, создал и разместил 3 точки CreateEmpty для координат наших этажей введите сюда описание изображения

Создал Canvas с кнопками для управления лифтом (В вашей игре его можно будет скрыть а потом включит если вы подошли к лифту и тд...) введите сюда описание изображения

Ну а теперь пишем простенький скрипт для лифта. Суть такова. создаем массив arrayOfFloors[] с нашими точками этажей (0 элемент - 1 этаж, 1 ел - 2 этаж ..) Добавляем аниматор, скорость лифта. Создаем переменную Transform _targetFloor её мы будем менять при нажатии кнопок, а тем временем в Update() лифт будем всегда стремиться к _targetFloor. В Awake() _targetFloor ставим на 1-й этаж можно заменить если по умолчанию этаж другой.. Для управления анимациями создана корутина IEnumerator OpenAndCloseDoor() в которой мы проигрываем анимацию открытия двери, ждем 2 секунды и закрываем дверь. Вызывать мы её будем из метода OnEnterOrExitFromElevator() который в свою очередь будет у меня вызываться по кнопке входа выхода а у Вас может и по триггеру и тд.. Также при входе выходе я меняю переменную _isAnyoneInElevator потому что мы не модем ехать и нажимать на кнопки если мы не сели в лифт.

Метод OnGoToFloor(int floor) мы тоже будем вызывать по кнопке. Также в самом редакторе присвоим каждой кнопке свое значение floor для того чтобы этот метод знал на какой этаж мы хотим приехать. В самом методе просто присваиваем нашему _targetFloor соответствующий элемент массива arrayOfFloors[]. Ну а тут уже будет работать метод Update, который будет плавно нас переносить куда мы захотим:

using System.Collections;
using UnityEngine;

public class Elevator : MonoBehaviour
{
   public Transform[] arrayOfFloors; // Массив координат этажей
   public Animator doorAnimator;
   public float elevatorSpeed = 5;

   private bool _isAnyoneInElevator; // есть ли кто в лифте ???
   private Transform _targetFloor; // позиция этажа на которую мы будем ехать
   private float _elevatorPosition;
   
   public void OnEnterOrExitFromElevator() // Ивент на кнопку захода / выхода из лифта. Можно будет заменить на `OnTriggerEnter` и тд
   {
      _isAnyoneInElevator = !_isAnyoneInElevator; // лифт пуст / не пуст
      StartCoroutine(OpenAndCloseDoor()); // запуск корутины для проигрывания анимации закрытия / открытия дверей лифта
   }

   public void OnGoToFloor(int floor) // Ивент на кнопку нажатия кнопки лифта (1, 2, ...)
   {
      if (_isAnyoneInElevator) // если мы в лифте
      {
         _targetFloor = arrayOfFloors[floor - 1]; // меняем позицию этажа на нужную 
      }
   }

   private void Awake()
   {
      _targetFloor = arrayOfFloors[0]; // стандартная позиция лифта на 1м этаже
   }

   private void Update()
   {
      // наш лифт всегда будет стремиться к `_targetFloor`
      
      _elevatorPosition = Mathf.Lerp(_elevatorPosition, _targetFloor.position.y, Time.deltaTime * elevatorSpeed); // плавное изменение _elevatorPosition по y-координате
      transform.position = new Vector3(transform.position.x, _elevatorPosition, transform.position.z); // применение новой позиции, вычеслиной выше

   }

   private IEnumerator OpenAndCloseDoor() // корутина для проигрывания анимации закрытия / открытия дверей лифта
   {
      doorAnimator.Play("open_elevator");// открываем двери
      yield return new WaitForSeconds(2); // ждем 2 секунды
      doorAnimator.Play("close_elevator");// закрываем двери
   }
}

Ну а теперь возвращаемся в редактор, цепляем скрипт на лифт и начинаем настройку скрипта в редакторе. введите сюда описание изображения

И кнопки введите сюда описание изображения введите сюда описание изображения

Все готово. Вот видео-результат: https://youtu.be/3-N2ns7fFnc Вот ссылка с проектом на гите: https://github.com/grouptout/elevator

Ps. Естественно мою реализацию можно подганять уже под разные задачи, условия, события и тд.

Забыл добавить. Чтобы дверь открывалась автоматически можно создать в классе булевую переменную например bool _wannaOpenDoor = false; тогда при вызове

public void OnGoToFloor(int floor) // Ивент на кнопку нажатия кнопки лифта (1, 2, ...)
   {
      if (_isAnyoneInElevator) // если мы в лифте
      {
         _wannaOpenDoor = true;
         _targetFloor = arrayOfFloors[floor - 1]; // меняем позицию этажа на нужную 
      }
   }

и в Update

private void Update()
   {
      // наш лифт всегда будет стремиться к `_targetFloor`
      
      _elevatorPosition = Mathf.Lerp(_elevatorPosition, _targetFloor.position.y, Time.deltaTime * elevatorSpeed); // плавное изменение _elevatorPosition по y-координате
      transform.position = new Vector3(transform.position.x, _elevatorPosition, transform.position.z); // применение новой позиции, вычеслиной выше

    // если мы толькочто приехали
    if(Math.Abs(transform.position.y - _targetFloor.position.y) < 0.02 && _wannaOpenDoor) 
    {
        _wannaOpenDoor = false; 
        OnEnterOrExitFromElevator(); // автоматически открываем дверь после приезда
    }
   }

Теперь по приезду на этаж двери автоматически открываются. На гите обновил проект с этим функционалом. Вот видео-результат с автоматическими дверьми: https://youtu.be/g7LMmzTPECQ

→ Ссылка