简体   繁体   中英

How do I use goto attribute in Unity 3D?

Does this work? This is in the start method, using photon for networking. I am trying to wait till room time is initialised.

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

In general I would say avoid using goto at all !

In almost all cases I can think of any other solution in my eyes is cleaner and better to read and maintain than goto jumps. It is more a "relic" of former times. In the examples of goto might be the only use-case where it might make sense.. within a switch-case or to break out of a nested loop.. but even there you can find other (in my eyes better) solutions.

Your code basically equals writing

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

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

And latest now I hope you see the huge issue : You have a neverending while loop!

  • Inside the while the condition is never changed
  • And it can not be changed from the outside either since you run this in Start so the entire Unity main thread is blocked until that loop ends. I'm not 100% sure but afaik PhotonNetwork needs the Unity main thread to dispatch the received events -> your condition probably will never ever become true.

You should rather use a Coroutine . A Coroutine is like a small temporary Update method. It is not async but rather runs right after Update until the next yield statement and thereby still allows your Unity main thread to continue rendering and doesn't freeze your entire application.

// 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());

    ....
}

Even better than checking this every frame in a loop at all would actually be

  • check this once in start
  • only check it again once after the room properties have actually changed

So something like eg

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);
}

And rather make other methods wait until isInitialized is true.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM