miwarnec / DOTSNET

Public DOTSNET issue tracker
20 stars 0 forks source link

Spawning a prefab with nested `NetworkIdentity`s results in extra entities client-side and `netId` set to 0 #48

Open HeyZoos opened 3 years ago

HeyZoos commented 3 years ago

Describe the bug

Spawning a prefab with nested NetworkIdentitys results in extra entities and no netId to be set.

To Reproduce Steps to reproduce the behavior:

1) Create a fresh unity project and add DOTSNET 2) Create a prefab with a NetworkIdentity, call it Parent 3) Create another prefab with a NetworkIdentity and nest it under parent, add a visual representation if you want

Your prefabs should now look like this

image

image

4) Trigger a spawn by hooking into one of the existing systems (I hooked into the chat system message server system)

        protected override void OnMessage(int connectionId, ChatMessage message)
        {
            var prefab = _prefabSystem.prefabs.ToList()[0];
            for (int i = 0; i < 10; i++)
            {
                Debug.Log("Hello");
                var spawned = EntityManager.Instantiate(prefab.Value);
                server.Spawn(spawned, connectionId);
            }
            ...

Expected behavior Occurs when spawning untested child prefab, only 10 entities spawn client-side and all have unique netId values

Actual behavior Hundreds of extra client-side entities all with netId set to 0

Desktop (please complete the following information):

HeyZoos commented 3 years ago

It doesn't look like the Spawn system makes any effort to inspect a prefabs children?

                NetworkIdentity identity = GetComponent<NetworkIdentity>(entity);
                if (identity.netId == 0)
                {
                    // set netId to Entity's unique id (Index + Version)
                    // there is no reason to generate a new unique id if we already
                    // have one. this is way easier to debug as well.
                    // -> on server, netId is simply the entity.UniqueId()
                    // -> on client, it's a unique Id from the server
                    identity.netId = entity.UniqueId();

                    // set the owner connectionId
                    identity.connectionId = ownerConnectionId;

                    // apply component changes
                    SetComponent(entity, identity);
HeyZoos commented 3 years ago

The NetworkIdentitys, when nested end up with the same prefabIds as the parent NetworkIdentity

HeyZoos commented 3 years ago

The issue is here in NetworkIdentityAuthoring.cs:

            // is this a prefab? then assign prefab's Guid
            if (PrefabUtility.IsPartOfPrefabAsset(gameObject))
            {
                string path = AssetDatabase.GetAssetPath(gameObject);

AssetDatabase.GetAssetPath(gameObject) will return the same path for both the parent NetworkIdentity component and a nested NetworkIdentity component.

And because these are the same, when the server sends a spawn message, it tells the client to spawn multiple of the parent.