Simulation Behaviour
Overview
SimulationBehaviour
is the base class for NetworkBehaviour
and can be used to have safe access to Fusion's update
methods like FixedUpdateNetwork
, Render
and such without the need for a NetworkObject
.
SimulationBehaviour
can not have any networked properties and are not meant to be used along with NetworkObject
.
They need to be registered manually on the NetworkRunner
using NetworkRunner.AddGlobal()
. Registering is not needed for SimulationBehaviours
that are on the same GameObject
as the NetworkRunner.
Register/Unregister SimulationBehaviours
A SimulationBehavior
that is not attached to the same GameObject
as the NetworkRunner
must be registered manually.
A safe way of doing this is to use the NetworkRunner.GetRunnerForGameObject()
method to find the correct runner reference, as shown below.
C#
public void RegisterOnRunner() {
// Find the network runner for this gameobject scene. This is useful on a scene object.
var runner = NetworkRunner.GetRunnerForGameObject(gameObject);
// Make sure the network runner is started and running.
if (runner.IsRunning) {
runner.AddGlobal(this);
}
}
public void RemoveFromRunner() {
// The same process can be done to remove the SimulationBehaviour.
var runner = NetworkRunner.GetRunnerForGameObject(gameObject);
if (runner.IsRunning) {
runner.RemoveGlobal(this);
}
}
Example of use
A SimulationBehavior
can be used to access Fusion's internal logic, but they cannot have networked properties and are
not synchronized with other peers. It is perfect for scenarios like an item or power-up spawner on an authoritative
server game where clients should not be aware of the spawn logic, but only need to replicate the spawned power-up or item itself.
Here is an example of a power up spawner using a SimulationBehaviour
:
C#
public class BasicPowerUpSpawner : SimulationBehaviour {
// Local list of prefabs for the available power ups to be spawned.
[SerializeField] private List<NetworkPrefabRef> _availablePowerUps = new List<NetworkPrefabRef>();
private float _spawnDelay = 3f;
public void RegisterOnRunner() {
// Find the network runner for this gameobject scene. This is useful on a scene object.
var runner = NetworkRunner.GetRunnerForGameObject(gameObject);
// Make sure the network runner is started and running.
if (runner.IsRunning) {
runner.AddGlobal(this);
}
}
public void RemoveFromRunner() {
// The same process can be done to remove the SimulationBehaviour.
var runner = NetworkRunner.GetRunnerForGameObject(gameObject);
if (runner.IsRunning) {
runner.RemoveGlobal(this);
}
}
public override void FixedUpdateNetwork() {
if (Runner.Tick % Mathf.RoundToInt(Runner.TickRate * _spawnDelay) == 0) {
// Generate a random index to select a power up from the list.
int randomIndex = Random.Range(0, _availablePowerUps.Count);
// Spawn the selected power up.
Runner.Spawn(_availablePowerUps[randomIndex]);
}
}
}
Note that this script does not register itself on the NetworkRunner
, but it does have the register method that needs to be called on demand. The list of available Power Ups is a local list that is only important to the host/server instance,
but the spawned Power Ups NetworkObjects
will be correctly replicated to all clients without them needing to know about the spawning logic.