Time, coroutines and random numbers

The clock

Time.time, Time.timeAsDoubleSeconds since the world started on this game (the scripts' clock). Time.timeSinceLevelLoad and Time.realtimeSinceStartup read the same clock.
Time.deltaTime, Time.unscaledDeltaTimeThe length of the current frame, in seconds.
Time.frameCountFrames run so far.
Time.fixedDeltaTimeThe length of a physics step (FixedUpdate).
Time.localTimeOfDaySeconds since midnight on the machine's clock: the player's own time of day on their game, the server's on the server.
Networking.serverTimeThe server's clock, the same for every player (synced objects and values).

Each game starts its own clock when it loads the world: Time.time differs between players. To agree on a moment, use the server's clock.

Wait: coroutines

csharp
using System.Collections;
using NodeWorld.Flux;
using Flux;

namespace MyWorld
{
    public class Fountain : FluxScript
    {
        public ParticleSystem water;

        protected override void Start() => StartCoroutine(Cycle());

        private IEnumerator Cycle()
        {
            while (true)
            {
                water.Play();
                yield return new WaitForSeconds(5f);
                water.Stop();
                yield return new WaitUntil(() => Players.count > 0);
            }
        }
    }
}
  • StartCoroutine(routine) runs it at once up to its first yield return. It belongs to the script: it stops when the script is destroyed or fails.
  • yield return null: the next frame. new WaitForSeconds(s): s seconds of the scripts' clock. new WaitUntil(predicate), new WaitWhile(predicate): checked at once, then each frame. Another IEnumerator: runs it inside, then goes on. Another Coroutine: waits for it to end. A Task: waits for it to complete.
  • StopCoroutine(coroutine), StopAllCoroutines(): their finally blocks run.
  • A class of yours derived from CustomYieldInstruction, with keepWaiting, waits as long as it returns true.

WaitForSeconds, WaitUntil, WaitWhile, CustomYieldInstruction and Frame are in using Flux;.

Run later

  • RunAfter(seconds, action): runs action after that many seconds of the scripts' clock, as long as the script lives.
  • RunAfterFrames(frames, action): after that many frames (1: the next one).

Both return the Coroutine, to stop it.

async methods

async and await work: await Frame.Next() resumes the method at the next frame, and a method awaiting a task (Task.Run, a web request) resumes on the main thread, where the world API is allowed. See threads and async.

csharp
protected override async void Start()
{
    await Frame.Next();
    Debug.Log("One frame later");
}

Random numbers

Random.value (0 to 1, both included), Random.Range(min, max) (floats: both included; ints: max excluded), Random.insideUnitSphere, Random.onUnitSphere, Random.insideUnitCircle, Random.rotation.

The world has one sequence for all its scripts. Random.InitState(seed) makes it the same for every player who uses the same seed: share a seed in a synced state or a network event, and each game draws the same show.