Unity 3D 动画在切换场景时停止工作?

问题描述 投票:0回答:1

我的游戏中有两个场景,其中有一个门对象,玩家可以与之交互以在两者之间来回移动。我使用

DontDestroyOnLoad
让玩家对象在场景之间转换。在第一个场景中,我有一个箱子对象,当玩家在交互范围内时,它会打开动画。从该场景开始游戏时,动画会按预期运行。当我转到第二个场景然后回到第一个场景时,动画不再有效,尽管一切看起来都应该如此。

当我返回场景 1 并且动画器设置为“始终动画”时,动画器组件(及其动画控制器)和我的胸部脚本仍在胸部对象上。我仍然能够与箱子互动,所以在互动范围内触发动画似乎不是问题的一部分。

这是动画胸部的脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Chest : MonoBehaviour, IInteractable
{   
    [SerializeField] private string prompt;
    public string InteractionPrompt => prompt;
    private bool MouseDn = false;
    Animator animator;
    
    private void Awake()
    {
        animator = gameObject.GetComponent<Animator>();
    }
    public void OnMouseDown()
    {
        MouseDn = true;
    }

    public void OnMouseUp()
    {
        MouseDn = false;
    }
    public bool Interact(Interactor interactor)
    {
        animator.SetBool("isOpen", true);
        
        if (MouseDn == true)
        {
            MouseDn = false;
            Debug.Log(message:"Opening Chest!");
            return true;
        }
        else
        {
            return false;
        }
    }
    private void Update()
    {
        animator.SetBool("isOpen", false);
    }
}

这使用接口 IInteractable:

public interface IInteractable
{
    public string InteractionPrompt{ get; }
    public bool Interact(Interactor interactor);
}

玩家有一个脚本“Interactor”:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class Interactor : MonoBehaviour
{
    [SerializeField] private Transform interactionPoint;
    [SerializeField] private float interactionPointRadius = 0.5f;
    [SerializeField] private LayerMask interactableMask;

    private readonly Collider[] colliders = new Collider[3];
    [SerializeField] private int numFound;

    private void Update()
    {
        numFound = Physics.OverlapSphereNonAlloc(interactionPoint.position, interactionPointRadius, colliders, interactableMask);

        if (numFound > 0)
        {
            var interactable = colliders[0].GetComponent<IInteractable>();
            if (interactable != null)
            {
                interactable.Interact(this);
            }
        }
    }
}

我真的很感激任何帮助或建议。谢谢!

unity3d animation
1个回答
0
投票

我认为这是一个脚本执行顺序问题,脚本的顺序在场景之间是变化的。 Unity 不保证 Update 等方法的脚本执行顺序,除非您在项目设置中覆盖脚本执行顺序。

场景一:Chest.Update先运行

  1. Chest.Update
    运行(isOpen = false)
  2. Interactor.Update
    运行并调用
    Chest.Interact
    (isOpen = true)
  3. 动画师运行并播放动画,因为 isOpen 为真

场景2:Interactor.Update先运行

  1. Interactor.Update
    运行并调用
    Chest.Interact
    (isOpen = true)
  2. Chest.Update
    运行(isOpen = false)
  3. 动画师运行并且没有任何变化,因为 isOpen 是 false

如果你想播放一次性动画,我建议使用

Animator.SetTrigger
方法而不是使用 bool - 这样你就不会在需要关闭时担心任何时间问题。

或者,您可以覆盖脚本执行顺序 - 但随着这类问题的出现,这很快就会失控,通常最好生成不会根据更新时间中断的代码。

另一种选择可能是将一些逻辑移至 LateUpdate,但同样,这对于大项目来说不是可扩展的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.