Mirror: How do I get Server object references

Hi partypeople,

I really hoped I wouldn’t have to ask questions like this so early in development, but this one makes my head spin. How can I get a reference to an object spawned on the Server with Mirror?

It seems like in UNET, there was the possibility to get it via netId and a list of objects, that doesn’t exist in Mirror:

NetworkServer.objects[netId].gameObject

In my case, I have a spawned arena and because there can only be one, I would love to have a static instance with all the information that other objects and players require (like spawnpoints). And since Commands and Rpc calls don’t return values, I don’t really see an easy solution to this.

Is this the wrong workflow? Am I missing something?

Any help would be highly appreciated and I also take two cents.

Cheers!

When you instantiate the object it returns the reference. You can use that same returned reference on the server after you call Spawn on it. Assign it to your static instance, etc.

1 Like

Thanks for the fast reply! But what about objects that were created on the server? Or is there no reason to run the spawn code on the server? I’m still new to this and don’t quite understand what code should run on the server and what should run on the client and be synchronized. I just read that because it could be potentially abused by cheaters, the more code goes to the server-side the better, but please correct me if I’m wrong :slight_smile:

I’m not sure I understand. When you “create” an object on the server, normally the process is on the server you Instantiate a prefab, and then spawn that instantiated prefab. A call to Instantiate, which returns a reference to the instantiated object, which you then pass to Spawn. The object then appears on all clients. The reference originally returned from the Instantiate call on the server is the same reference to the object after it is spawned.

On the clients if you want a reference to the same object, you can capture it in a Start method on the object itself, or find the object after it should already have appeared.

And yeah, generally you can reduce some forms of cheating if you trust the client as little as possible with as much of your logic on the server as you can.

2 Likes

I think I get it now. I didn’t understand that “the reference originally returned from the Instantiate call on the server is the same reference to the object after it is spawned.”

I did as you said and it works.

Thanks again!

1 Like

I’m not using OnServerAddPlayer, but custom character spawning as described here: https://mirror-networking.com/docs/Articles/Guides/GameObjects/SpawnPlayerCustom.html

When you NetworkServer.Spawn a GameObject, you first have to Instantiate it and that’s when you can catch the reference to the instance.

I know this is an old post, but i wanted to shed some light on this topic as most newcomers still get lost when it comes to identifying the client and server objects associated with COMMAND’s and RPC’s.

I wanted to share what i do in case it helps others still:

I made a NetworkObject class that i use as a baseclass for all my other networkbehavior scripts, such as Item,Interactable Scenery, Chests, Npc, Player, etc

using Mirror;
using System.Collections.Generic;

public class NetworkObject : NetworkBehaviour {

        // Dictionary to store spawned gameobjects by netId |  Usage: spawnedNetworkObjects[netId]
        public static Dictionary<uint,NetworkObject> spawnedNetworkObjects = new Dictionary<uint, NetworkObject>();

        // Add this object to the dictionary
        public virtual void Start()
        {
            spawnedNetworkObjects.Add(netId, this);
        }

        // Remove this object from the dictionary
        public virtual void OnDestroy()
        {
            spawnedNetworkObjects.Remove(netId);
        }
}

Example of it in use from a Player

public class Player : NetworkObject
{
        public override void Start()
        {
              base.Start();
              if (isServer)
                   Debug.Log($"Find Myself On server: {spawnedNetworkObjects[netId].name}");

              if (isLocalPlayer)
              {
                   Debug.Log($"Find Myself On Local Client: {spawnedNetworkObjects[netId].name}");
                   Debug.Log($"Same as this: {name}");
              }
        }
}

This can also be used from other classes or commands as well using the full static method

NetworkObject.spawnedNetworkObjects[netId];

And you can use it to find Components attached to the object just like any other GameObject.

NetworkObject.spawnedNetworkObjects[netId].GetComponent<T>();
NetworkObject.spawnedNetworkObjects[netId].transform;
NetworkObject.spawnedNetworkObjects[netId].gameObject;
// Etc

I tend to use this method when i need a client to send a command to the server, with a netID and any additional parameters of the object im interacting with, then i can just look it up with NetworkObject.spawnedNetworkObjects[netId].

Again i know this post was old, but i wanted to elaborate more as this was one of the first results on google when it comes to this topic.

If you want more information let me know.

2 Likes