DarkRift 2 Tutorial for Unity 3D – Part 7 – How about synchronized objects

Reminder : You can find all the DarkRift2 related articles here 
You can find the entire project on my official GitHub

Concept

When you’re working in a Server/Client environment, there is some problems that doesn’t exists in a solo game. For exemple, the synchronisation of gameobjects.

One diffuculty is to keep a track of each network gameobjects and synchronize them. You get it ? It means that all synchronized game object on the network must have an Unique ID. This unique ID must be the same both on server and on all connected clients

Here is the way we’ll proceed :

As you can see, we need to identify on the scene wich game object need to be synchronized. After that, when the scene is loaded, we have to check on wich side we are executing the code (Server or Client side) in order to generate an unique network ID or to destroy the gameobject itself.

We’ll first focus on identifying where the game is executed.

Where game is executed ?

There is many ways of doing that. I choosed to use the Singleton pattern to accomplish this task. How it will works ?

Both ServerManager and ClientManager will use the singleton pattern. It means that we can access at any time (except on Awake()) to the ServerManager instance by writing :

GameServerManager.instance; //Return the unique instance

Download my utilities on GitHub

I provide you some utilities on my official github repository that you can download right now here : https://github.com/TheUncas/unity3D-tools

Download it as .ZIP and copy/paste the content on the scripts folder on the unity project. You should have this : (The content may change over time…)

We’ll use 2 classes wich are :

  • MonoBehaviourSingletonNonPersistent : Singleton Pattern that doesn’t persists after scene is destroyed
  • MonoBehaviourSingletonPersistent : Singleton Pattern that persits after scene is destroyed. It means that the game object will be not destroyed.

In our case, we want to keep an instance always alive, so we’ll use the Persistent Singleton. Let’s implement it on both GameServerManager. Modify the class declaration like that :

using Utilities;

public class GameServerManager : MonoBehaviourSingletonPersistent<GameServerManager>

Do the same for the ClientManager class.

Generate a unique network ID

For each object that needs to e synchronized over network, we want a unique network ID, so… let’s create a specific script that will perform it. Let’s call him NetworkObject in the Network folder :

We want from this component that it :

  • Generates an unique ID if we are on the server and register the object into a the ServerManager gameobject (To be created)
  • Destroys immediately the gameobject if we are on a client.

So simple as it is. Here is the code :

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NetworkObject : MonoBehaviour
{
    #region Properties

    /// <summary>
    /// Id of the network object
    /// </summary>
    [HideInInspector]
    public int id;

    #endregion

    #region Unity Callbacks

    private void Start()
    {
        //If we are not on the server and id is not set, destroy the gameobject
        if (Equals(GameServerManager.instance, null) && id == 0)
        {
            Destroy(gameObject);
        }
        else if(!Equals(GameServerManager.instance, null))
        {
            // Get the instance id of the gameobject on the server scene
            id = GetInstanceID();
            //Register with the server
            //GameServerManager.instance.RegisterNetworkObject(this);
        }
    }

    #endregion
}

As you can see, i commented the line with the RegisterNetworkObject() because this method doesn’t exists yet on the ServerManager script. We’ll create it on the next article.

So now, let’s assign this script to the ball on the MainGameScene and launch both the client and both the server in unity :

That’s perfect. We are now ready to tell the server to send a message to the client to tell him to spawn a ball into its own scene. Of course, we’ll need to instantiate gameobject on the fly. There is 2 way to do that :

  • Using the Resource folder, wich is not an option if we decide to put in production our produce
  • Using Asset Bundles, wich is the most efficient and elegant way of instanciate objects

For our purpose, we’ll use the resources folder because it’s totally appropriate to fastly prototype a game. If you decide to make a production version of your game, you should consider to move to AssetBundles.

What about object position synchronization ?

Regarding the position of synchronized objects, we will treat this subject later, we first need to instantiate these objects on each connected clients.

What’s next ?

On the next article of this tutorial, we’ll keep a track of each network gameobject in the server scene and create our message to send to the client when he connects.

Posted in Dark Rift 2, Tutorials and tagged , .

Leave a Reply

Your email address will not be published. Required fields are marked *