docs.unity3d.com
    Show / Hide Table of Contents

    Use real time multiparticipant

    You can connect your client application to the Unity Cloud Netcode for GameObjects (NGO) server to connect your participants to one another. For example, you can create participant avatars, share their locations, and spawn them inside rooms whenever new participants join those rooms.

    Whenever two or more participants join the same room, the Unity Cloud cloud automatically spawns a multiparticipant server instance using the NGO server. You can connect your application to this multiparticipant server instance to share data with other participants.

    Prerequisites

    Before you manage your participants, you must first manage your room.

    Connect your participants to a server

    To connect your participants to a Netcode server instance, see the following steps:

    1. Go to GameObject > Create Empty and name the new game object NetcodeManager.
    2. In your Assets/Scripts directory, create a new script and name it NetcodeManager.
    3. Attach the NetcodeManager script to your NetcodeManager game object.
    4. In your NetcodeManager script file, use the NetcodeManager class to reference NGO's NetworkManager, NetcodeParticipantManager, INetcodeService, and ISessionProvider.

       public class NetcodeManager : MonoBehaviour
       {
           [SerializeField]
           NetworkManager m_NetworkManager;
      
           [SerializeField]
           NetcodeParticipantManager m_NetcodeParticipantManager;
      
           INetcodeService m_NetcodeService;
           ISessionProvider m_SessionProvider;
       }
      
    5. Use the Awake method to retrieve the ISessionProvider service from PlatformServices and to reference the NetworkProvider in the Editor. You must create the INetcodeService method internally and dispose of it with the OnDestroy method.

       void Awake()
       {
           m_SessionProvider = PlatformServices.SessionProvider;
           m_NetcodeService = new NetcodeService(m_NetworkManager, m_NetcodeParticipantManager, m_SessionProvider);
       }
      
       void OnDestroy()
       {
           m_NetcodeService = null;
       }
      

    Server connection varies depending on how many participants are in a room. See the following for more information:

    • If the participant is alone in the room, the Presence Service doesn't spawn a server instance because there are no other participants for the server to share data with.
    • If the participant is the second participant to join the room, the Presence Service spawns a server instance and both participants automatically connect to this server.
    • If the participant joins a room with 2 or more participants, the server instance already exists.
    • When a new participant joins a room, a NetcodeParticipant game object spawns in the server. All participants then see this game object in their scene. NetcodeParticipant is a NetworkBehaviour . NetcodeParticipant cannot be used directly. It is accessible through an INetcodeParticipant. INetcodeParticipant can be used to share participant data among all clients.

    Create participant avatar prefabs

    You can create an avatar prefab to share the position of a participant in the room. To create an avatar prefab, see the following steps:

    1. Create a ParticipantAvatar prefab. You can add geometry and text to display the name of the participant.
      Screenshot of creating a prefab with some geometry and text
    2. In your Assets/Scripts directory, create a new script and name it ParticipantPrefab.
    3. Attach the ParticipantPrefab script to your ParticipantAvatar prefab.
    4. In your ParticipantPrefab script file, use the ParticipantAvatar class to expose two floats for movement control, reference the text field, and reference the corresponding INetcodeParticipant.

       public class ParticipantAvatar : MonoBehaviour
       {
           [SerializeField]
           float m_MovementSpeed = 2.0f;
           [SerializeField]
           float m_LookSpeed = 10.0f;
      
           [SerializeField]
           TextMesh m_ParticipantNameText;
      
           INetcodeParticipant m_NetcodeParticipant;
       }
      
    5. Use the Initialize method to store the INetcodeParticipant argument, subscribe to its ParticipantIdChanged event, and call ApplyParticipantId to make sure that the participant Id is updated from the start. Use the OnDestroy method to unsubscribe from the event.

       public void Initialize(INetcodeParticipant participant)
       {
           m_NetcodeParticipant = participant;
           m_NetcodeParticipant.ParticipantIdChanged += ApplyParticipantId;
      
           ApplyParticipantId(m_NetcodeParticipant.ParticipantId);
       }
      
       void OnDestroy()
       {
           m_NetcodeParticipant.ParticipantIdChanged -= ApplyParticipantId;
       }
      
       void ApplyParticipantId(ParticipantId participantId)
       {
           m_ParticipantNameText.text = participantId.ToString();
       }
      
    6. Use the Update method to handle the avatar position. If m_NetcodeParticipant.IsOwner is true, the avatar belongs to the current participant. If m_NetcodeParticipant.IsOwner is false, the avatar belongs to another participant.

       void Update()
       {
           if (m_NetcodeParticipant == null)
               return;
      
           if (m_NetcodeParticipant.IsOwner)
           {
               UpdateOwner();
           }
           else
           {
               UpdateOtherParticipant();
           }
       }
      
    7. If m_NetcodeParticipant.IsOwner is true, use the SetParticipantTransform method to allow movement and sync the new value with the server.

       void UpdateOwner()
       {
           if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D))
           {
               var movementSpeed = m_MovementSpeed * Time.deltaTime;
               transform.Translate(Input.GetAxis("Horizontal") * movementSpeed, 0.0f,
                   Input.GetAxis("Vertical") * movementSpeed);
           }
           else if (Input.GetMouseButton(1))
           {
               var rotationSpeed = m_LookSpeed * Time.deltaTime;
               transform.eulerAngles = transform.eulerAngles +
                   new Vector3(-Input.GetAxis("Mouse Y"), Input.GetAxis("Mouse X"), 0) * rotationSpeed;
           }
      
           m_NetcodeParticipant.SetParticipantTransform(transform.position, transform.rotation);
       }
      
    8. If m_NetcodeParticipant.IsOwner is false, read m_NetcodeParticipant.Transform to read the latest value. csharp void UpdateOtherParticipant() { var newTransform = m_NetcodeParticipant.Transform; transform.position = newTransform.position; transform.rotation = newTransform.rotation; }

    Spawn participant avatars

    When a new participant joins the room, you can use an avatar spawner to instantiate an avatar for that new participant. To spawn an avatar, see the following steps:

    1. In your Assets/Scripts directory, create a new script and name it AvatarSpawner.
    2. Attach the AvatarSpawner script to your NetcodeManager game object.
    3. In your AvatarSpawner script file, use the AvatarSpawner class to reference your ParticipantAvatar prefab, a transform that contains all instantiated game objects, and a dictionary mapping between the Participant ID and its corresponding ParticipantAvatar.

       public class AvatarSpawner : MonoBehaviour
       {
           [SerializeField]
           Avatar m_Prefab;
      
           [SerializeField]
           Transform m_Root;
      
           readonly Dictionary<ParticipantId, ParticipantAvatar> m_Avatars = new();
       }
      
    4. Use the Awake method to subscribe to the m_NetcodeService.ParticipantAdded and m_NetcodeService.ParticipantRemoved events. Use the OnDestroy method to unsubscribe from the events.

       void Awake()
       {
           m_NetcodeService.ParticipantAdded += OnParticipantAdded;
           m_NetcodeService.ParticipantRemoved += OnParticipantRemoved;
       }
      
       void OnDestroy()
       {
           m_NetcodeService.ParticipantAdded -= OnParticipantAdded;
           m_NetcodeService.ParticipantRemoved -= OnParticipantRemoved;
       }
      
    5. When the participant prefab is created, instantiate the avatar prefab, initialize it with participant data, and save it in the mapping. csharp void OnParticipantAdded(INetcodeParticipant participant) { var avatar = Instantiate(m_Prefab, m_Root); avatar.transform.localPosition = Vector3.zero; avatar.Initialize(participant); m_Avatars[participant.ParticipantId] = avatar; }
    6. When the participant prefab is destroyed, destroy the avatar prefab and clear it from the mapping. csharp void OnParticipantRemoved(INetcodeParticipant participant) { if (m_Avatars.ContainsKey(participant.ParticipantId)) { var avatar = m_Avatars[participant.ParticipantId]; Destroy(avatar.gameObject); m_Avatars.Remove(participant.ParticipantId); } }

    Complete your scene setup

    To complete your scene setup, see the following steps:

    1. In the Unity Editor, open your Packages/Unity Cloud/Prefabs.
    2. Instantiate the NetworkManager prefab in your scene.
    3. Select the NetcodeManager game object you created earlier.
    4. Update the NetcodeManager game object with your NetworkManager and NetcodeParticipantManager instance, your avatar prefab, and a root transform.
      Screenshot providing the right values in the NetcodeManager
    Back to top
    Copyright © 2023 Unity Technologies — Terms of use
    • Legal
    • Privacy Policy
    • Cookies
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)
    "Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
    Generated by DocFX on 18 October 2023