我正在制作一个游戏,在该游戏中,我希望对象开始隐藏或不活动,并在几秒钟后出现。我尝试使用协程,但是问题或错误是,因为我从一开始就将对象设置为隐藏或不活动,协程需要活动对象,因此我从另一个外部脚本进行尝试,但仍然没有成功。第二个脚本甚至没有启动。有人有任何建议或解决方法吗?
我已经从另一个外部脚本尝试过,但是仍然没有成功。在我添加的图片中,Num Trigger脚本在碰撞后只是禁用了对象。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ActivationRutine : MonoBehaviour
{
public GameObject objectToActivate;
// Start is called before the first frame update
void Start()
{
StartCoroutine(StartFunction());
}
private IEnumerator StartFunction()
{
//Wait for 5 sec.
yield return new WaitForSeconds(5);
//Turn My game object that is set to false(off) to True(on).
objectToActivate.SetActive(true);
}
}
答案 0 :(得分:0)
协程是对象而不是函数。是由包含StartCoroutine()
调用的游戏对象托管的。调用本身仅添加协程对象,并使用统一的协程调度程序对其进行调度。这意味着协程仅在禁用或销毁宿主对象时,或者在通过StopCoroutine()
调用通知调度程序停止协程时才停止。
您可以:
[推荐]
A)将协程存放在与未激活/激活的对象不同的对象上。这是最佳做法。
[不推荐]
B)禁用对象中的组件,例如禁用了“渲染器”,“碰撞器”和逻辑脚本,而对象本身仍处于活动状态。在激活脚本上,启用禁用的组件和脚本。 片段:
private void Awake() {
var components = GetComponents<MonoBehaviour>().ToList();
components.Remove(this);
foreach (var component in components)
component.enabled = false;
StartCoroutine(ActivationCountdown(3f));
}
private void Activate() {
var components = GetComponents<MonoBehaviour>().ToList();
components.Remove(this);
foreach (var component in components)
component.enabled = true;
Destroy(this);
}
private IEnumerator ActivationCountdown(float time) {
yield return new WaitForSeconds(time);
Activate();
}
不建议使用(B)方法,因为尽管在所有其他组件都被禁用的情况下解决方案很容易,但是一旦您开始需要管理哪些内容的列表,它很快就会成为工作的噩梦。需要从启动开始激活VS延迟后激活。我需要在编辑器中为每个对象进行设置,或者需要使用脚本来管理每种情况。变成了依赖性意大利面条。
将协程托管在外部(例如,单例)要容易得多。您具有一个依赖项:您的对象需要在单例上调用函数,将自身作为参数引用,就像我在代码片段中对变量“ time”进行引用一样。这应该很容易管理,因为它是一个单例。
答案 1 :(得分:0)
除了完全不使用协程,您还可以简单地使用Invoke
,它仍将在禁用的对象上执行!
您可以将其做成一个类似
的小组件public class DelayedActivation : MonoBehaviour
{
[Tooltip("Automatically activtae the object after delay.\n"
+ "If set to false object has to be activated by another script.\n"
+ "Can still be done delayed using 'ActivateDelayed()'")]
public bool ActivateOnStart = true;
public float ActivationDelay = 5.0f;
// Start is called before the first frame update
private void Start()
{
gameObject.SetActive(false);
if (ActivateOnStart) ActivateDelayed();
}
private void AfterDelay()
{
gameObject.SetActive(true);
}
/*
* Activates the object after the configured delay
*/
public void ActivateDelayed()
{
Invoke(nameof(AfterDelay), ActivationDelay);
}
/*
* Activates the object after the passed custom delay
*/
public void ActivateDelayed(float customDelay)
{
Invoke(nameof(AfterDelay), customDelay)
}
}