(010)Unity3d 有关Invoke和 Coroutine 的执行条件的误解
Unity3d 有关Invoke和 Coroutine 的执行条件的误解
·
UI上InvokeRepeating 不执行
因为 Time.scale = 0 了 ><。
InvokeRepeating 的同名函数调用
对同一个函数的 InvokeRepeating调用,前一个不会覆盖之前的同名函数调用。
有关Invoke和 Coroutine 的执行条件的误解
之前一直以为在父物体未激活的状态下, invoke 和 Coroutine 都不会执行。这里面有一点误区。
正解
- Coroutine 在父物体未激活状态下,确实不会执行。并且如果在父物体(包括祖先节点)没有激活的情况下,直接调用 StartCoroutine 会抛出不可 catch 的错误
2. invoke 在父物体(包括祖先节点)未激活的情况下,如果被调用,依然会执行。
测试代码
代码下载:Test_CallInvoke_CallCoroutine_When_GameObject_Active.unitypackage
物体层级:
父物体代码:
using UnityEngine;
public class ParentNode : MonoBehaviour
{
[SerializeField]
private ChildNode ChildNode;
private void Awake()
{
ChildNode.SetParent(this);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.W))
{
Debug.Log("Get W Key Down");
gameObject.SetActive(true);
ChildNode.gameObject.SetActive(false);
ChildNode.CallInvoke();
ChildNode.CallCoroutine();
}
}
[ContextMenu(nameof(Call_When_Inactive))]
public void Call_When_Inactive()
{
gameObject.SetActive(false);
ChildNode.gameObject.SetActive(false);
ChildNode.CallInvoke();
ChildNode.CallCoroutine();
}
[ContextMenu(nameof(Call_When_Active_Then_Inactive))]
public void Call_When_Active_Then_Inactive()
{
gameObject.SetActive(true);
ChildNode.gameObject.SetActive(true);
ChildNode.CallInvoke();
ChildNode.CallCoroutine();
ChildNode.gameObject.SetActive(false);
}
}
子物体的代码:
using System;
using System.Collections;
using UnityEngine;
public class ChildNode : MonoBehaviour
{
private ParentNode _parentNode;
public void SetParent(ParentNode parentNode)
{
_parentNode = parentNode;
}
private void Update()
{
Debug.Log(nameof(ChildNode));
}
public void CallCoroutine()
{
// if (!gameObject.activeInHierarchy)
// return;
try
{
StartCoroutine(Internal_Called_From_Coroutine());
}
catch (Exception e)
{
// 注意,物体未激活,调用协程,异常不可捕捉
Debug.LogError($"must can't catch error, {e}");
}
}
public void CallInvoke()
{
Invoke(nameof(Internal_Called_From_Invoke), 3);
}
public void Internal_Called_From_Invoke()
{
Debug.Log(
$"{nameof(Internal_Called_From_Invoke)}"
+ $", 父物体激活状态: {(_parentNode.gameObject.activeSelf ? "true" : "false")}"
+ $", 当前物体激活状态: {(gameObject.activeSelf ? "true" : "false")}"
);
}
IEnumerator Internal_Called_From_Coroutine()
{
yield return new WaitForSeconds(3);
Debug.Log(
$"{nameof(Internal_Called_From_Coroutine)}"
+ $", 父物体激活状态: {(_parentNode.gameObject.activeSelf ? "true" : "false")}"
+ $", 当前物体激活状态: {(gameObject.activeSelf ? "true" : "false")}"
);
}
}
执行截图
- 父物体激活,脚本所在的物体未激活的情况:
2. 父物体和脚本所在的物体都未激活的情况:
3. 在父物体和子物体的都激活的情况,调用invoke 和 Coroutine,然后马上关闭子物体的激活状态:
这里是一个专注于游戏开发的社区,我们致力于为广大游戏爱好者提供一个良好的学习和交流平台。我们的专区包含了各大流行引擎的技术博文,涵盖了从入门到进阶的各个阶段,无论你是初学者还是资深开发者,都能在这里找到适合自己的内容。除此之外,我们还会不定期举办游戏开发相关的活动,让大家更好地交流互动。加入我们,一起探索游戏开发的奥秘吧!
更多推荐
已为社区贡献1条内容
所有评论(0)