com.unity.netcode.gameobjects icon indicating copy to clipboard operation
com.unity.netcode.gameobjects copied to clipboard

Specify GlobalObjectIdHash at runtime (for procedurally generated prefabs)

Open ghost opened this issue 4 years ago • 3 comments

Is your feature request related to a problem? Please describe. I would like to generate prefabs procedurally at runtime. I can easily register them with NetworkManager.PrefabHandler.AddHandler. The only missing part is that I can't set NetworkObject.GlobalObjectIdHash because it's internal.

Describe the solution you'd like I understand exposing NetworkObject.GlobalObjectIdHash might be a problem (it's advanced use case and if public on NetworkObject, user might think it's OK to edit it in typical scenario). Maybe adding it in a more specific location such as a method in NetworkPrefabHandler would be very helpful.

Describe alternatives you've considered Currently I use reflection to set it...

ghost avatar Oct 27 '21 02:10 ghost

Added into product backlog for consideration, MTTH-124

will-mearns avatar Oct 29 '21 17:10 will-mearns

After seeing #2565, I wanted to add two more details to my use case:

  • I add prefab after NetworkManager.Initialize()
  • #2565 unit test also set GlobalObjectIdHash just like I would like to do, but since it's internal I can't do it the same way.

Would it be possible to simply add a function like NetworkObject.SetRuntimeGlobalObjectIdHash() (I understand the GlobalObjectIdHash itself is probably better as non-public to not encourage user to edit it, and rather use a function name with Runtime to show it only make sense when creating runtime prefab). If that approach sounds OK, I would be happy to submit a PR.

What I do is something like this:

// Note: I make sure prefab handler and IDs match on both client and server
var handler = new VehicleNetworkPrefabInstanceHandler(prefabHandlerId++);
networkGame.NetworkManager.PrefabHandler.AddHandler(handler.Id, handler);

internal class VehicleNetworkPrefabInstanceHandler : INetworkPrefabInstanceHandler
{
    public VehicleNetworkPrefabInstanceHandler(uint id)
    {
        Id = id;
    }
    public NetworkObject Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation)
    {
        // Create NetworkObject
        var networkObject = vehicleInstance.AddComponent<NetworkObject>();
        // NOT POSSIBLE (I currently use reflection)
        networkObject.GlobalObjectIdHash = Id;
        return networkObject;
    }
    public void Destroy(NetworkObject networkObject) {}
}

ghost avatar Aug 08 '23 16:08 ghost

@virgile-wp, you saved my day with your code, thanks!

AnriiAndrushko avatar Jan 22 '24 16:01 AnriiAndrushko