Multiplayer Is Easy

Make your Unity game multiplayer by ticking the fields you want to synchronize. Version 1.0.0.

Overview

Multiplayer is easy works like Save is easy: add a MultiplayerIsEasyComponent to a GameObject and, in its inspector, tick the fields of its components that must be the same in every computer (the position, the health of the player, the color, a list of scores...). The asset sends the changes through the network, moves the objects smoothly, creates and destroys them in every computer and lets you call methods in other computers (RPCs). There are no special variable types: your scripts keep using normal fields.

  • A player ready to use in one click: GameObject > Multiplayer is easy > Player.
  • Host (server and player at the same time), dedicated server and client, over UDP with its own reliable protocol.
  • Select fields of your scripts and of Unity components (Transform, Rigidbody, Light, ...), including lists, dictionaries and [Serializable] classes.
  • Server authority or owner authority per object, with interpolation of the movement.
  • Player prefab, network prefabs, objects of the scene, RPCs, hooks, scene changes, password, connection approval and network simulation.
  • Unity 6 (6000.0) or newer. Works with the Built-in Render Pipeline, URP and HDRP, Windows, Mac, Linux, Android and iOS. Source code of the HUD, the examples and the adapters is included.

Quick start

Two players moving in the same scene, without writing code:

  1. Open the first scene of your game and use GameObject > Multiplayer is easy > Player. It creates:
    • the Network Manager: a GameObject with the MultiplayerIsEasyManager and the MultiplayerIsEasyHUD (the buttons Host, Client and Server to test);
    • a Player prefab in Assets: a capsule with a MultiplayerIsEasyComponent (Authority Owner, so each player controls its own, with Transform/position and Transform/rotation ticked) and a MultiplayerIsEasyMovement (WASD or the arrows). It is the Player Prefab of the manager;
    • two Spawn Points.
    To use your own model, select it in the scene before using the menu: it becomes the player prefab and leaves the scene, because every player that joins gets its own copy.
  2. Save the scene and put it first in the scene list of the build (File > Build Profiles, Scene List).
  3. Test with two players: use Window > Multiplayer is easy > Test with two players (Multiplayer Play Mode). The first time it installs Multiplayer Play Mode, a free package of Unity (until then, in Unity 6.0 Window > Multiplayer only has Multiplayer Center), and opens its window: tick Player 2 and press Play. Press Host in one window and Client in the other. You can also make a build (File > Build And Run) and press Host in one copy and Client in the other (see Testing your game).

Then make it your game: tick more fields, add your scripts to the player, place network objects in the scene... A field of your script is synchronized when you tick it, the computer that controls the object changes it and the others receive it:

using MultiplayerIsEasy;
using UnityEngine;

public class Health : MultiplayerIsEasyBehaviour {

    public int Hp = 100;   // tick "Health/Hp" in the MultiplayerIsEasyComponent of the player

    public void TakeDamage(int damage) {
        if (HasAuthority)  // only the computer that controls this player changes it
            Hp -= damage;
    }
}

You don't need to write code to synchronize: whatever the computer with the authority writes in a ticked field appears in the other computers. Read the value of the field as usual.

To make the player by hand: add a MultiplayerIsEasyComponent to the root of a prefab (Add Component > Multiplayer is easy, the position and the rotation come ticked), set its Authority to Owner, move it only where HasAuthority is true (MultiplayerIsEasyMovement is a good start), drag the prefab to the Player Prefab of the manager and don't leave a copy in the scene. The inspector of the manager warns you, with a button to fix it, if the Player Prefab is missing something.

Examples

The folder Multiplayer is easy/Examples has two scenes. Open one, press Play, press Host, and start a second copy of the game as Client. When you press Play in an example scene you are asked to add the example scenes at the top of the scene list of the build, so you can make a build to test (remove them from the list before building your own game).

SceneWhat it shows
Example 1 - PlayersThe player prefab (ExamplePlayer) with owner authority: each player moves with WASD, changes its color with C (a field with a [SyncHook]) and says hello with E (an RPC that runs in every computer). The name comes from the HUD with ConnectionData.
Example 2 - CoinsServer authority: only the server creates coins (MultiplayerIsEasyAPI.Spawn), decides who takes them and despawns them. The Scoreboard is an object of the scene with two ticked fields (Scores and CoinsTaken) and an RPC that any client can call.

The examples use a small shader that works in every render pipeline. They work with the old Input Manager and with the new Input System.

How it works

  • Server: the computer that has the real state of the game. Everything goes through it.
  • Client: a player connected to the server. Each client has an id (1, 2, 3...). The server is the id 0 (MultiplayerIsEasyAPI.ServerClientId).
  • Host: a server that is also a player (client id 0). It is the easiest way to play: one player hosts, the others join. The host and the server are the same id, so an object owned by the host is owned by the server.
  • Network object: a GameObject with a MultiplayerIsEasyComponent. Each one has a NetworkId that is the same in every computer, an owner (a client id) and an authority (who changes its fields).

Thirty times per second (the Tick Rate) the computer with the authority of each object compares its ticked fields with the last values that were sent and sends only what changed. Fields are sent reliably and in order; the movement of the Transform is sent unreliably (the newest state replaces the old one) and the final position is always confirmed. The other computers show the object a little in the past (the Interpolation Delay, 0.1 s by default) so it moves smoothly between the states that arrive. Each state carries the time when its owner took it, and if the states of an object take longer to arrive (a slow network, or an object moved by another client, that goes through the server) the delay of that object grows automatically, so it keeps moving smoothly instead of stopping.

A client that joins late receives the whole game: every network object with the current values of its fields. All the objects are created before their values are applied, so a reference from one object to another one arrives too, whatever their order.

The manager

You need one MultiplayerIsEasyManager in the first scene of the game. By default it is kept when other scenes are loaded (and so the connection). Most of the time you use the static class MultiplayerIsEasyAPI instead of the component.

SettingDescription
Address / PortWhere the clients connect (an IP, a domain or localhost) and the UDP port of the server (7777 by default).
Max ClientsMaximum number of remote clients (the host is not counted).
PasswordIf it is not empty, the clients need the same password to join.
Tick RateTimes per second that changes are sent (30 by default).
TimeoutSeconds without receiving anything before a connection is closed.
Interpolation DelayMinimum seconds in the past that remote objects are shown (0.1 s, about three ticks, works well). On slower networks it grows automatically for each object.
Check Application VersionReject clients with a different Application.version (Project Settings > Player > Version).
Player PrefabCreated for every player that joins (and for the host), owned by that player. Optional. The inspector warns you, with a button to fix it, if it has no MultiplayerIsEasyComponent, if its Authority is Server (only the server could move the players) or if a copy of it was left in the scene.
Spawn PointsWhere the players are created, one after the other. If it is empty, or its points were destroyed with their scene, the MultiplayerIsEasySpawnPoint of the loaded scenes are used (the easiest option for games with several scenes).
Add All Network PrefabsOn by default: every prefab of the project that has a MultiplayerIsEasyComponent in its root can be created with Spawn, without adding it to a list. They are added when the game starts and in the builds; the prefabs of the examples only in the example scenes. It needs the manager in a scene of the build: for a manager created from a prefab, turn it off and use the list.
Network PrefabsThe prefabs that can be created with Spawn when Add All Network Prefabs is off. Press Find all network prefabs to add every prefab of the project that has a MultiplayerIsEasyComponent.
Keep Between ScenesKeep the manager and the connection when another scene is loaded (it uses DontDestroyOnLoad).
Run In BackgroundKeep running without focus (needed to test two windows in the same computer and for servers).
Auto StartStart as Host, Server or Client when the game starts (one frame after it, so the Start of your scripts runs first).
Server In Batch ModeA build started without graphics (-batchmode, a dedicated server) starts the server automatically.
Log LevelWhich messages of the asset are shown in the console.
Network SimulationLatency (ms), jitter (ms) and packet loss (%) to test a bad network. Only in the editor and in development builds.
EventsUnityEvents for Server Started/Stopped, Client Connected/Disconnected (server) and Connected/Disconnected (client), folded at the end of the inspector.

Below the settings, Test with two players installs or opens Multiplayer Play Mode. In Play mode the inspector of the manager shows the state of the network (ping, traffic, clients) and buttons to start and stop.

Every setting can also be changed from code before starting, for example from the menu of your game:

MultiplayerIsEasyManager manager = MultiplayerIsEasyManager.Instance;
manager.Address = addressField.text;
manager.Password = passwordField.text;         // the same as MultiplayerIsEasyAPI.Password
manager.MaxClients = 8;
manager.AddNetworkPrefab(bulletPrefab);
manager.SpawnPoints = new[] { spawnA, spawnB };
MultiplayerIsEasyAPI.StartHost();

When the scene of the manager is loaded again (for example to restart a round), the new copy of the manager destroys its GameObject (and the HUD on it): the manager that was kept between scenes stays, with its connection, and takes the Spawn Points of the loaded scene.

Selecting the fields

The inspector of the MultiplayerIsEasyComponent shows every component of its GameObject as a tree. Tick the fields that must be synchronized. Groups can be opened to tick only some of their fields, a closed group shows how many fields are ticked, and the ? next to a field explains it (move the mouse over it, or click it). The search box at the top filters the tree. When you add the component in the inspector, Transform/position and Transform/rotation come ticked. The colors: orange for [AlwaysSync], blue for the interpolated Transform values and purple for fields with a [SyncHook].

  • Transform: position, rotation and localScale. They are compressed, sent unreliably, interpolated and confirmed when the object stops. Tick only what changes: a coin that never moves after it is spawned needs nothing, because the position is sent with the spawn.
  • Your scripts: their fields (public and private) and their properties with get and set. Nested [Serializable] classes and structs are shown as groups, so you can tick a single field inside them.
  • Unity components: their public properties with get and set, for example Light/intensity, Rigidbody/linearVelocity or GameObject/active. The common ones are shown first and the rest inside More properties.

Other settings of the component:

SettingDescription
AuthorityServer: only the server changes the fields. Owner: the owner of the object changes them (the player that controls it). While the server owns it, it behaves like Server.
InterpolateMove remote objects smoothly between the received states. Without it they jump to each new state.
Use Local SpaceSynchronize the local position and rotation (relative to the parent) instead of the world ones.
Destroy With OwnerWhen the owner leaves, the object is despawned. If it is off, the server becomes the owner.
Kinematic When RemoteIn the computers without the authority the Rigidbody (or Rigidbody2D) is kinematic, so physics do not fight with the network.
Position / Rotation / Scale ThresholdSmaller changes are not sent.

The fields can also be chosen by code before the object is spawned: SetSynced("Player/Health", true), IsSynced(path) and SyncedFields. A path is the name of the component and the names of the fields separated by /, as the tree shows them: Transform/position, Player/Stats/Speed (a field inside a nested class) or GameObject/active (calls SetActive). A group selects all its fields, like its checkbox in the tree: Player/Stats or Player. In an editor script that changes a prefab, save it after (PrefabUtility.SavePrefabAsset, or EditorUtility.SetDirty on the component). If you rename a field or a component, the inspector shows the ticked fields that do not exist anymore.

Every computer must run the same build: the ticked fields and the RPCs of every network prefab are compared when a client connects, and a client with different ones is rejected (VersionMismatch). The message says which prefab is different.

What can be synchronized

  • Numbers (int, float, double, long, byte, ...), bool, char, string, enums (yours and Unity's, like KeyCode or LightType), DateTime, TimeSpan, Guid and nullable values.
  • Unity types: Vector2, Vector3, Vector4, Vector2Int, Vector3Int, Quaternion, Color, Color32, Rect, RectInt, Bounds, BoundsInt, LayerMask and Matrix4x4.
  • Arrays, List<T> and Dictionary<K, V> of those types, and classes and structs with [System.Serializable] (a list or a nested class is sent whole when something inside it changes).
  • References to network objects: a field of type GameObject or of a component, that points to an object with a MultiplayerIsEasyComponent that is spawned, arrives as a reference to the same object in the other computers. Each copy of a prefab is a different object in the network, so a reference points to the right copy. They also work in lists and as RPC parameters. A reference to an object that is not in the network arrives as null.

Assets (materials, textures, prefabs, ScriptableObjects), UnityEvents and delegates cannot be synchronized; the tree does not show them. Send an index or a name instead and look up the asset in each computer. Messages can be up to 4 MB (strings up to 1 MB).

Authority and ownership

Every network object has an owner: the server (id 0) or a client. The player prefab is owned by its player; objects spawned with Spawn are owned by the server unless you pass an owner. The server can give the object to another client at any moment:

MultiplayerIsEasyAPI.ChangeOwnership(door, clientId);   // or GetComponent<MultiplayerIsEasyComponent>().ChangeOwnership(clientId)
networkObject.RemoveOwnership();                       // back to the server

Use HasAuthority to know if this computer changes the fields of the object, and IsOwner to know if it belongs to this player. In the other computers a change you make to a ticked field is overwritten by the next value that arrives. A quick rule:

  • Owner authority: things a player controls directly (its character, its camera target, its car). Responsive, but the player could cheat.
  • Server authority: game rules (scores, health, doors, pickups, enemies). Clients ask the server with an RPC and the server changes the fields.

An object with Owner authority can still have fields that only the server changes (a score, the health, a team): mark them with [ServerAuthority]. The owner moves the object and changes the other ticked fields, and the server decides those:

public class Player : MultiplayerIsEasyBehaviour {
    public string Nickname;      // changed by the owner
    [ServerAuthority]
    public int Score;            // changed only by the server, a change made in the owner is overwritten
}

When the owner changes, the new owner continues from the last position and values it received, so the object does not jump back. When the server gives away an object it controls, its last changes arrive before the change of owner, and the updates that the old owner sent before it knew are ignored.

To move an object instantly (a respawn, a portal) without interpolation call networkObject.Teleport(position, rotation) in the computer with the authority.

Spawning objects

Only the server creates and destroys network objects; the clients create them automatically. With Add All Network Prefabs (on by default) any prefab with a MultiplayerIsEasyComponent in its root can be spawned. Without it the prefab must be in the Network Prefabs of the manager (or registered with MultiplayerIsEasyAPI.RegisterPrefab in every computer before starting).

if (MultiplayerIsEasyAPI.IsServer) {
    GameObject bullet = MultiplayerIsEasyAPI.Spawn(bulletPrefab, position, rotation);        // owned by the server
    GameObject pet = MultiplayerIsEasyAPI.Spawn(petPrefab, position, rotation, clientId);    // owned by a client
    MultiplayerIsEasyAPI.Despawn(bullet);                                                    // destroyed in every computer
}
  • The position and the values of the ticked fields at the moment of the spawn arrive with the object. To set them first, instantiate the prefab, change it and pass the instance: MultiplayerIsEasyAPI.Spawn(instance). Later changes are sent as normal updates.
  • Destroying a network object in the server (Destroy) despawns it in every computer. Destroying it in a client only removes it in that client.
  • Each prefab receives an id from the editor (shown in its inspector) when it is created or saved, also by a script. A copy of a prefab or a prefab variant receives its own id. The ids are checked again when you press Play, when you press Find all network prefabs and when you make a build.
  • The player prefab is spawned for every player when it joins, at the next spawn point, and despawned when it leaves (with Destroy With Owner). Get it with MultiplayerIsEasyAPI.LocalPlayer or GetPlayerObject(clientId).

Objects of the scene

A GameObject placed in a scene with a MultiplayerIsEasyComponent (a door, a scoreboard, a platform) is synchronized automatically when the game starts. The editor gives it a scene id when you add it, duplicate it, save the scene and make a build. All the computers must load the same scene. These objects are owned by the server.

RPCs

An RPC is a method that runs in other computers. Mark it with [MultiplayerRpc] and call it with SendRpc and the name of the method:

public class Door : MultiplayerIsEasyBehaviour {

    public bool Opened;   // ticked, changed only by the server

    public void Use() {
        SendRpc(nameof(RequestOpen), RpcTarget.Server);   // any client asks the server
    }

    [MultiplayerRpc(RequireOwnership = false)]
    private void RequestOpen(RpcInfo info) {
        Debug.Log("The client " + info.SenderClientId + " opened the door");
        Opened = true;   // runs in the server, the field reaches everybody
        SendRpc(nameof(PlaySound), RpcTarget.All, 0.8f);
    }

    [MultiplayerRpc]
    private void PlaySound(float volume) { /* ... */ }
}
TargetRuns inIn the caller
ServerOnly the server (or the host).Only if the caller is the server, at once.
AllThe server and every client.Yes, at once.
OthersThe server and every client except the caller.No.
OwnerThe owner of the object.Only if the caller is the owner, at once.
ClientsEvery client (and the host), not a dedicated server.Yes, at once (not in a dedicated server).
SendRpcToClient(method, clientId, ...)One client.Only if it is that client (the host is 0), at once.

When an RPC runs in the computer that calls it, it runs at once, inside SendRpc. The other computers run it when it arrives.

  • The parameters can be any type that can be synchronized. An optional last parameter of type RpcInfo tells who sent it.
  • By default only the owner of the object can call its RPCs (RequireOwnership = true); the server can always call them. Use RequireOwnership = false for requests that any client can make, and check them in the server.
  • Reliable = false sends it unreliably (it can be lost, good for effects that are sent often). It must fit in one packet (about 1 KB).
  • From any MonoBehaviour use the extension this.SendRpc(...) or MultiplayerIsEasyAPI.SendRpc(this, ...). The script must be on a GameObject with a MultiplayerIsEasyComponent that is spawned. RPCs cannot have overloads, ref or out parameters.

Attributes

AttributeUse
[SyncHook(nameof(Method))]On a ticked field: the method is called in the computers that receive a new value. It can have no parameters, one (the new value) or two (the old and the new value). It is not called in the computer that made the change.
[AlwaysSync]The field is always synchronized, without ticking it (useful in reusable scripts and adapters).
[ServerAuthority]On a field of an object with Owner authority: only the server changes it (see Authority). The tree shows it with "(server)".
[AvoidSync]On a field, a property or a class: it is not shown in the tree and is never synchronized.
[MultiplayerRpc]Makes a method an RPC (see RPCs).
[SyncHook(nameof(OnHealthChanged))]
public int Health = 100;

void OnHealthChanged(int oldValue, int newValue) {
    healthBar.fillAmount = newValue / 100f;
}

Events

Scripts on a network object can derive from MultiplayerIsEasyBehaviour (or implement IMultiplayerIsEasyEvents) to receive:

  • OnNetworkSpawn(): the object is in the network, IsOwner, HasAuthority and NetworkId are valid and the ticked fields already have the values that arrived with it (their [SyncHook] methods run just before). In a client that joins, it runs when the whole game has arrived: the references to other network objects already point to them.
  • OnNetworkDespawn(): the object leaves the network (despawned, the scene changes or the connection stops). IsOwner and HasAuthority still tell what it was, for example to give back the camera.
  • OnOwnershipChanged(previous, current).

MultiplayerIsEasyBehaviour also has IsServer, IsClient, IsHost, IsOwner, HasAuthority, OwnerId and SendRpc.

Global events of MultiplayerIsEasyAPI:

MultiplayerIsEasyAPI.OnServerStarted += () => { };
MultiplayerIsEasyAPI.OnClientConnected += clientId => { };      // in the server, also for the host (0)
MultiplayerIsEasyAPI.OnClientDisconnected += clientId => { };
MultiplayerIsEasyAPI.OnConnected += () => { };                  // in the client (and the host), the game is ready
MultiplayerIsEasyAPI.OnDisconnected += reason => { };           // DisconnectReason: Timeout, WrongPassword, ServerFull, Kicked...
MultiplayerIsEasyAPI.OnSceneLoaded += sceneName => { };

OnClientConnected is called when the client already has the game: its player object exists (GetPlayerObject(clientId)) and the RPCs you send to it arrive. In OnDisconnected, MultiplayerIsEasyAPI.DisconnectMessage has the text that came with it, for example the reason of a rejection.

Subscribe before the network starts. Auto Start, the command line and Server In Batch Mode start it one frame after the scene starts, so subscribing in Awake, OnEnable or Start is enough. If your own script starts the network in its Start, subscribe in Awake or OnEnable.

Ready-made components

They are source code (in Multiplayer is easy/Movement and Multiplayer is easy/Adapters): use them as they are, change them or copy them as the start of your own scripts.

ComponentWhat it does
MultiplayerIsEasyMovementMoves the object with WASD or the arrows, only in the computer that controls it (HasAuthority); the other computers receive the position. Speed and Turn To Direction in the inspector. It works with the new Input System and with the old Input Manager. The menu Player adds it to the player.
MultiplayerIsEasyAnimatorAdd it next to an Animator of a network object: the float, int and bool parameters of the Animator are synchronized (the field Values has [AlwaysSync], nothing to tick), so the animations look the same in every computer. Change the parameters only in the computer with the authority. For triggers call GetComponent<MultiplayerIsEasyAnimator>().SetTrigger("Jump") instead of Animator.SetTrigger: it is sent to the other computers with an RPC. Float Damping smooths the received floats.
MultiplayerIsEasyHUDThe buttons Host, Client and Server, the address, the port, the name (ConnectionData) and the password, and the state of the network. It is added to the Network Manager; replace it with the menu of your game.

Changing the scene

The server changes the scene for everybody with MultiplayerIsEasyAPI.LoadScene("Level 2"). The clients load it automatically. The spawned objects are destroyed, the objects of the new scene are synchronized and the players are created again at the spawn points of the new scene. A client that joins later loads the scene of the server automatically. The scenes must be in the scene list of the build. Don't use SceneManager.LoadScene while connected.

Connection, password and approval

  • MultiplayerIsEasyAPI.StartClient("192.168.0.10", 7777) connects to an address; StartClient() uses the Address and Port of the manager.
  • MultiplayerIsEasyAPI.Password = "1234" before starting: the server asks for it and the client sends it. A client with another password is rejected with WrongPassword. The HUD has a field for it; the fields of the HUD that you don't edit show, and keep, what your code set in the manager (address, port, password and ConnectionData).
  • MultiplayerIsEasyAPI.ConnectionData = "Ana" before connecting sends a text to the server (a name, a token, a JSON...). The server reads it with MultiplayerIsEasyAPI.GetConnectionData(clientId); for the host (0) it is its own ConnectionData.
  • The server can decide who joins:
    MultiplayerIsEasyAPI.ConnectionApproval = request => {
        if (request.Data == "banned name") {
            request.RejectMessage = "You can not join.";
            return false;
        }
        return true;   // request.Address is the IP of the client
    };
  • The server can kick a client with DisconnectClient(clientId). The reason of a disconnection arrives in OnDisconnected, and the RejectMessage in MultiplayerIsEasyAPI.DisconnectMessage.

Testing your game

You need two copies of the game running at the same time:

  • Multiplayer Play Mode (Window > Multiplayer > Multiplayer Play Mode, package com.unity.multiplayer.playmode): runs up to four players from the editor without building. New projects don't have it: Window > Multiplayer is easy > Test with two players (or the button at the end of the inspector of the manager) installs it and opens its window. Tick Player 2, press Play, and press Host in one window and Client in the other.
  • A build and the editor: put your scene first in the scene list (File > Build Profiles), make a build (File > Build And Run), and press Host in one and Client in the other. Run In Background (on by default) keeps both running.
  • Command line: -mie-host, -mie-server, -mie-client, -mie-address 192.168.0.10 and -mie-port 7777 start the build automatically, for example MyGame.exe -mie-client -mie-address 127.0.0.1.
  • Network simulation: turn it on in the manager to add latency, jitter and packet loss and see how your game feels on a bad network.

In the same computer use the address 127.0.0.1. In a local network use the IP of the host (for example 192.168.0.10).

Builds and servers

  • Over the internet, the server (or the host) must be reachable: open the UDP port in its firewall and, at home, forward the port in the router to that computer. Players join with the public IP or a domain name.
  • A dedicated server is a build without graphics that starts the server automatically (Server In Batch Mode). The best way is the Dedicated Server build target of Unity (File > Build Profiles > Windows Server or Linux Server, a module that you install from the Unity Hub): it does not need a screen. A normal build started with -batchmode -nographics also works on most computers, but on a Linux server without a display use the Dedicated Server target. Use -mie-port to change the port.
  • The clients and the server must be the same build (same prefabs, ticked fields and RPCs). With Check Application Version the version must match too.
  • IL2CPP (iOS, Android, consoles): Unity removes the code that nobody calls, and the asset uses your fields, RPCs and hooks by reflection. The asset keeps them: it has a link.xml for its DLL and in each build it adds one with the components of your network prefabs and of the network objects of the scenes of the build. Objects made by code and registered with RegisterPrefab are not known in the build: with a Managed Stripping Level higher than Minimal add [UnityEngine.Scripting.Preserve] to their scripts.

API summary

MultiplayerIsEasyAPI
StartHost(), StartServer(), StartClient(), StartClient(address, port), Stop()Start and stop the network.
IsServer, IsClient, IsHost, IsRunning, IsConnecting, IsConnected, LocalClientIdState of this computer.
Spawn(prefab, [position, rotation], [owner]), Despawn(gameObject), ChangeOwnership(gameObject, clientId), RemoveOwnership(gameObject)Network objects (server).
GetNetworkObject(networkId), GetPlayerObject(clientId), LocalPlayer, ConnectedClientsFind objects and players (GetPlayerObject returns the GameObject, GetNetworkObject and LocalPlayer its MultiplayerIsEasyComponent).
SendRpc(script, method, target, args), SendRpcToClient(script, method, clientId, args)RPCs.
LoadScene(name), DisconnectClient(clientId), RegisterPrefab(prefab)Server tools.
Password, ConnectionData, GetConnectionData(clientId), ConnectionApproval, DisconnectMessageConnection.
ServerTime, StatisticsThe time of the server (the same in every computer) and the ping and traffic.
OnServerStarted, OnServerStopped, OnClientConnected, OnClientDisconnected, OnConnected, OnDisconnected, OnSceneLoadedEvents.
MultiplayerIsEasyComponent
NetworkId, IsSpawned, OwnerId, IsOwner, HasAuthority, IsSceneObject, IsPlayerObjectState of the object.
ChangeOwnership(clientId), RemoveOwnership(), Despawn(), Teleport(position, rotation)Actions.
SetSynced(path, synced), IsSynced(path), SyncedFieldsThe ticked fields.
Authority, Interpolate, DestroyWithOwner, thresholds...The settings of the inspector.

MultiplayerIsEasyManager.Instance has the settings of the inspector as properties (Address, Port, MaxClients, Password, TickRate, PlayerPrefab, AddNetworkPrefab, SpawnPoints, Timeout, InterpolationDelay, KeepBetweenScenes, RunInBackground, LogLevel, SimulateNetwork...). Every class and member has its documentation in the code editor (MultiplayerIsEasyDLL.xml).

Limitations

  • WebGL is not supported (browsers do not allow UDP).
  • There is no relay or NAT punch-through: the server must be reachable (see Builds and servers).
  • No client-side prediction or lag compensation: with owner authority the owner moves at once; with server authority the client sees the result after a round trip.
  • Every client receives every network object (there is no interest management). It is designed for small and medium games (up to about 16-32 players).
  • The parent of a network object is not synchronized; only the root of a prefab can be a network object (children can have ticked fields only through the components of the root).
  • Only one manager per game, and one MultiplayerIsEasyComponent per GameObject.

Troubleshooting

ProblemSolution
The client stays in "Connecting" and ends with ConnectionFailed.Check the address and the port, that the server is running and that the UDP port is open in its firewall. In the same computer use 127.0.0.1.
The client is rejected with VersionMismatch.The two builds are different (prefabs, ticked fields, RPCs or Application.version); the message says which prefab is different. Make a new build of both.
"The prefab is not in the Network Prefabs".Turn on Add All Network Prefabs in the manager, or add the prefab to its list.
The players do not move, or a player moves two capsules.Look at the inspector of the Network Manager: it warns if the Player Prefab has Server authority, if its position is not ticked or if a copy of it was left in the scene, with a button to fix it.
"The host could not start on the port...".Another program, or another copy of the game, is using the port. Stop it or use another port.
The build starts in another scene.Put your scene first in the scene list (File > Build Profiles).
A field does not change in the other computers.Is it ticked? Is it changed in the computer with the authority (HasAuthority)? A list or a class must be changed in place or replaced; both are detected.
A remote object shakes or lags.Make sure only the computer with the authority moves it (scripts, animations with root motion, physics). Raise the Interpolation Delay if the network loses packets.
The game freezes in the second window.Turn on Run In Background in the manager (and in Project Settings > Player).
An RPC does nothing.Check the console: the method needs [MultiplayerRpc], the object must be spawned, and by default only its owner can call it.

API reference

The public classes of the asset, in the MultiplayerIsEasy namespace.

MultiplayerIsEasyAPI

The main class of the asset: start and stop the game, create objects in the network, call RPCs and receive the events. It uses the MultiplayerIsEasyManager of the scene.

MultiplayerIsEasyAPI.StartHost();
MultiplayerIsEasyAPI.StartClient("192.168.0.10", 7777);
MultiplayerIsEasyAPI.Spawn(enemyPrefab, position, Quaternion.identity);

Properties

ConnectionApproval

Only in the server: decides if a client can join, after the password and the version were checked. Return false to reject it, set ConnectionRequest.RejectMessage to tell the client why. Set it before starting the server.

MultiplayerIsEasyAPI.ConnectionApproval = request => request.Data != "BannedPlayer";
ConnectionData

A text that the client sends to the server when it connects, for example the name of the player. The server reads it in MultiplayerIsEasyAPI.ConnectionApproval and with MultiplayerIsEasyAPI.GetConnectionData(System.Int32). Set it before connecting.

Manager

The manager of the game, null if there is no MultiplayerIsEasyManager in the scene.

Password

The password of the manager: in the server the clients need it to join, in a client it is the one that it sends. Set it before starting (for example from a text field of your menu).

IsConnecting

true while a client is connecting (before it receives the game).

DisconnectMessage

The text that came with the last disconnection of this client, for example the ConnectionRequest.RejectMessage of the MultiplayerIsEasyAPI.ConnectionApproval of the server. Read it in MultiplayerIsEasyAPI.OnDisconnected.

IsServer

true in the server and in the host.

IsClient

true in a client and in the host.

IsHost

true in the host (server and client at the same time).

IsRunning

true if the game was started (as host, server or client).

IsConnected

true if the server is running, or if the client finished joining the game.

LocalClientId

The id of the local game: 0 in the server and in the host, 1 or more in the clients, -1 if it is not connected.

ServerTime

The time of the server in seconds since it started, in the clients it is estimated. Useful to synchronize timers.

Statistics

Statistics of the network traffic (round trip time, bytes per second, ...).

ConnectedClients

Only in the server: the ids of the clients in the game, including the host (0).

LocalPlayer

The player object of the local game, null if it does not have one.

Methods

StartHost()

Starts the server and a local client at the same time.

Returns: false if it could not start.

StartServer()

Starts a dedicated server (without a local player).

Returns: false if it could not start.

StartClient()

Connects to the server with the address and port of the manager.

Returns: false if it could not start connecting.

StartClient(string address, int port)

Connects to a server.

address: An IP (for example 192.168.0.10), a domain name or "localhost".
port: The UDP port of the server.

Returns: false if it could not start connecting.

Stop()

Stops the server, the host or the client.

Spawn(GameObject prefabOrInstance, int ownerClientId)

Creates a network prefab in all the computers (only the server can do it). If it receives an instance of a network prefab that is in the scene, that object is spawned.

prefabOrInstance: A prefab of the Network Prefabs of the manager, or an instance of one.
ownerClientId: The id of the owner, 0 for the server.

Returns: The created object, null if it could not be spawned.

Spawn(GameObject prefab, Vector3 position, Quaternion rotation, int ownerClientId)

Creates a network prefab in all the computers at the position and rotation (only the server can do it).

prefab: A prefab of the Network Prefabs of the manager.
position: The position.
rotation: The rotation.
ownerClientId: The id of the owner, 0 for the server.

Returns: The created object, null if it could not be spawned.

Despawn(GameObject networkObject)

Removes an object from the network and destroys it in all the computers (only the server can do it). Destroying the object in the server with Destroy() does the same.

networkObject: An object with a MultiplayerIsEasyComponent.

RemoveOwnership(GameObject networkObject)

Gives a network object back to the server (only the server can do it). The same as ChangeOwnership(networkObject, 0).

networkObject: An object with a MultiplayerIsEasyComponent that is spawned.

ChangeOwnership(GameObject networkObject, int clientId)

Changes the owner of a network object (only the server can do it).

networkObject: An object with a MultiplayerIsEasyComponent that is spawned.
clientId: The id of the new owner, 0 for the server.

GetNetworkObject(uint networkId)

Finds a network object by its id.

networkId: The MultiplayerIsEasyComponent.NetworkId of the object.

Returns: The object, null if it does not exist.

GetPlayerObject(int clientId)

The player object of a client.

clientId: The id of the client, 0 for the host.

Returns: The player object, null if the client does not have one.

GetConnectionData(int clientId)

Only in the server: the MultiplayerIsEasyAPI.ConnectionData that a client sent when it connected.

clientId: The id of the client.

Returns: The text, empty if the client does not exist.

LoadScene(string sceneName)

Loads a scene in the server and in all the clients (only the server can do it). It must be in the scene list of the build.

sceneName: The name of the scene.

DisconnectClient(int clientId)

Disconnects a client (only the server can do it).

clientId: The id of the client.

RegisterPrefab(GameObject prefab)

Adds a prefab to the network prefabs from code. Call it before starting the game, in all the computers.

prefab: A prefab with a MultiplayerIsEasyComponent. It can also be an inactive object of the scene used as a template (for example an object made by code, with the same name in all the computers): the spawned objects are active copies of it.

SendRpc(MonoBehaviour behaviour, string method, RpcTarget target, object[] args)

Calls a method marked with MultiplayerRpcAttribute in other computers. The GameObject needs a MultiplayerIsEasyComponent.

behaviour: The script that has the method.
method: The name of the method, use nameof(MyMethod).
target: Where the method is executed.
args: The parameters of the method.

SendRpcToClient(MonoBehaviour behaviour, string method, int clientId, object[] args)

Calls a method marked with MultiplayerRpcAttribute only in one client. If that client is the caller (or the host calls it for 0), it runs at once.

behaviour: The script that has the method.
method: The name of the method, use nameof(MyMethod).
clientId: The id of the client, 0 for the host.
args: The parameters of the method.

Fields

ServerClientId

The client id of the server, and of the host.

Events

OnServerStarted

The server started (also the host).

OnServerStopped

The server stopped (also the host).

OnClientConnected

Only in the server: a client joined the game, it receives the id of the client (0 is the host).

OnClientDisconnected

Only in the server: a client left the game, it receives the id of the client.

OnConnected

The local client joined the game and received all the objects (also called in the host).

OnDisconnected

The local client was disconnected, or it could not connect. It receives the reason.

OnSceneLoaded

A scene loaded with MultiplayerIsEasyAPI.LoadScene(System.String) finished loading in this computer.

MultiplayerIsEasyManager

Manages the network game: starts the host, the server or the client, keeps the list of prefabs that can be created in the network, creates the object of each player and sends the changes of the synchronized fields.
You need one MultiplayerIsEasyManager in the first scene of the game. By default it is kept when other scenes are loaded.
Most of the time you can use the static class MultiplayerIsEasyAPI instead of this component.

Properties

Instance

The manager of the game, null if there is none. There is only one: when the scene of the manager is loaded again, the new copy destroys its GameObject and this one (kept between scenes, with the connection) takes the Spawn Points of that scene.

Address

The address of the server that the clients connect to.

Port

The UDP port of the server.

MaxClients

Maximum number of remote clients. Change it before starting the server.

Password

The password of the server, or the password that the client sends. Empty for no password.

TickRate

Times per second that the changes are sent. Change it before starting the server, the clients use the value of the server.

PlayerPrefab

The prefab that is created for each player.

AddAllNetworkPrefabs

Add all the prefabs of the project that have a MultiplayerIsEasyComponent in their root to the network prefabs, when the game starts (in the editor) and in the builds, so the Network Prefabs list is not needed. The prefabs of the examples are only added in the example scenes. In a build it works with the managers placed in the scenes of the build, not with a manager created from a prefab.

NetworkPrefabs

The prefabs that can be created in the network (the Network Prefabs list of the inspector). Change it with MultiplayerIsEasyManager.AddNetworkPrefab(UnityEngine.GameObject) and MultiplayerIsEasyManager.RemoveNetworkPrefab(UnityEngine.GameObject).

SpawnPoints

Where the players are created, one after the other. If it is empty the MultiplayerIsEasySpawnPoint of the scene are used.

Timeout

Seconds without receiving anything before a connection is closed. It is used the next time the game starts.

InterpolationDelay

Minimum seconds in the past that the objects controlled by other computers are shown, so they move smoothly. On slower networks it grows automatically for each object. It is used the next time the game starts.

CheckApplicationVersion

Reject the clients that have a different Application.version.

KeepBetweenScenes

Keep the manager, and the connection, when a new scene is loaded (the "Keep Between Scenes" setting: it uses DontDestroyOnLoad).

RunInBackground

Keep running when the window does not have the focus.

AutoStart

How the manager starts when the game starts.

ServerInBatchMode

In a build without graphics (batch mode, a dedicated server) the server starts automatically.

LogLevel

Which messages of the asset are shown in the console.

SimulateNetwork

Simulate a slow network (only in the editor and in development builds). It is used the next time the game starts.

SimulatedLatency

Delay of each packet that is sent when MultiplayerIsEasyManager.SimulateNetwork is on, in milliseconds.

SimulatedJitter

Random variation of the delay when MultiplayerIsEasyManager.SimulateNetwork is on, in milliseconds.

SimulatedPacketLoss

Percentage of the packets that are lost when MultiplayerIsEasyManager.SimulateNetwork is on.

DisconnectMessage

The text that came with the last disconnection of this client, for example the ConnectionRequest.RejectMessage of the server. Empty if there was no text.

IsServer

true in the server and in the host.

IsClient

true in a client and in the host.

IsHost

true in the host (server and client at the same time).

IsRunning

true if the game was started (as host, server or client) and it was not stopped.

IsConnected

true if the server is running, or if the client finished joining the game.

IsConnecting

true while a client is connecting or receiving the game.

LocalClientId

The id of the local game: 0 in the server and in the host, 1 or more in the clients, -1 if it is not connected.

ServerTime

The time of the server in seconds since it started, in the clients it is estimated.

Statistics

Statistics of the network traffic.

ConnectedClients

Only in the server: the ids of the clients in the game, including the host (0).

LocalPlayer

The player object of the local game, null if it does not have one.

Methods

AddNetworkPrefab(GameObject prefab)

Adds a prefab to the Network Prefabs list, like dragging it in the inspector (a prefab that is already in the list is ignored). In an editor script that sets up a scene, mark the manager dirty after it (EditorUtility.SetDirty) or use Undo, so the scene saves it. In the game, add it before starting and in every computer: the server and the clients need the same prefabs.

prefab: A prefab with a MultiplayerIsEasyComponent in its root.

RemoveNetworkPrefab(GameObject prefab)

Removes a prefab from the Network Prefabs list.

prefab: The prefab.

StartHost()

Starts the server and a local client at the same time.

Returns: false if it could not start, for example because the port is in use.

StartServer()

Starts a dedicated server (without a local player).

Returns: false if it could not start, for example because the port is in use.

StartClient()

Connects to the server at MultiplayerIsEasyManager.Address and MultiplayerIsEasyManager.Port. When it finishes joining the game MultiplayerIsEasyAPI.OnConnected is called, and if it fails MultiplayerIsEasyAPI.OnDisconnected.

Returns: false if it could not start connecting, for example because the address is not valid.

StartClient(string serverAddress, int serverPort)

Connects to the server at the address and port.

serverAddress: An IP (for example 192.168.0.10), a domain name or "localhost".
serverPort: The UDP port of the server.

Returns: false if it could not start connecting, for example because the address is not valid.

Stop()

Stops the server, the host or the client. The objects created in the network are destroyed.

RegisterPrefab(GameObject prefab)

Adds a prefab to the network prefabs from code. Call it before starting the game, in all the computers.

prefab: A prefab with a MultiplayerIsEasyComponent. It can also be an inactive object of the scene used as a template (for example an object made by code, with the same name in all the computers): the spawned objects are active copies of it.

Spawn(GameObject prefabOrInstance, int ownerClientId)

Creates a network prefab in all the computers (only the server can do it). If it receives an object of the scene that is an instance of a network prefab, that object is spawned.

prefabOrInstance: A prefab of the Network Prefabs, or an instance of one of them.
ownerClientId: The id of the owner, 0 for the server.

Returns: The created object, null if it could not be spawned.

Spawn(GameObject prefab, Vector3 position, Quaternion rotation, int ownerClientId)

Creates a network prefab in all the computers at the position and rotation (only the server can do it).

prefab: A prefab of the Network Prefabs.
position: The position.
rotation: The rotation.
ownerClientId: The id of the owner, 0 for the server.

Returns: The created object, null if it could not be spawned.

Despawn(GameObject networkObject)

Removes an object from the network and destroys it in all the computers (only the server can do it).

networkObject: An object with a MultiplayerIsEasyComponent that is spawned.

GetNetworkObject(uint networkId)

Finds a network object by its MultiplayerIsEasyComponent.NetworkId.

networkId: The id of the object in the network.

Returns: The object, null if it does not exist.

GetPlayerObject(int clientId)

The player object of a client.

clientId: The id of the client, 0 for the host.

Returns: The player object, null if the client does not have one.

LoadScene(string sceneName)

Loads a scene in the server and in all the clients (only the server can do it). The objects created in the network are destroyed and the players are created again. The scene must be in the scene list of the build.

sceneName: The name of the scene.

DisconnectClient(int clientId)

Disconnects a client (only the server can do it). The client receives DisconnectReason.Kicked.

clientId: The id of the client.

Fields

ServerStarted

Called when the server (or the host) starts.

ServerStopped

Called when the server (or the host) stops.

ClientConnected

Only in the server: a client joined the game (it receives its id, 0 is the host).

ClientDisconnected

Only in the server: a client left the game (it receives its id).

Connected

The local client joined the game (also in the host).

Disconnected

The local client was disconnected (it receives the reason).

MultiplayerIsEasyComponent

To synchronize a GameObject in the network you need this component. In the inspector select the fields of the components that you want to synchronize (the position of the Transform, the health of your script, ...), like in Save Is Easy.
The objects placed in the scene are synchronized automatically. The prefabs that are created during the game must be in the Network Prefabs of the MultiplayerIsEasyManager and they are created with MultiplayerIsEasyAPI.Spawn(UnityEngine.GameObject,System.Int32).

Properties

NetworkId

The id of the object in the network, the same in all the computers. 0 if it is not spawned.

IsSpawned

true if the object is in the network (spawned by the server or an object of the scene in a running game).

OwnerId

The id of the client that owns the object, 0 (MultiplayerIsEasyAPI.ServerClientId) if it is owned by the server.

IsOwner

true if the local game owns this object.

HasAuthority

true if the local game controls the synchronized fields of this object (see MultiplayerIsEasyComponent.Authority). Change the fields only where it is true, in the other computers they are overwritten.

IsSceneObject

true if the object was placed in a scene in the editor (and it is not a prefab spawned during the game).

IsPlayerObject

true if it is the player object of a client (spawned with the Player Prefab of the manager).

PrefabId

The id that identifies the prefab of this object in all the computers. The editor assigns it when the prefab is created or saved (also by a script), and checks it again when you press Play and when you make a build.

SceneId

The id that identifies this object in the scene in all the computers, 0 if it is not an object of a scene. It is assigned in the editor.

Authority

Who can change the synchronized fields. Change it before the object is spawned.

Interpolate

Move the object smoothly between the states that arrive from the network.

UseLocalSpace

Synchronize the local position and rotation (relative to the parent) instead of the world position and rotation.

DestroyWithOwner

When the owner leaves the game the object is despawned. If it is false the server becomes the owner.

KinematicWhenRemote

In the computers that do not control the object its Rigidbody (or Rigidbody2D) is kinematic.

PositionThreshold

Smaller movements are not sent (in units).

RotationThreshold

Smaller rotations are not sent (in degrees).

ScaleThreshold

Smaller changes of scale are not sent.

SyncedFields

The fields selected in the inspector, for example "Transform/position" or "PlayerScript/health".

Methods

IsSynced(string path)

true if the field is selected to be synchronized. For a group (a component, or a class or struct inside it) true if all its fields are.

path: The path of the field: the name of the component and the name of the field separated by '/', for example "PlayerScript/health".

SetSynced(string path, bool synced)

Selects or unselects a field from code, like the inspector. It has to be done before the object is spawned and in the same way in all the computers. In an editor script that changes a prefab, save it after (PrefabUtility.SavePrefabAsset, or EditorUtility.SetDirty on this component).

path: The path of the field as the tree shows it: the name of the component and the names of the fields separated by '/', for example "PlayerScript/health", "PlayerScript/Stats/Speed" (a field of a nested class), "Transform/position" or "GameObject/active". A group selects all its fields, like its checkbox in the inspector: "PlayerScript/Stats" (a nested class or struct) or "PlayerScript" (every field of the component).
synced: true to synchronize it.

ChangeOwnership(int clientId)

Changes the owner of the object. Only the server can do it.

clientId: The id of the new owner, 0 for the server.

RemoveOwnership()

The server becomes the owner of the object. Only the server can do it.

Despawn()

Removes the object from the network and destroys it in all the computers. Only the server can do it.

Teleport(Vector3 position, Quaternion rotation)

Moves the object to a new place without interpolation (the other computers do not show it moving through the space in between). Only the computer with the authority can do it.

position: The new position (local if MultiplayerIsEasyComponent.UseLocalSpace is true).
rotation: The new rotation (local if MultiplayerIsEasyComponent.UseLocalSpace is true).

SendRpc(MonoBehaviour target, string method, RpcTarget rpcTarget, object[] args)

Calls a method marked with MultiplayerRpcAttribute in other computers.

target: The script that has the method, it must be in this GameObject.
method: The name of the method, use nameof(MyMethod).
rpcTarget: Where the method is executed.
args: The parameters of the method.

SendRpcToClient(MonoBehaviour target, string method, int clientId, object[] args)

Calls a method marked with MultiplayerRpcAttribute only in one client.

target: The script that has the method, it must be in this GameObject.
method: The name of the method, use nameof(MyMethod).
clientId: The id of the client, 0 for the host.
args: The parameters of the method.

MultiplayerIsEasyBehaviour

A MonoBehaviour with shortcuts for the network: IsOwner, HasAuthority, IsServer, SendRpc and the network events as virtual methods. Inheriting from it is optional, any script works with the MultiplayerIsEasyComponent.

public class Player : MultiplayerIsEasyBehaviour {
    public override void OnNetworkSpawn() {
        if (IsOwner) Camera.main.transform.SetParent(transform);
    }
}

Properties

NetworkObject

The MultiplayerIsEasyComponent of this GameObject.

IsServer

true in the server and in the host.

IsClient

true in a client and in the host.

IsHost

true in the host.

IsOwner

true if the local game owns this object.

HasAuthority

true if the local game controls the synchronized fields of this object.

IsSpawned

true if the object is in the network.

OwnerId

The id of the owner of the object, 0 for the server.

NetworkId

The id of the object in the network.

LocalClientId

The id of the local game: 0 in the server and in the host, 1 or more in the clients.

Methods

OnNetworkSpawn()

The object is now in the network. Use it instead of Start() for the code that needs to know the owner or the synchronized values.

OnNetworkDespawn()

The object is no longer in the network.

OnOwnershipChanged(int previousOwner, int newOwner)

The owner of the object changed.

previousOwner: The id of the previous owner.
newOwner: The id of the new owner.

SendRpc(string method, RpcTarget target, object[] args)

Calls a method of this script marked with MultiplayerRpcAttribute in other computers.

method: The name of the method, use nameof(MyMethod).
target: Where the method is executed.
args: The parameters of the method.

SendRpcToClient(string method, int clientId, object[] args)

Calls a method of this script marked with MultiplayerRpcAttribute only in one client. If that client is the caller (or the host calls it for 0), it runs at once.

method: The name of the method, use nameof(MyMethod).
clientId: The id of the client, 0 for the host.
args: The parameters of the method.

IMultiplayerIsEasyEvents

Implement this interface in a script of a GameObject that has a MultiplayerIsEasyComponent to receive its network events. You can also inherit from MultiplayerIsEasyBehaviour, that implements it with virtual methods.

Methods

OnNetworkSpawn()

The object is now in the network. Use it instead of Start() for the code that needs to know the owner or the synchronized values, in the clients it is called after the values of the server were applied.

OnNetworkDespawn()

The object is no longer in the network: it was despawned, the game was disconnected or a new scene was loaded.

OnOwnershipChanged(int previousOwner, int newOwner)

The owner of the object changed.

previousOwner: The id of the previous owner (0 is the server).
newOwner: The id of the new owner (0 is the server).

MultiplayerIsEasySpawnPoint

Marks a place where the players are created. If the Spawn Points of the MultiplayerIsEasyManager are empty, the players are created at the spawn points of the scene, one after the other (each scene can have its own).

MultiplayerIsEasyExtensions

Shortcuts to use the network from any script.

Methods

SendRpc(MonoBehaviour behaviour, string method, RpcTarget target, object[] args)

Calls a method of this script marked with MultiplayerRpcAttribute in other computers.

this.SendRpc(nameof(Shoot), RpcTarget.All, direction);

behaviour: The script that has the method.
method: The name of the method, use nameof(MyMethod).
target: Where the method is executed.
args: The parameters of the method.

SendRpcToClient(MonoBehaviour behaviour, string method, int clientId, object[] args)

Calls a method of this script marked with MultiplayerRpcAttribute only in one client. If that client is the caller (or the host calls it for 0), it runs at once.

behaviour: The script that has the method.
method: The name of the method, use nameof(MyMethod).
clientId: The id of the client, 0 for the host.
args: The parameters of the method.

GetNetworkObject(Component component)

The MultiplayerIsEasyComponent of the GameObject of this component, null if it does not have one.

component: Any component of the GameObject.

Returns: The MultiplayerIsEasyComponent or null.

GetNetworkObject(GameObject gameObject)

The MultiplayerIsEasyComponent of the GameObject, null if it does not have one.

gameObject: The GameObject.

Returns: The MultiplayerIsEasyComponent or null.

MultiplayerRpcAttribute

Marks a method of a script as a remote procedure call (RPC), so it can be executed in other computers with SendRpc. The GameObject needs a MultiplayerIsEasyComponent.
The parameters can be of any type that can be synchronized (numbers, strings, enums, Vector3, arrays, lists, ...). Add RpcInfo as the last parameter to know who made the call.

[MultiplayerRpc]
void Shoot(Vector3 direction) { ... }

//in another method
this.SendRpc(nameof(Shoot), RpcTarget.All, transform.forward);

Properties

RequireOwnership

If true (the default) only the owner of the object, or the server, can make the call. Set it to false so any client can make it, for example to open a door that is owned by the server.

Reliable

If true (the default) the call always arrives and in order. If false it is faster but it can be lost, use it for calls that are sent very often and where only the last one matters.

RpcInfo

Information about a remote procedure call. Add it as the last parameter of a method marked with MultiplayerRpcAttribute to know who made the call, it is filled automatically and it is not sent.

[MultiplayerRpc(RequireOwnership = false)]
void OpenDoor(RpcInfo info) {
    Debug.Log("The client " + info.SenderClientId + " opened the door");
}

Properties

SenderClientId

The id of the client that made the call, 0 if it was the server or the host.

RpcTarget

Where a remote procedure call (a method marked with MultiplayerRpcAttribute) is executed. When it runs in the computer that makes the call, it runs at once, inside SendRpc; the others run it when the call arrives.

Fields

Server

Only on the server (or the host). If the caller is the server, it runs at once.

All

On the server and on every client, including the one that makes the call (the caller runs it at once).

Others

On the server and on every client, except the one that makes the call.

Owner

Only on the owner of the object (the server or host if the object is owned by the server). If the caller is the owner, it runs at once.

Clients

On every client, including the host, but not on a dedicated server. A client or the host that makes the call runs it at once.

SyncAuthority

Who is allowed to change the synchronized fields of a networked GameObject.

Fields

Server

Only the server changes the synchronized fields and every client receives them. Changes made by a client are overwritten by the next update of the server.

Owner

The owner of the object changes the synchronized fields (for example the player that controls it), the server receives them and sends them to the other clients. While the object is owned by the server it behaves like SyncAuthority.Server.

ServerAuthorityAttribute

Only the server changes this synchronized field or property, also in an object with SyncAuthority.Owner authority. Use it for the values that the game rules decide, for example the score or the health of a player that its owner moves. The changes that the owner makes to it are not sent (the next value of the server replaces them). It can also be put on a field that has a class or a struct inside, then it applies to all its fields.

[ServerAuthority]
public int Score;   //the server adds the points, the owner can not change them

SyncHookAttribute

Calls a method of the same class when the synchronized value of the field or property changes because of a value that arrived from the network (it is not called in the computer that made the change).
The method can have no parameters, one parameter (the new value) or two parameters (the old value and the new value).

[SyncHook(nameof(OnHealthChanged))]
public int Health;

void OnHealthChanged(int oldValue, int newValue) {
    healthBar.value = newValue;
}

Properties

MethodName

The name of the method that is called.

Methods

SyncHookAttribute(string methodName)

The method is called when the value changes because of the network.

methodName: The name of the method, use nameof(MyMethod).

AlwaysSyncAttribute

The field or property is always synchronized, it can not be turned off in the MultiplayerIsEasyComponent.

AvoidSyncAttribute

The field, property, class or struct can not be synchronized and it is not shown in the MultiplayerIsEasyComponent.

ConnectionRequest

A client that wants to join the game. The server receives it in MultiplayerIsEasyAPI.ConnectionApproval to decide if the client can join (after the password and the version were checked).

Properties

Address

The IP address and port of the client.

Data

The text that the client set in MultiplayerIsEasyAPI.ConnectionData before connecting, for example the name of the player.

RejectMessage

The message that the client receives if the connection is rejected.

DisconnectReason

Why a connection was closed.

Fields

None

There is no reason, the connection is still open.

Disconnected

The local game closed the connection, for example with MultiplayerIsEasyAPI.Stop(). On the server it means that the client left the game.

ServerShutdown

The server was stopped.

Timeout

Nothing was received from the other side for longer than the timeout of the manager.

ConnectionFailed

The server could not be reached. Check the address, the port, the firewall and that the server is running.

ServerFull

The server already has the maximum number of clients.

WrongPassword

The password of the client is not the password of the server.

VersionMismatch

The client and the server are different builds: different version of the asset, of the game (Application.version) or different network prefabs or synchronized fields.

Rejected

The connection approval callback of the server rejected the client.

Kicked

The server disconnected the client.

ProtocolError

Invalid data was received, the connection was closed to protect the game.

AutoStartMode

How the manager starts when the game starts.

Fields

None

It does not start, call MultiplayerIsEasyAPI.StartHost, StartServer or StartClient (or use the MultiplayerIsEasyHUD).

Host

Starts as host: server and client at the same time.

Server

Starts as a dedicated server (without a local player).

Client

Connects as a client to the address and port of the manager.

LogLevel

Which messages of the asset are shown in the console.

Fields

All

Everything, including connections and disconnections.

Warnings

Warnings and errors.

Errors

Only errors.

None

Nothing.

NetworkStatistics

Statistics of the network traffic of the local game.

Properties

RoundTripTime

Round trip time in milliseconds: on a client the time to the server and back, on the server the average of the clients.

BytesSent

Total bytes sent since the start of the session.

BytesReceived

Total bytes received since the start of the session.

BytesSentPerSecond

Bytes sent during the last second.

BytesReceivedPerSecond

Bytes received during the last second.

PacketsSent

Total packets sent since the start of the session.

PacketsReceived

Total packets received since the start of the session.

ResentMessages

Reliable messages that had to be sent again because they were lost.

Connections

Number of connections: on the server the remote clients, on a client 1 when it is connected.

Contact

For questions, problems or suggestions, write to zedgeincorporation@gmail.com, in English or Spanish.