我的游戏中有两个场景,其中有一个门对象,玩家可以与之交互以在两者之间来回移动。我使用
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);
}
}
}
}
我真的很感激任何帮助或建议。谢谢!
我认为这是一个脚本执行顺序问题,脚本的顺序在场景之间是变化的。 Unity 不保证 Update 等方法的脚本执行顺序,除非您在项目设置中覆盖脚本执行顺序。
场景一:Chest.Update先运行
Chest.Update
运行(isOpen = false)Interactor.Update
运行并调用Chest.Interact
(isOpen = true)场景2:Interactor.Update先运行
Interactor.Update
运行并调用Chest.Interact
(isOpen = true)Chest.Update
运行(isOpen = false)如果你想播放一次性动画,我建议使用
Animator.SetTrigger
方法而不是使用 bool - 这样你就不会在需要关闭时担心任何时间问题。
或者,您可以覆盖脚本执行顺序 - 但随着这类问题的出现,这很快就会失控,通常最好生成不会根据更新时间中断的代码。
另一种选择可能是将一些逻辑移至 LateUpdate,但同样,这对于大项目来说不是可扩展的解决方案。