首页 > 解决方案 > 如何在 Unity 3D 中使用 goto 属性?

问题描述

这行得通吗?这是在启动方法中,使用光子进行联网。我正试图等到房间时间初始化。

 Wait:
        if (!PhotonNetwork.CurrentRoom.CustomProperties.ContainsKey("StartTime") )
        {
            goto Wait;
        }
        else
        {
            goto Continue;
        }
        Continue:
        startTime = double.Parse(PhotonNetwork.CurrentRoom.CustomProperties["StartTime"].ToString());

标签: c#unity3dphoton

解决方案


一般来说,我会说goto 完全避免使用!

在几乎所有情况下,我认为任何其他解决方案都比goto跳转更清洁、更易于阅读和维护。它更像是过去的“遗物”。在示例中,goto可能是唯一有意义的用例......在一个或打破嵌套循环......但即使在那里你也可以找到其他(在我看来更好的)解决方案switch-case

你的代码基本上等于写

while(!PhotonNetwork.CurrentRoom.CustomProperties.ContainsKey("StartTime")) { }

startTime = double.Parse(PhotonNetwork.CurrentRoom.CustomProperties["StartTime"].ToString());

最新的我希望你能看到一个巨大的问题:你有一个永无止境的while循环!

  • 内部while条件永远不会改变
  • 而且它也不能从外部更改,因为您在其中运行它,Start因此整个 Unity 主线程被阻塞,直到该循环结束。我不是 100% 确定,但 afaikPhotonNetwork需要 Unity 主线程来调度接收到的事件 -> 你的情况可能永远不会成为真的。

您应该使用Coroutine. 协程就像一个小的临时Update方法。它不是异步的,而是Update在下一条yield语句之后立即运行,因此仍然允许您的 Unity 主线程继续渲染并且不会冻结您的整个应用程序。

// Yes, if you make Start return IEnumerator
// then Unity automatically runs it as a Coroutine!
private IEnumerator Start ()
{
    // https://docs.unity3d.com/ScriptReference/WaitUntil.html
    // This basically does what it says: Wait until a condition is true
    // In a Coroutine the yield basically tells Unity
    // "pause" this routine, render this frame and continue from here in the next frame
    yield return new WaitUntil(() => PhotonNetwork.CurrentRoom.CustomProperties.ContainsKey("StartTime"));

    startTime = double.Parse(PhotonNetwork.CurrentRoom.CustomProperties["StartTime"].ToString());

    ....
}

甚至比在一个循环中检查每一帧实际上更好

  • 在开始时检查一次
  • 只有在房间属性实际更改后再次检查一次

所以像例如

bool isInitialzed;

private void Start ()
{
    TryGetStartTime (PhotonNetwork.CurrentRoom.CustomProperties);
}

private void TryGetStartTime(Hashtable properties)
{
    if(!properties.Contains("StartTime")) return;

    startTime = double.Parse(properties["StartTime"].ToString());
    isInitialzed = true;
}

public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
{
    TryGetStartTime (propertiesThatChanged);
}

而是让其他方法等到isInitialized为真。


推荐阅读