đC# Important Guide
Documents important standards on writing reusable code for LIMEN
Delay Invoke Until a Variable is Set
Due to network execution order, SyncVars
in managers would update first before OnStartClient
, OnStartServer
, and OnStartLocalPlayer
are called. This creates dependency issues, such as for the Player.LocalPlayer
static field is set in Player's OnStartLocalPlayer
, yet a SyncVar
hook may need its reference to perform some actions.
// This SyncVar hook will be called when Player.LocalPlayer is not available
// for late joiners
[SyncVar(hook = nameof(HookGameStateChanged))]
private GameState mGameState = GameState.Discover_HostMachine;
The naive approach would be to start a coroutine and yield till the reference is set, but that can get messy, starting so many coroutines for each variable, as well as dealing with canceling the previously started coroutine when a new one should start.
Thus, for variables that needed to be waited for reference before a function can be invoked, we have provided an extension method InvokeAfterVariableIsSet
in MonoBehaviourExtensions.cs
// Called when SyncVar mGameState is updated to a different value
protected void HookGameStateChanged(GameState oldVar, GameState newVar)
{
// Use a named delegate function instead of creating an anonymous Action (e.g., Action mAction = () => {...}).
// This prevents creating a new Action instance each time, which would cause multiple instances of the same function to be added to the dictionary.
// By using a named delegate, we ensure only the latest invocation is stored, avoiding duplicate calls.
void delegateToInvoke()
{
Player.LocalPlayer.GetComponent<PlayerObjectiveDisplay>().SetObjectiveDisplay(mGameState.ToString(), mGameState.ToString() + LEAN_BODY_ENDING);
}
this.InvokeAfterVariableIsSet(delegateToInvoke, () => Player.LocalPlayer);
}
Constants & Const Fields (No Magic Number)
For constant variables, avoid using magic number and make them const
. const
is static
thus public const
can be accessed in other scripts as well, so do not use static
.
public class Player : NetworkBehaviour
{
#region Const Defines
// Here, HEALTH_MAX can be accessed by Player.HEALTH_MAX
// And more optimized than using static int
public const int HEALTH_MAX = 100;
#endregion
}
OnValidate() For Validation Only
Use MonoBehaviour.OnValidate()
to validate important fields, such as checking if tag and layer are set to Door
for GameObjects with the Door.cs
script attached, as InteractionDetection
expects that tag and layer.
OnValidate()
should not set values directly as those are lost; we want to warn setup problems to correct them in the scene file manually.
Last updated