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). Then load the
Launch scene and press
|1.1.5||Mar 02, 2023||Fusion Asteroids Host Advanced 1.1.5 Build 107|
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
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
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,
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).
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
NetworkBehaviour with a few new properties and a new callback that is called once an object has been migrated (aptly named
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
Migrated, but do remember to call
base.Migrated from you overridden implementation.
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:
- The networked state (a struct implementing
ISimpleState) which is a special
INetworkStructcontaining everything that needs to be synchronized across the network. In this sample this is the
- A MonoBehaviour implementing
ISimpleObjectwhich represents the state visually. In this sample, this is the
BulletBehaviour. Note that the
BulletBehaviouris not a
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.