MigrationGuidePart02SessionsIdentityAndStateSync

How connecting, joining a session, and declaring a networked identity map onto Alteruna's Connect/Room/CommunicationBridgeUID model.

Sessions and connection

All of these frameworks separate "get on the network" from "get into a session together". Alteruna keeps that split too: Connect() reaches Alteruna's relay/matchmaking service, then CreateRoom() or JoinRoom() puts you in a session - closer to Photon's connect-then-join-room flow than to Fusion's or Netcode's single call that starts a NetworkRunner/NetworkManager and joins a session in one step. One difference from all of them: MultiplayerManager connects automatically on start by default (the ConnectOnStart option), so you usually don't call Connect() yourself at all - it's only there for when you've turned that off.

The recommended way to get into a room is the RoomMenu prefab (see User Guide Part 05), rather than hand-rolling this. Its Start button is a useful pattern to know regardless: if you're connected to Alteruna's service, create a room there; if not (offline, unregistered, LAN-only build), fall back to hosting locally instead of failing outright.

C#
if (multiplayer.IsConnected)
{
    multiplayer.CreateRoom();
}
else
{
    multiplayer.Host();
}

Session and player events move from interface overrides (PUN 2), C# events (Netcode, FishNet), or NetworkRunner callbacks (Fusion) onto UnityEvent listeners on MultiplayerManager:

C#
multiplayer.OnRoomJoined.AddListener(e => { });
multiplayer.OnOtherUserJoined.AddListener(e => { });
multiplayer.OnOtherUserLeft.AddListener(e => { });
multiplayer.OnRoomLeft.AddListener(e => { });

See User Guide Part 03 for what a User and a Room are in Alteruna terms.

Networked identity

PhotonView (PUN 2) and NetworkObject (Fusion, Netcode, FishNet) do double duty: a stable network ID plus a slot for behaviours that opt into replication. Alteruna splits that into a base identity, CommunicationBridgeUID, and two ways to attach data to it:

  • AttributesSync - the PhotonView-in-a-script equivalent. Inherit it, mark members with [SynchronizableField]/[SynchronizableMethod], done.
  • Synchronizable - lower level, for when you want to hand-write the byte stream yourself (the IPunObservable equivalent), overriding AssembleData/DisassembleData and calling Commit() on your own schedule. See Developer Guide Part 01 for a full walkthrough.
  • Avatar - the player-representing object specifically. A CommunicationBridge that additionally tracks who possesses it, which is where ownership questions actually live (see Part 04).

State synchronization

The closest thing to a one-line swap in this whole guide: mark a field, stop writing serialization glue. Pick a framework to compare how it replicates a Health value:

C#
[SynchronizableField]
public float Health = 100f;
C#
public float Health;

public void OnPhotonSerializeView(PhotonStream s, PhotonMessageInfo i)
{
    if (s.IsWriting) s.SendNext(Health);
    else Health = (float)s.ReceiveNext();
}
C#
[Networked]
public float Health { get; set; } = 100f;
C#
public NetworkVariable<float> Health = new(100f);
C#
readonly SyncVar<float> _health = new(100f);

On AttributesSync, the base LateUpdate diffs marked fields against their last-sent value and commits automatically - you don't call Commit() yourself unless you've hidden LateUpdate. For byte-level control over what goes on the wire (bit-packing, delta-compressing a large struct), drop to a hand-written Synchronizable instead.



← Back | Next →

See Also