Skip to main content

2D Space Shooter Sample

The 2D Space Shooter Project provides examples of physics, player health, and status effects using Unity MLAPI. Technical features include NetworkVariable and ObjectPooling.

Server Authorative Physics Movement#

The movement in 2DSpaceShooter is physics based. The player object is a dynamic rigidbody and can collide with other players or asteroids. Physics in multiplayer games can be hard to get right. For simplicity, 2DSpaceShooter runs all movement and physics just on the server-side.

The client sends inputs in the form of RPCs to the server. The server then uses those inputs to adjust the throttle and turn values of the player.

This method of running physics makes sure that there are no desyncs or other physics issues between the client and server, but it introduces more latency. With future prediction support of MLAPI, the latency will no longer be an issue which makes this the best choice of a movement model for a game like this.

Player Health#

2DSpaceShooter uses NetworkVariables to track the players health and energy. Both variables are server authorative, only the host or server can make changes to them. The client draws the player's health bar simply by accessing the value of the NetworkVariable.

For example:

See full example on GitHub

Power-ups and Status Effects#

The 2DSpaceShooter sample has power-ups which apply different status effects to a player on collection. The core implementation of the power up effects in ShipControl.cs is very simplistic.

The power-ups themselves are server authorative. On the server they check if a player has entered their trigger and then apply a timed status effect to that player and disappear.

The ShipControl.cs of the player object tracks each status effect. NetworkVariables are used as duration timers to control the beginning and end of status effects. You could also use regular floats for timers. By using NetworkVariables, the client could use this information to display different graphics based on active buffs to players. Such as double shot and triple shot effects.

See full example on GitHub

NetworkObject Pooling#

The 2DSpaceShooter object creates many objects dynamically at runtime including bullets, asteroids, and pickups. 2DSpaceShooter uses object pooling to avoid performance issues of instantiating and destroying Unity Objects all the time and creating allocations in the process.

2DSpaceShooter uses the NetworkObjectPool script, which can be found in the Community Contributions Repository.

pool img

All of the runtime spawnable objects have been registered to the pool. On the client-side, this will cause MLAPI to use an object from the pool instead of instantiating a new Object. When the NetworkObject is despawned, it will be automatically be returned to the pool instead of getting destroyed.

Adding the NetworkObjectPool to the scene will not yet pool server objects because these must be manually created and then spawned by the user. Instead of instantiating objects, your code should take them from the pool.

Regular MLAPI Spawn Code example:

GameObject powerUp = Instantiate(m_PowerupPrefab);
powerUp.GetComponent<NetworkObject>().Spawn(null, true);

Pooled MLAPI Spawn Code example:

GameObject powerUp = m_ObjectPool.GetNetworkObject(m_PowerupPrefab);
powerUp.GetComponent<NetworkObject>().Spawn(null, true);

If you are using Unity 2021, you can use the built-in Object Pooling API instead to build your own object pools.