Instantiate / Destroy

Creating and destroying networked objects.

Prefabs

Instantiated objects are basically the same as synchronized objects placed on the scene during development. They are, as the name suggests, spawned at runtime. Thus they have one extra requirement: they have to be placed in prefabs with an ElympicsBehaviour as the root GameObject.

Prefab Example

Instantiate

ElympicsInstantiate

The only way to spawn synchronized prefab is to use ElympicsMonoBehaviour.ElympicsInstantiate.

This method has 2 parameters:

  • pathInResources: path to prefab in Resources directory e.g. "BlueBall"
  • player: predictable for player or ownership
    • ElympicsPlayer.World - only server can spawn with this option and it means it won’t be predictable to any player - useful for random server events
    • ElympicsPlayer.All - object predictable for all players, can be spawned by any player - useful for fully predictable psychics props
    • ElympicsPlayer.FromIndex(i) - object predictable for specific player, can be spawned by this specific player or server - useful for projectiles created by player

NetworkId

Objects created using ElympicsInstantiate have their NetworkIds assigned using formula:

var networkId = (playerIndex + 4) * 10 000 000 + i;

where i means index of instantiated object increased with every new object.

This means that all instantiated objects have these NetworkId ranges:

  • for All players - [10 000 000; 19 999 999]
  • for World player - [20 000 000; 29 999 999]
  • for Player 0 - [40 000 000; 49 999 999]
  • etc.

Destroy

Self destroy

The easiest way to destroy an object instantiated at runtime is to do this from a script within that object. So this object should have a script attached to it similar to:

private readonly ElympicsInt _ticksAlive = new ElympicsInt();

public void ElympicsUpdate()
{
	if (!IsPredictableForMe)
		return;

	_ticksAlive.Value++;
	if (_ticksAlive > 60)
		ElympicsDestroy(gameObject);
}

From another object

Another way to destroy an instantiated object is to save its reference and destroy it from the outside of this object.

private readonly ElympicsInt        _tick = new ElympicsInt(0);
private readonly ElympicsGameObject _cube = new ElympicsGameObject(null);

public void ElympicsUpdate()
{
	if (!IsPredictableForMe)
		return;

	_tick.Value++;
	var tickPeriod = _tick.Value % 200;
	if (tickPeriod == 80) // or (tickPeriod >= 80 && tickPeriod <= 199 && ReferenceEquals(_cube.Value, null))
		_cube.Value = ElympicsInstantiate("Cube", ElympicsPlayer.All).GetComponent<ElympicsBehaviour>();

	if (tickPeriod == 199 && !ReferenceEquals(_cube.Value, null))
	{
		ElympicsDestroy(_cube.Value.gameObject);
		_cube.Value = null;
	}
}

ElympicsFactory

How do objects instantiated at runtime on the server appear on the clients?

There is an alternative to ElympicsBehaviour designed for this: ElympicsFactory. ElympicsFactory is split internally into parts. Each part for each player - World, All, 0, 1 etc.

Each part contains information about instantiated objects and is predictable to corresponding players. Thus each player can predict the state of their factory part and check if their prediction was successful.

Other parts that are not predictable are just simply deserialized and proper objects are instantiated.

Coding principles

These are the most important rules for instantiation programming and should always be followed!

Deal only with your objects

As mentioned earlier, clients should only instantiate objects they desire to use or interact with and destroy the ones created by themselves.

This applies also to the server. There are some special cases when server should also instantiate or destroy objects intended to be used by players. For example a special bonus weapon for a specific player (with PredictableFor or ownership set for this player), intended to be used for some specific time duration.