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

NetworkPrefab has a duplicate GlobalObjectIdHash source entry value of XYZ

Open daniellochner opened this issue 3 years ago • 12 comments
trafficstars

Describe the bug: Every now and then, I get this issue when trying to enter play mode:

NetworkPrefab (Example1) has a duplicate GlobalObjectIdHash source entry value of: 951099334! Removing entry from list! NetworkPrefab (Example2) has a duplicate GlobalObjectIdHash source entry value of: 951099334! Removing entry from list! NetworkPrefab (Example3) has a duplicate GlobalObjectIdHash source entry value of: 951099334! Removing entry from list!

It seems to happen with some of the prefabs in my network prefabs list. To fix it, I just revalidate the NetworkObject component (e.g., toggle one of the parameters on and off), and another GlobalObjectIdHash is generated. I tried completely removing and re-adding the NetworkObject components from each of the prefabs, however, it didn't seem to work.

To reproduce: I unfortunately cannot seem to deterministically reproduce this error.

Screenshot: image

Environment:

  • OS: Windows 10
  • Unity Version: 2020.3.12f1
  • Netcode Version: 1.0.0-pre.3
  • Unity Transport Version: 1.0.0.-pre.10
  • Transport for Netcode Version: 1.0.0-pre.3

daniellochner avatar Dec 05 '21 18:12 daniellochner

Hi @daniellochner, It would help to know how your network prefabs are organized. Could you provide either a sample repository that yields the same results or provide screenshot for some of the prefabs so I can see how they are organized?

NoelStephensUnity avatar Dec 09 '21 15:12 NoelStephensUnity

Hi @NoelStephensUnity,

sometimes I have the same problem. As a workaround I change something in the NetworkObject Component of my NetworkPrefab (tick off a checkbox and back again). After rebuilding it is working again. I have to repeat this workaround from time to time.

At the moment I don't have the problem, but here is a screenshot of a very simple Enemy networkPrefab, that has this problem sometimes: grafik

And here is the NetworkManager Component, where I added my NetworkPrefab: grafik

NachtAktivist avatar Dec 17 '21 06:12 NachtAktivist

Thanks @NachtAktivist. For a quick workaround, I've attached a component to my startup scene that toggles a property from each network prefab twice...

public class NetworkPrefabFix : MonoBehaviour
{
    [SerializeField] private NetworkObject[] objects;
#if UNITY_EDITOR
    private void Start()
    {
        foreach (NetworkObject obj in objects)
        {
            obj.AlwaysReplicateAsRoot = !obj.AlwaysReplicateAsRoot;
            obj.AlwaysReplicateAsRoot = !obj.AlwaysReplicateAsRoot;
        }
    }
#endif
}

Silly workaround, but this issue has been incredibly frustrating, so just glad I don't have to worry about it again.

daniellochner avatar Dec 23 '21 01:12 daniellochner

Hi, I have a similar issue with the system complaining of identical GlobalObjectIdHash however it's not the case when I start the game.

I start playing - the values are properly different then - and when I StartHost or StartClient the GlobalObjectIdHash values all get set to 951099334.

There is also a post on the Multiplayer part of the Unity forum about this.

Can someone from Unity please have a look?

styliann-eth avatar Jan 01 '22 18:01 styliann-eth

@ns2808 Do you have a repository or perhaps could you provide a project as a zip file where you are experiencing this issue?
It will help me determine the best way to fix your issue.

NoelStephensUnity avatar Jan 06 '22 20:01 NoelStephensUnity

This happened to us recently, we had a main prefab and 2 prefab variants that were added as network prefabs, we edited the main prefab, and sometimes on the parrelsync client clone it would get broken (both prefab variants ended up with the same value) The main project was fine, only the parrelsync clone got broken In order to fix that, we just changed some value in the prefab saved, and let the clone refresh.

Hope the info helps

rgarat avatar Jan 07 '22 16:01 rgarat

Add to our backlog - MTT-3052

ashwinimurt avatar Mar 29 '22 22:03 ashwinimurt

Can't believe this issue is still not fixed. This makes Netcode unusable with large number of NetworkObjects in a scene.

For anyone that has this issue, you can use this Editor script in your scene when it happens:

using UnityEngine;
using UnityEditor;
using Unity.Netcode;
using UnityEditor.SceneManagement;

namespace EditorTool
{
    /// <summary>
    /// Fix network ID duplicate issue
    /// </summary>

    public class FixNetworkID : ScriptableWizard
    {
        [MenuItem("Netcode/Fix Network IDs", priority = 500)]
        static void ScriptableWizardMenu()
        {
            ScriptableWizard.DisplayWizard<FixNetworkID>("Fix Network IDs", "Fix");
        }

        void OnWizardCreate()
        {
            NetworkObject[] nobjs = FindObjectsOfType<NetworkObject>();
            foreach (NetworkObject nobj in nobjs)
            {
                EditorUtility.SetDirty(nobj);
            }

            EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
        }

        void OnWizardUpdate()
        {
            helpString = "Use this tool when you receive error that there are duplicate NetworkObject ids.";
        }
    }
}

Marc477 avatar Aug 04 '22 01:08 Marc477

I'll look into this later again. I'll leave my current thoughts in this comment. https://docs.unity3d.com/ScriptReference/GlobalObjectId.html states: 'The ID changes when the object is moved to a new scene because the scene ID is part of the GlobalObjectID.' As long as Netcode, supports scene changes, this ID will keep on changing and this gets worse when clients are on different scenes than the server. The same NetworkObject could potentially have a lot of wrong IDs. This shouldn't be used as an identifier? The server should only have one ID for one spawned NetworkObject?

wlwl2 avatar Aug 16 '22 17:08 wlwl2

wlwl2 We do use the GetGlobalObjectIdSlow method during the validation period which only regenerates the GlobalObjectIdHash value if there is a change, if the script is being loaded, when entering into play mode, and when building a stand alone build.

There is a known issue where if the Reload Scene is unchecked via Project Settings->Editor->Enter Play Mode Options then this can cause issues with that unique identifier not being generated. So, always make sure that is the default (both darked out and appear unchecked) in order to assure the scene is reloaded when entering play mode.

I have also seen this bug happen when using some form of bootstrap scene loader that directly loads a scene using the SceneManager as opposed to using EditorSceneManager.OpenScene followed by EditorApplication.EnterPlaymode() , which the former way (SceneManager) skips the GlobalObjectIdHash generation that occurs within the editor context where the later way (EditorSceneManager.OpenScene) assures the GlobalObjectIdHash generation occurs before entering into play mode.

The bottom line is that if the editor scene reloading that occurs when entering into play mode is disabled or bypassed it could cause this issue to arise. For the near future up-and-coming update, I don't think this will get fixed. However, I will start looking at that section of the code and our current GlobalObjectIdHash generation process to see if I can come up with a better way to handle when that value is generated.

NoelStephensUnity avatar Aug 16 '22 21:08 NoelStephensUnity

@NoelStephensUnity That solved the issue for me! It's no problem if this issue doesn't get fixed in the short term.

wlwl2 avatar Aug 16 '22 23:08 wlwl2

This happens a lot if you use variant prefabs.

I have a base prefab called Unit. From it I have 4 prefab variants: Warrior, Archer, Mage, Priestess. If I have NetworkObject on the parent prefab, then after every edit to base prefab the Global Hash ID glitches out and becomes the same. I removed NetworkObject from the base prefab. Each time I encounter the Global Hash ID error, I remove and re-add NetworkObject from all the Variants (which is annoying).

jaros3 avatar Sep 18 '22 07:09 jaros3

I also got the same error, unity version 2021.3.6. I get it when I try to load a scene from an asset bundle. If the scene was present in the Build Settings, then there is no error

Anvarito avatar Jan 23 '23 09:01 Anvarito

@Anvarito Asset bundles are not fully supported yet, but it does sound like we will need to add a feature similar to NetworkManager.AddNetworkPrefab but for the scene within the asset bundle. NGO creates a hash table of scenes in the build list and uses the hash value to communicate to clients what scenes should be loaded or unloaded. Since the scene exists outside of the scenes in build list context, the hash value is not created. The only complexity involved with this that I could see is whether the asset bundle is already known by the clients or not (i.e. is downloaded from some remote server). If it is not, then the address of the asset bundle would need to be communicated as well.
If you wouldn't mind, could you create a separate feature request (a new issue with the feature request label) to support scene loading from asset bundles?

NoelStephensUnity avatar Jan 28 '23 22:01 NoelStephensUnity

I'm facing the same problem.

Looking through this issue - am I the only one wondering why we get the exact same GlobalObjectIdHash?

Because I get the exact same as others, not just same problem, but exactly same hash = 951099334

I'm on NetCode 1.2.0 and Unity 2021.3.20f1.

Laumania avatar Mar 26 '23 13:03 Laumania

@Laumania There are a few possible reasons for this. Could you provide details as to what you were doing when this occurred? Just collecting information on the various scenarios this could occur.

NoelStephensUnity avatar Mar 27 '23 02:03 NoelStephensUnity

Thanks for quick reply @NoelStephensUnity ! Well, I have had two different versions of this. The first one was the one I actually wrote about here yesterday, but I cannot reproduce it now... I'll get back if I figure out a way to reproduce it.

The second one, is more edge case, but still something that I think should be supported. The GlobalObjectIdHash is right now ONLY set in Unity on the OnValidate method. https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/blob/develop/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs#L45

However, that doesn't seems correct with the description of the AddNetworkPrefab method on NetworkManager.

This can be any GameObject with a NetworkObject component, from any source (addressables, asset
bundles, Resource.Load, **dynamically created**, etc)

https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/blob/develop/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs#L651

"Dynamically created" I would assume means exactly when components are added at runtime/dynamically?

Anyway, as it's something I need to support old mods in my game, that was made before the game was made multiplayer, its an edge case I know.

I just ended a live stream where I explained the problem to my viewers and ended up finding a hacky fix that could work for now, maybe, where I set it via Reflection - I know - but it's only to try and make old mods work - and it did work :) https://youtu.be/qvcPFUD4P6s?t=1529 (Feel free to remove the last part here with live stream link etc. if you don't feel it's relevant.)

Laumania avatar Mar 27 '23 16:03 Laumania

@Laumania Please disregard the **dynamically created** portion... it is inaccurate. Currently, GlobalObjectIdHash values are only generated from network prefab assets created within the editor.

NoelStephensUnity avatar Mar 27 '23 21:03 NoelStephensUnity

Oh yeah... watched your video and that was awesome! Your use of reflection and finding an alternate way to generate a unique uint hash identifier was refreshing. There are always ways to do things. 👍

However, I agree there should be an easier way to handle this than what you had to run through to get it working. No promises... but will definitely, at a minimum, look into exposing some of that stuff as public (like the hash XXHash should have some form of public accessor, etc.).

But indeed very clever how you got it to work! 😺 💯

NoelStephensUnity avatar Mar 28 '23 12:03 NoelStephensUnity

@NoelStephensUnity Thanks - I was also really excited when I figured it out - because it means players than use the 1500+ pieces of fireworks that is in the workshop (mods) already.

I agree it would be really nice to be able to do something like this, as in cases like my. But the game dev, need to be aware that they are responsible for actually having unique ids that is the same on both host and clients. I'm sure you figure something out - so far NetCode have been a joy and it's my first multiplayer project.

Laumania avatar Mar 28 '23 17:03 Laumania

Confusing bug... I'm not sure really why sometimes I've run into the "duplicate GlobalObjectIdHash" error message as noted in the original post.

@Laumania @NoelStephensUnity I can give you a bit of an update on why we all get the hash 951099334:

That's the hash of "GlobalObjectId_V1-0-00000000000000000000000000000000-0-0" which is sometimes returned by UnityEditor.GlobalObjectId.GetGlobalObjectIdSlow(this).ToString(); for some reason, even though if you also log this.gameObject.name you get a real object from your scene.

I do have prefab variants (but those are not the only prefabs affected) and I am using additive scene loading.

In general, something about using OnValidate for this seems fishy? What am I missing? I would really only want one GUID ever generated for an object, right? I wouldn't want it to keep getting regenerated?

Update:

Okay, to further add to my own confusion about this subject, it seems like Prefabs in the NetworkPrefabs list are actually all saved to file with a GlobalObjectIdHash of 951099334 instead of an unique id? So is that by design? Whatever you see in the Editor is not what's serialized to the .prefab file on disk. That id of 951099334 actually seems to represent "none" or "no ID"?

It seems like previously some of my prefabs with NetworkObjects were being written to disk with a real unique ID rather than the 951099334 and now that my prefabs are serialized on disk as 951099334 everything seems to be working correctly.

I'm really kind of perplexed now at what was causing this issue in the first place and how I solved it.

zachstronaut avatar Jul 19 '23 19:07 zachstronaut

I've documented 100% repro-rate bug with GlobalObjectId collisions in the Bossroom example which may be adjacent to this ticket, too:

https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/issues/2644

zachstronaut avatar Jul 26 '23 14:07 zachstronaut

@zachstronaut 951099334 is the "not assigned" GlobalObjectIdHash... which I have seen some (more recent) odd behaviors with GlobalObjectIdHash. I am looking into this issue currently, but it might be a few days before I get to the core issue.

NoelStephensUnity avatar Jul 27 '23 21:07 NoelStephensUnity

@zachstronaut

I would really only want one GUID ever generated for an object, right?

The issue with a GUID is that it is uniquely tied to the machine generating it (i.e. uses part of the NIC's MAC), but there is something about the GlobalObjectIdHash value generation that does seem to be problematic. I am trying to isolate what specifically happens (i.e. replicate it consistently). Will take a look at Boss Room to see if I can get the issue to replicate, if you can come up with some steps it would definitely help me track this issue down. 👍

NoelStephensUnity avatar Jul 30 '23 21:07 NoelStephensUnity

I'm following this issue with interest as the 951099334 issue is happening more frequently for us now. For now we've bypassed the issue by adding a button to call OnValidate on all our NetworkObjects.

I've always seen this on our parrelsync clone, however just this morning every prefab in the main editor project was 951099334 for one of our team members.

I've added some prints this morning to GenerateGlobalObjectIdHash to see what is going on, but there's not much of a stack with OnValidate unfortunately.

Some interesting tidbits from prints so far:

  • OnValidate seems to be called twice for each changed NetObj, most of the time, when doing a refresh on the parrelsync clone. The first time it gets the 951099334 value, but then it gets called again with the proper value.
  • One time it only got one OnValidate call, but it was the correct value.
  • On the main editor (ie not the clone) if I add a script to a netobj, it gets called 4 times:
    • 3 times from OnValidate (wrong, wrong, correct)
    • then a forth time from [Worker3], also correct.

I'll let you know if/when I get the failure case.

MikeSchurman avatar Jul 31 '23 14:07 MikeSchurman

@MikeSchurman Thank you very much for that information and for offering to provide more information if you run across it. I have a local/new branch that logs additional information to the console to help track the issue down and will provide you a link (if you wanted to see the additional info) once I push it to the repository.

NoelStephensUnity avatar Jul 31 '23 17:07 NoelStephensUnity

@NoelStephensUnity yes you can send me the link.

I had no luck reproducing the error yesterday (either me being methodical about it was enough to change the pattern, or my current tasks don't involve changing prefabs much).

But this morning I did get it, however the logs are mysterious. I added logs like this:

        internal void GenerateGlobalObjectIdHash()
        {
            Debug.Log($"GenerateGlobalObjectIdHash-{name}");
            // do NOT regenerate GlobalObjectIdHash for NetworkPrefabs while Editor is in PlayMode
            if (UnityEditor.EditorApplication.isPlaying && !string.IsNullOrEmpty(gameObject.scene.name))
            {
                return;
            }

            // do NOT regenerate GlobalObjectIdHash if Editor is transitioning into or out of PlayMode
            if (!UnityEditor.EditorApplication.isPlaying && UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }

            var globalObjectIdString = UnityEditor.GlobalObjectId.GetGlobalObjectIdSlow(this).ToString();
            Debug.Log($"GenerateGlobalObjectIdHash-{name}:" + globalObjectIdString);
            GlobalObjectIdHash = XXHash.Hash32(globalObjectIdString);
            Debug.Log($"GenerateGlobalObjectIdHash-{name}:" + GlobalObjectIdHash);
        }

But I don't see any log line printed with the 951099334 on server or client. There were a few cases of the if/play checks in GenerateGlobalObjectIdHash bailing out early, but, I never see the final print with the dreaded number.

I was thinking perhaps parrelsync is syncing while it's the bad value, but, I don't see it set to the bad value on non-clone. I do see OnValidate is being called from Odin inspector, which could be another possible issue.

edit: I should mention we're on NGO 1.3.1

MikeSchurman avatar Aug 01 '23 12:08 MikeSchurman

Ahh... yeah there have been several updates since v1.3.1 that might avoid some of the issues you are encountering. ParrelSync has been known to cause issues with prefabs and getting out of synchronization with the primary editor instance (editor that you are making changes to a prefab within).

I was diverted to a different issue yesterday so I haven't had a chance to get back to this bug search... but will definitely post a link to the branch once I have pushed it to the repository. 👍

NoelStephensUnity avatar Aug 01 '23 15:08 NoelStephensUnity

I'm getting the same issue but weirdly only in my second virtual player when using the MPPM package. Didn't manage to narrow down what was causing it, but I did delete my parallel syncs, enabled the Reload Domain option, and cleared my Library folder which has fixed everything so far.

thekiwicoder0 avatar Aug 12 '23 05:08 thekiwicoder0

@zachstronaut @rgarat @thekiwicoder0 I am currently investigating a user suggested fix that has been implemented in the fix/globalobjectidhash-serializing-invalid-values-mtt-77098 branch.

So far, the changes look promising and I haven't found any instabilities. There is one small block of code I am still investigating, but if you are feeling adventurous you could help test against that branch to see if you see any of the issues you have outlined above still occur when using those modifications. You can do this by replacing your com.unity.netcodegameobjects entry in your manifest file with this entry: "com.unity.netcode.gameobjects": "https://github.com/Unity-Technologies/com.unity.netcode.gameobjects.git?path=com.unity.netcode.gameobjects#fix/globalobjectidhash-serializing-invalid-values-mtt-77098",

NoelStephensUnity avatar Aug 14 '23 13:08 NoelStephensUnity