Migrating from UNet to Netcode for GameObjects
Use this step-by-step guide to migrate your projects from Unity UNet to Netcode for GameObjects (Netcode). If you need help, contact us in the Unity Multiplayer Networking Discord.
UNet is an entirely deprecated product, and you should upgrade to Netcode for GameObjects as soon as possible.
Current limitations
Review the following limitations for upgrade and migrations from previous versions of Unity UNet to Netcode:
- Naming constraints may cause issues. UNet prefixed methods with
Cmd
orRpc
. Netcode requires postfix. This may require either complicated multi-line regex to find and replace, or manual updates. For example,CommandAttribute
has been renamedServerRpcAttribute
andClientRPCAttribute
has been renamedClientRpcAttribute
. - Errors for RPC postfix naming patterns don't show in your IDE.
- Client and Server have separate representations in UNet. UNet has a number of callbacks that don't exist for Netcode.
- Prefabs need to be added to the Prefab registration list for Netcode.
- Matchmaking isn't available in Netcode at this time.
Backup your project
It is recommended that you back up your project before proceeding with the migration. For example:
- Create a copy of your entire project folder.
- Use source control software, like Git.
We recommend using both methods to backup your project. This gives you a copied project and tracking through committed changes and history.
Install Netcode and restart Unity
See the Netcode installation guide for more information.
If you install Git for the first time, you will need to restart your system.
RPC Invoking
Invoking an RPC works the same way as in UNet. Just call the function and it will send an RPC.
Replace NetworkIdentity with NetworkObject
UNet’s NetworkIdentity
is called NetworkObject
in Netcode and works in a similar way.
Replace UNet NetworkTransform with Netcode NetworkTransform
UNet’s NetworkTransform
is also called NetworkTransform
in Netcode and works in a similar way.
The NetworkTransform
does not have full feature parity with UNET's NetworkTransform
. It lacks features like position synchronizing for rigidbodies.
Replace UNet NetworkAnimator with Netcode NetworkAnimator
Replace UNEt's NetworkAnimator
with Netcode's NetworkAnimator
component everywhere in your project.
Update NetworkBehaviour
Replace UNet NetworkBehaviour
with Netcode's NetworkBehaviour
everywhere in your project.
- UNET Example
- Netcode for GameObjects Example
public class MyUnetClass : NetworkBehaviour
{
[SyncVar]
public float MySyncFloat;
public void Start()
{
if (isClient)
{
CmdExample(10f);
}
else if (isServer)
{
RpcExample(10f);
}
}
[Command]
public void CmdExample(float x)
{
Debug.Log(“Runs on server”);
}
[ClientRpc]
public void RpcExample(float x)
{
Debug.Log(“Runs on clients”);
}
}
public class MyNetcodeExample : NetworkBehaviour
{
public NetworkVariable<float> MyNetworkVariable = new NetworkVariable<float>();
public override void OnNetworkSpawn()
{
ExampleClientRpc(10f);
ExampleServerRpc(10f);
}
[ServerRpc]
public void ExampleServerRpc(float x)
{
Debug.Log(“Runs on server”);
}
[ClientRpc]
public void ExampleClientRpc(float x)
{
Debug.Log(“Runs on clients”);
}
}
See NetworkBehaviour for more information.
Replace SyncVar
Replace SyncVar
with NetworkVariable
everywhere in your project.
To achieve equivalent functionality of SyncVar
hooks in Netcode subscribe a function to the OnValueChanged
callback of the NetworkVariable
. A noteable difference between the UNet hooks and Netcode's OnValueChanged
callback is that Netcode gives you both the old and the newly changed value while UNet provides you only with the old value. With UNet, you also had to manually assign the value of the SyncVar.
- UNET Example
- Netcode for GameObjects Example
public class SpaceShip : NetworkBehaviour
{
[SyncVar]
public string PlayerName;
[SyncVar(hook = "OnChangeHealth"))]
public int Health = 42;
void OnChangeHealth(int newHealth){
Health = newHealth; //This is no longer necessary in Netcode.
Debug.Log($"My new health is {newHealth}.");
}
}
// Don't forget to initialize NetworkVariable with a value.
public NetworkVariable<string> PlayerName = new NetworkVariable<string>();
public NetworkVariable<int> Health = new NetworkVariable<int>(42);
// This how you update the value of a NetworkVariable, you can also use .Value to access the current value of a NetworkVariable.
void MyUpdate()
{
Health.Value += 30;
}
void Awake()
{
// Call this is in Awake or Start to subscribe to changes of the NetworkVariable.
Health.OnValueChanged += OnChangeHealth;
}
void OnChangeHealth(int oldHealth, int newHealth){
//There is no need anymore to manually assign the value of the variable here with Netcode. This is done automatically by Netcode for you.
Debug.Log($"My new health is {newHealth}. Before my health was {oldHealth}");
}
Replace all postfix increment and decrement usages of SyncVar in your project. Netcode's NetworkVariable.Value
exposes a value type that's why postfix increment/decrement isn't supported.
- UNET Example
- Netcode for GameObjects Example
public int Health = 42;
public void Update(){
Health++;
}
public NetworkVariable<int> Health = new NetworkVariable<int>(42);
public void Update(){
Health.Value = Health.Value + 1;
}
See NetworkVariable for more information.
Replace SyncList with NetworkList
Replace SyncList<T>
with NetworkList<T>
everywhere in your project. NetworkList
has a OnListChanged
event which is similar to UNet's Callback
.
- UNET Example
- Netcode for GameObjects Example
public SyncListInt m_ints = new SyncListInt();
private void OnIntChanged(SyncListInt.Operation op, int index)
{
Debug.Log("list changed " + op);
}
public override void OnStartClient()
{
m_ints.Callback = OnIntChanged;
}
NetworkList<int> m_ints = new NetworkList<int>();
// Call this is in Awake or Start to subscribe to changes of the NetworkList.
void ListenChanges()
{
m_ints.OnListChanged += OnIntChanged;
}
// The NetworkListEvent has information about the operation and index of the change.
void OnIntChanged(NetworkListEvent<int> changeEvent)
{
}
Replace Command/ClientRPC
UNet’s Command/ClientRPC
is replaced with Server/ClientRpc
in Netcode which works in a similar way.
- UNET Example
- Netcode for GameObjects Example
[Command]
public void CmdExample(float x)
{
Debug.Log(“Runs on server”);
}
[ClientRpc]
public void RpcExample(float x)
{
Debug.Log(“Runs on clients”);
}
[ServerRPC]
public void ExampleServerRpc(float x)
{
Debug.Log(“Runs on server”);
}
[ClientRPC]
public void ExampleClientRpc(float x)
{
Debug.Log(“Runs on clients”);
}
In Netcode, RPC function names must end with a ClientRpc/ServerRpc
suffix.
See Messaging System for more information.
Replace OnServerAddPlayer
Replace OnServerAddPlayer
with ConnectionApproval
everywhere in your project.
- UNET Example
- Netcode for GameObjects Example
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.NetworkSystem;
class MyManager : NetworkManager
{
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader)
{
if (extraMessageReader != null)
{
var s = extraMessageReader.ReadMessage<StringMessage>();
Debug.Log("my name is " + s.value);
}
OnServerAddPlayer(conn, playerControllerId, extraMessageReader);
}
}
Server-only example:
using Unity.Netcode;
private void Setup()
{
NetworkManager.Singleton.ConnectionApprovalCallback += ApprovalCheck;
NetworkManager.Singleton.StartHost();
}
private void ApprovalCheck(byte[] connectionData, ulong clientId, NetworkManager.ConnectionApprovedDelegate callback)
{
//Your logic here
bool approve = true;
bool createPlayerObject = true;
// The Prefab hash. Use null to use the default player prefab
// If using this hash, replace "MyPrefabHashGenerator" with the name of a Prefab added to the NetworkPrefabs field of your NetworkManager object in the scene
ulong? prefabHash = NetworkpawnManager.GetPrefabHashFromGenerator("MyPrefabHashGenerator");
//If approve is true, the connection gets added. If it's false. The client gets disconnected
callback(createPlayerObject, prefabHash, approve, positionToSpawnAt, rotationToSpawnWith);
}
See Connection Approval for more information.
Replace NetworkServer.Spawn with NetworkObject.Spawn
Replace NetworkServer.Spawn
with NetworkObject.Spawn
everywhere in your project.
- UNET Example
- Netcode for GameObjects Example
using UnityEngine;
using UnityEngine.Networking;
public class Example : NetworkBehaviour
{
//Assign the Prefab in the Inspector
public GameObject m_MyGameObject;
GameObject m_MyInstantiated;
void Start()
{
//Instantiate the prefab
m_MyInstantiated = Instantiate(m_MyGameObject);
//Spawn the GameObject you assign in the Inspector
NetworkServer.Spawn(m_MyInstantiated);
}
}
GameObject go = Instantiate(myPrefab, Vector3.zero, Quaternion.identity);
go.GetComponent<NetworkObject>().Spawn();
See Object Spawning for more information.
Custom Spawn Handlers
Netcode has Custom Spawn Handlers
to replace UNet's Custom Spawn Functions
. See Object Pooling for more information.
Replace NetworkContextProperties
Netcode has IsLocalPlayer
, IsClient
, IsServer
and IsHost
to replace UNets isLocalPlayer
, isClient
and isServer
. In Netcode each object can be owned by a specific peer. This can be checked with IsOwner
which is similar to UNets hasAuthority
.
Network Proximity Checker/ OnCheckObserver with Netcode visibility
There is no direct equivalent to the NetworkPromimityChecker
UNet component in Netcode. Network visiblilty for clients works similar as in UNet. Netcode does not have an equivalent to the ObjectHide
message from UNet. In Netcode networked objects on the host are always visible. There is no equivalent to the OnSetLocalVisibility
function in UNet. A manual network promiximty implementation with the OnCheckObserver
can be ported to Netcode by using NetworkObject.CheckObjectVisibility
. OnRebuildObservers
isn't needed for Netcode visibilty system.
- UNET Example
- Netcode for GameObjects Example
public override bool OnCheckObserver(NetworkConnection conn)
{
return IsvisibleToPlayer(getComponent<NetworkIdentity>(), coon);
}
public bool IsVisibleToPlayer(NetworkIdentity identity, NetworkConnection conn){
// Any promimity function.
return true;
}
public void Start(){
NetworkObject.CheckObjectVisibility = ((clientId) => {
return IsVisibleToPlayer(NetworkObject, NetworkManager.Singleton.ConnectedClients[clientId]);
});
}
public bool IsVisibleToPlayer(NetworkObject networkObject, NetworkClient client){
// Any promimity function.
return true;
}
See Object Visbility to learn more about Netcodes network visiblity check.
Update SceneManagement
In Netcode, scene management isn't done over the NetworkManager
like in UNet. The NetworkSceneManager
provides equivalent functionality for switching scenes.
- UNET Example
- Netcode for GameObjects Example
public void ChangeScene()
{
MyNetworkManager.ServerChangeScene("MyNewScene");
}
public void ChangeScene()
{
NetworkSceneManager.LoadScene("MyNewScene", LoadSceneMode.Single);
}
Update ClientAttribute/ClientCallbackAttribute and ServerAttribute/ServerCallbackAttribute
Netcode currently does not offer a replacement for marking a function with an attribute so that it only runs on the server or the client. You can manually return out of the function instead.
- UNET Example
- Netcode for GameObjects Example
[Client]
public void MyClientOnlyFunction()
{
Debug.Log("I'm a client!");
}
public void MyClientOnlyFunction()
{
if (!IsClient) { return; }
Debug.Log("I'm a client!");
}
Replace SyncEvent with RPC event
Netcode does not provide an equivalent for SyncEvent
. To port SyncEvent
code from UNet to Netcode, send an RPC to invoke the event on the other side.
- UNET Example
- Netcode for GameObjects Example
public class DamageClass : NetworkBehaviour
{
public delegate void TakeDamageDelegate(int amount);
[SyncEvent]
public event TakeDamageDelegate EventTakeDamage;
[Command]
public void CmdTakeDamage(int val)
{
EventTakeDamage(val);
}
}
public class DamageClass : NetworkBehaviour
{
public delegate void TakeDamageDelegate(int amount);
public event TakeDamageDelegate EventTakeDamage;
[ServerRpc]
public void TakeDamageServerRpc(int val)
{
EventTakeDamage(val);
OnTakeDamageClientRpc(val);
}
[ClientRpc]
public void OnTakeDamageClientRpc(int val){
EventTakeDamage(val);
}
}
Network Discovery
Netcode does not provide Network Discovery. The Contributions repository provides an example implementation for NetworkDiscovery.
Next Steps
After migrating and updating to the Netcode package, we recommend looking into the following:
- Consider using the Hello World and Golden Path series to learn some basics of Netcode for GameObjects.
- Explore the educational samples content for a deeper exploration into Netcode for GameObjects: