Из-за чего анимация не проигрывается при включении объекта?

Ссылка скопирована
1 ответ

Сейчас ситуация такая: суть проблемы: при использовании метода HideItemsInHand внутри ShowItemInHand() ломается аниматор и анимация застывает на 1 кадре
Скрипт:

using UnityEngine; using UnityEngine.UI; public class QuickslotInventory : MonoBehaviour { // Объект у которого дети являются слотами [SerializeField] private Transform quickslotParent; [SerializeField] private Transform _itemHolder; [SerializeField] private InventoryManager inventoryManager; public int currentQuickslotID = 0; [SerializeField] private Sprite selectedSprite; [SerializeField] private Sprite notSelectedSprite; [SerializeField] private MenuPaused _menuManager; [SerializeField] private InventorySlot _activeSlot; // Update is called once per frame void Update() { float mw = Input.GetAxis("Mouse ScrollWheel"); // Используем колесико мышки if (mw < 0.1 && _menuManager.isMenuPaused == false && quickslotParent.childCount < 5) { // Берем предыдущий слот и меняем его картинку на обычную quickslotParent.GetChild(currentQuickslotID).GetComponent<Image>().sprite = notSelectedSprite; // Если крутим колесиком мышки вперед и наше число currentQuickslotID равно последнему слоту, то выбираем наш первый слот (первый слот считается нулевым) if (currentQuickslotID >= quickslotParent.childCount-1) { currentQuickslotID = 0; } else { // Прибавляем к числу currentQuickslotID единичку currentQuickslotID++; } // Берем предыдущий слот и меняем его картинку на "выбранную" quickslotParent.GetChild(currentQuickslotID).GetComponent<Image>().sprite = selectedSprite; _activeSlot = quickslotParent.GetChild(currentQuickslotID).GetComponent<InventorySlot>(); ShowItemInHand(); // Что то делаем с предметом: } if (mw > -0.1 && _menuManager.isMenuPaused == false && quickslotParent.childCount < 5) { // Берем предыдущий слот и меняем его картинку на обычную quickslotParent.GetChild(currentQuickslotID).GetComponent<Image>().sprite = notSelectedSprite; // Если крутим колесиком мышки назад и наше число currentQuickslotID равно 0, то выбираем наш последний слот if (currentQuickslotID <= 0) { currentQuickslotID = quickslotParent.childCount-1; } else { // Уменьшаем число currentQuickslotID на 1 currentQuickslotID--; } // Берем предыдущий слот и меняем его картинку на "выбранную" quickslotParent.GetChild(currentQuickslotID).GetComponent<Image>().sprite = selectedSprite; _activeSlot = quickslotParent.GetChild(currentQuickslotID).GetComponent<InventorySlot>(); ShowItemInHand(); // Что то делаем с предметом: } // Используем цифры for(int i = 0; i < quickslotParent.childCount; i++) { // если мы нажимаем на клавиши 1 по 5 то... if (Input.GetKeyDown((i + 1).ToString()) && _menuManager.isMenuPaused == false && quickslotParent.childCount < 5) { // проверяем если наш выбранный слот равен слоту который у нас уже выбран, то if (currentQuickslotID == i) { // Ставим картинку "selected" на слот если он "not selected" или наоборот if (quickslotParent.GetChild(currentQuickslotID).GetComponent<Image>().sprite == notSelectedSprite) { quickslotParent.GetChild(currentQuickslotID).GetComponent<Image>().sprite = selectedSprite; _activeSlot = quickslotParent.GetChild(currentQuickslotID).GetComponent<InventorySlot>(); ShowItemInHand(); } else { quickslotParent.GetChild(currentQuickslotID).GetComponent<Image>().sprite = notSelectedSprite; _activeSlot = null; HideItemsInHand(); } } // Иначе мы убираем свечение с предыдущего слота и светим слот который мы выбираем else { quickslotParent.GetChild(currentQuickslotID).GetComponent<Image>().sprite = notSelectedSprite; currentQuickslotID = i; quickslotParent.GetChild(currentQuickslotID).GetComponent<Image>().sprite = selectedSprite; _activeSlot = quickslotParent.GetChild(currentQuickslotID).GetComponent<InventorySlot>(); ShowItemInHand(); } } } } private void ShowItemInHand() { if (_activeSlot.item == null) { return; } for (int i = 0; i < _itemHolder.childCount; i++) { if (_activeSlot.item.itemName == _itemHolder.GetChild(i).name) { _itemHolder.GetChild(i).gameObject.SetActive(true); } } } private void HideItemsInHand() { for (int i = 0; i < _itemHolder.childCount; i++) { _itemHolder.GetChild(i).gameObject.SetActive(false); } } }

Частично помогло_animator.keepAnimatorStateOnDisable = true;Сейчас ситуация такая:, но при дефолтно значении, то есть false в аниматоре следующая картина: анимации застывают на 1 кадре и не могут проиграться дальше
68acba878a14e663657806.png

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Артём Dev Ответ

По описанию очень похоже, что HideItemsInHand() отключает объект, на котором висит Animator, или отключает дочерний объект в момент, когда вы сразу пытаетесь запустить анимацию. В Unity при SetActive(false) состояние Animator сбрасывается/останавливается, а при повторном включении он может остаться на первом кадре, если триггер был выставлен до активации или если объект включили не в том порядке.

Типичная ошибка в инвентарях такая: сначала скрываются все предметы в руке, потом включается нужный предмет, но Animator/Animation на нем уже получил Play/SetTrigger в момент, когда GameObject был inactive. Визуально это выглядит как “анимация застывает на первом кадре”.

Проверьте порядок действий. Надежная схема:

  • Сначала выключить старый активный предмет.
  • Включить новый предмет.
  • Получить Animator уже на активном объекте.
  • Сбросить состояние Animator при необходимости.
  • Запустить анимацию через Play/SetTrigger после включения.
private void ShowItemInHand(GameObject item)
{
    HideItemsInHand();
 
    item.SetActive(true);
 
    var animator = item.GetComponentInChildren&lt;Animator&gt;(true);
    if (animator != null)
    {
        animator.Rebind();
        animator.Update(0f);
        animator.Play("Show", 0, 0f);
    }
}

private void ShowItemInHand(GameObject item) { HideItemsInHand(); item.SetActive(true); var animator = item.GetComponentInChildren&lt;Animator&gt;(true); if (animator != null) { animator.Rebind(); animator.Update(0f); animator.Play("Show", 0, 0f); } }

Если Animator находится на общем _itemHolder, а вы выключаете только модели предметов, лучше не отключать объект с Animator. Оставьте holder активным, а скрывайте MeshRenderer/SpriteRenderer или конкретные child-модели. Это стабильнее, чем каждый раз выключать всю иерархию.

Еще один частый момент: если в Animator Controller переход из Entry в состояние зависит от trigger, а trigger вызывается на inactive-объекте, он может не отработать. Тогда вместо SetTrigger попробуйте прямой Play с нулевой нормализованной позицией, как в примере выше.

Также проверьте галочку Animator: Keep Animator Controller State On Disable. Она может помочь, если вам нужно сохранять состояние при выключении объекта, но для предмета в руке чаще правильнее явно переинициализировать анимацию после включения. В вашем случае я бы сначала убедился, что HideItemsInHand() не выключает _itemHolder или родителя активного слота, а затем перенес запуск анимации строго после item.SetActive(true).

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно