Skip to main content

Instantiate / Destroy

Requirements

Instantiated game objects are basically the same as synchronized objects placed on the scene during development, but because they are spawned at runtime, they have to be placed in prefabs with the ElympicsBehaviour component attached to the root GameObject and stored inside the Resources directory.

Prefab Example

Instantiate

ElympicsInstantiate

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

This method has 2 parameters:

  • pathInResources: path to a prefab in Resources directory e.g. "BlueBall"
  • player: instantiated object will be predictable for this player (can be used for simulating ownership)
    • ElympicsPlayer.World - only the 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 physics objects
    • ElympicsPlayer.FromIndex(i) - object predictable for a specific player, can be spawned by this specific player or the server - useful for projectiles created by players
info

The path from pathInResources parameter is case insensitive and must not contain a file extension.

ElympicsInstantiate returns an object of type GameObject and there is currently no generic override of the method available. To get a specific component from an object spawned this way, simply use Unity's GetComponent method, like in the example below.

// spawns "BlueBall" every 100 ticks
private readonly ElympicsInt _tick = new ElympicsInt(0);

public void ElympicsUpdate()
{
_tick.Value++;
var tickPeriod = _tick.Value % 100;
if (tickPeriod == 99)
{
GameObject prefabInstance = ElympicsInstantiate("BlueBall", ElympicsPlayer.All);
CustomScript custom = prefabInstance.GetComponent<CustomScript>();
custom.CustomMethod();
}
}

NetworkId

An object created using ElympicsInstantiate method has its NetworkId assigned using the following formula:

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

where i is the index of the instantiated object increased with every new object.

This means that all instantiated objects have the following 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.
Player limit

Number of players is limited to 196, which means the maximal possible network ID for an instantiated object is 1 999 999 999. This may change in the future releases.

info

ElympicsUpdate and other callbacks are called in a deterministic order of increasing NetworkId. Scripts attached to objects instantiated at runtime will be executed at the end of the game loop. Learn more.

Destroy

To destroy a game object spawned with ElympicsMonoBehaviour.ElympicsInstantiate, simply call ElympicsMonoBehaviour.ElympicsDestroy and pass that object as an argument. ElympicsDestroy can be called from any code, as long as it is a part of IUpdatable.ElympicsUpdate or IInitializable.Initialize.

private readonly ElympicsInt _ticksAlive = new ElympicsInt(0);

public void ElympicsUpdate()
{
_ticksAlive.Value++;
if (_ticksAlive.Value > 60)
ElympicsDestroy(gameObject);
}

Prediction

Spawning and destroying objects modifies the state of the game. This means, that those operations must follow the server authoritative approach. As a result, both ElympicsInstantiate and ElympicsDestroy always has to be called on the server.

Calling those methods on a client is only possible in games with prediction enabled. Any attempt to spawn or destory objects on a client for which they are not predictable will result in an exception. If a call to ElympicsInstantiate or ElympicsDestroy for an object which is predictable for the given client does not happen in the same tick on both client and server, reconciliation will be triggered once the client receives a snapshot for that tick.

Predictable Instantiate/Destroy

If you want spawning and destroying objects in your game to take advantage of prediction, you can ensure it always happens in the same tick on both server and client by using inputs. You can also send a player-to-server RPC in the same tick in which you call ElympicsInstantiate or ElympicsDestroy on a client.