This document is about: FUSION 1
SWITCH TO

Asteroids Advanced

Level 4

Overview

This sample uses the HostMode topology.

The Fusion Asteroids Advanced sample is a remake of the original PUN Asteroids demo in with Unity 2021.3 for PC (Windows), using some of the more advanced features of Fusion:

  • Host Migration: When the host leaves the session, the ownership of NetworkObjects is transferred to one of the remaining clients.
  • Addressables: The spaceship and the main game scene are both addressables.
  • Lag Compensation: Bullets are using lagcompensated raycasts to check collision with asteroids.
  • Custom GameObject Handling: Bullets are not NetworkObjects, but uses a simpler networked struct to manage their state and a custom manager to associate that state with local game objects.
  • Custom SceneManager: Specifically needed to handle addressables.

Before You Start

To run the sample, first create a Fusion AppId in the PhotonEngine Dashboard and paste it into the App Id Fusion field in Real Time Settings (reachable from the Fusion menu).

This example is using Unity's addressable assets, so you need to build those before you can launch the sample:

Go to Window | AssetManagement | Addressables | Groups to open the asset management window for addressables.

Then find the Build button and select New Build | Default Build Script

When the build completes you can load the Launch scene and press Play.

Download

Version Release Date Download
1.1.10 Sep 11, 2024 Fusion Asteroids Host Advanced 1.1.10 Build 654

Application Flow

The AsteroidsAdvanced-Menu scene allow the player to either host a game or join a running session with another host. Once the session has started, an instance of AsteroidsGame is instantiated and the AsteroidsAdvanced-Game scene is loaded. The clients will then wait for the host to start the game.

This initial setup is entirely handled by the code in the Menu folder.

AsteroidsGame is only responsible for the core session handling. It does not create any additional network state or objects, instead the loaded map contains a GameStateController that manages the game loop and spawns the required objects - specifically player space ships and asteroids, though the latter is delegated to the AsteroidSpawner.

While the game is running, SpaceshipController takes care of collecting input from the player and of predicting/applying that input in FixedUpdateNetwork. Each spaceship also maintains its own list of bullets as an array of "simple" network objects and associated local GameObjects in a SimpleObjectCollection.

When the time runs out or a player dies 3 times, the game ends and whoever has more points wins. Arguably an odd form of gameplay since a leading player can win by flying into an asteroid, but that's not the point of this example.

In the event that the host disconnects, the MigrationManager takes over and initiates the host migration process. Essentially, this allow a former client to become the new host and obtain a previously saved network snapshot from which it can restore selective parts of the original game state. In this example, SpaceShipController and GameStateController instances are restored since only these two derive from MigrationBehaviour (Note that this is a convention used specifically in this sample, not a general Fusion feature).

MigrationManager

Host Migration is a Fusion feature that allow a client to inherit the hosting responsibilities for a network session when the original host leaves. The MigrationManager attempts to simplify this process by introducing a few limitations and conventions.

Specifically, in order for a NetworkObject to be migrated to a new host, it must have exactly one component that derives from MigrationBehaviour.

MigrationBehaviour extends NetworkBehaviour with a few new properties and a new callback that is called once an object has been migrated (aptly named Migrated).

An object is "migrated" when it has been spawned again and had its state restored, but also, maybe more importantly, the player who originally had input authority of the object has re-connected to the new migrated session and is once again in control of the object.

The primary thing to remember when using the MigrationManager is that objects that gets migrated are re-spawned well ahead of their input authority re-connecting, so you generally want to delay activation of the migrated object until Migrated has been called.

To simplify this, the default implementation if MigrationBehaviour is to disable the game object in Spawned if a migration is pending, but call Migrated immediately if not. The default implementation of Migrated will then enable the game object.

As a consequence, most derived classes can just move their code from Spawned to Migrated, but do remember to call base.Migrated from you overridden implementation.

SimpleObjectCollection

The SimpleObjectCollection is a lightweight wrapper for networked objects that does not need to be individually identified on the network and thus does not require a full NetworkObject for each local game object.

The collection has two parts:

  1. The networked state (a struct implementing ISimpleState) which is a special INetworkStruct containing everything that needs to be synchronized across the network. In this sample this is the BulletState.
  2. A MonoBehaviour implementing ISimpleObject which represents the state visually. In this sample, this is the BulletBehaviour. Note that the BulletBehaviour is not a NetworkBehaviour

The SimpleObjectCollection will call SimpleFixedUpdateNetwork on the state struct to advance the state from one tick to the next and it will call SimpleRender on the mono behaviour to update the visual.

The render method differs a bit from the one used by a common NetworkBehaviour in that it provides two copies of the state and a normalized offset between the two that should represent the interpolated values. If you want snapshot accuracy, just use the to value and ignore the rest.

Back to top