Scripts, callbacks and fields
A script is a C# class of the world's FL# scripts folder, listed in Flux Sharp Sources of the NW World Config. The FL# Script component puts it on an object of the scene: one component per script, as many as you like on one object.
What makes a script
- A class derived from
FluxScript, not abstract, not generic, public (or nested in a class without being private). An abstract or generic class can be the base of your scripts. - A public constructor without parameters: the scene creates the script. Without it,
fluxcstops withFL# script MyWorld.Door needs a public constructor without parameters: the scene creates it. - Callbacks written
protected override.void Update()written as in Unity would never be called, sofluxcrefuses it:error CS0114: 'Door.Update()' hides inherited member 'FluxScript.Update()'.
using NodeWorld.Flux;
namespace MyWorld
{
public class Spinner : FluxScript
{
public float degreesPerSecond = 45f;
protected override void Update()
{
transform.Rotate(new Vector3(0f, degreesPerSecond * Time.deltaTime, 0f));
}
}
}Callbacks
In the order of Unity's MonoBehaviour:
| Callback | When |
|---|---|
Awake() | The script is created, its fields already set from the scene. Every script of the scene is created and set before the first Awake, so a field may name a script created after it. Awake runs on an inactive object too. |
OnEnable() | Its object becomes active in the hierarchy, and right after Awake when it is active at load. |
Start() | Before its first Update. |
FixedUpdate() | At each physics step (Time.fixedDeltaTime). |
Update() | Each frame. |
LateUpdate() | Each frame, after every Update, the coroutines and the async continuations. |
OnBeforeRender() | Just before the frame is drawn (a mirror renders its reflection here). |
OnDisable() | Its object becomes inactive: no Start, Update, LateUpdate, FixedUpdate nor OnBeforeRender until it is active again. |
OnDestroy() | Its object is destroyed, or the world unloads. |
enabled = false stops the Update, LateUpdate, FixedUpdate and OnBeforeRender of the script; its events still come.
The events have their pages: using and grabbing objects in interaction and input, triggers and collisions in physics, players joining, leaving and respawning in players, ownership and synced state in synced objects and values, messages in network events.
Fields set from the scene
The FL# Script component sets the public fields of the script before Awake. Click Read the scripts on it: the SDK compiles the world's scripts once, lists their classes under Script and shows the fields of the one you pick. A field you leave alone says script default (the value your code gives it); Set gives it a value of the scene, Reset takes it back.
A field is set from the scene when it is a public instance field, not static, const or readonly, of one of these types, or a one-dimensional array of them:
| Kind | Types |
|---|---|
| Values | bool, int, long, float, double, string, an enum |
| Vectors | Vector2, Vector3, Vector4, Quaternion, Color |
| Objects | GameObject, and another FL# script class of the world |
| Components | Transform, RectTransform, Rigidbody, Collider, BoxCollider, SphereCollider, Renderer, LineRenderer, TrailRenderer, MeshFilter, Camera, Light, AudioSource, ParticleSystem, Animator, LODGroup, ReflectionProbe, ParentConstraint, Volume, Canvas, CanvasGroup, Text, Image, Button, Slider, Toggle, Dropdown, InputField, ScrollRect, Scrollbar |
| Assets | AudioClip, Material, Texture, Sprite, Mesh |
A field of another type keeps the value your code gives it. A value saved in the scene that no longer fits the field (you changed its type in the script) is left out, and the log says so: 'Door': the value of MyWorld.Door.openAngle is a String, the field is a float: not set.
Where a script runs
Each player's game runs the world's scripts for itself, and the server runs them too, on its own copy of the scene. World.isServer says where the code runs.
| Players' games | Server | |
|---|---|---|
| A script without attribute | yes | yes |
[ClientOnly] | yes | no |
[ServerOnly] | no | yes |
A class cannot have both attributes (fluxc: cannot be [ClientOnly] and [ServerOnly]). The server has no physics, no rendering, no local player and no input: mark [ClientOnly] a script that only draws, plays sound or reads the player, and see what runs on the server.
In Play mode, the scripts run once, as in a player's game, with you alone in the room: you are the master, and [ServerOnly] scripts are not created.
Scripts that use each other
GetScript<T>()gives the script of classTon the same object (the first one), ornull;gameObject.GetScripts<T>()all of them;gameObject.GetScriptsInChildren<T>()those of the object and its children.- A field typed as another script class (
public Scoreboard board;) is set from the scene: drop the object that carries that script.
When a script fails
An exception thrown out of a callback stops that script alone: it gets no more callbacks and its coroutines stop. The other scripts go on. The log says which one, where and why:
[FL# Tavern] FL# script MyWorld.Door on Door stopped in Update: System.InvalidOperationException: <its message>A call the game refuses (a wrong value, something your world may not do) does nothing, returns 0, false or null, and the script goes on; the log says it once: FL# host refused a script call (ignored, the scripts go on): <reason>. Where to read these lines: logs of your scripts.
