Unity-Technologies / com.unity.netcode.gameobjects

Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.
MIT License
2.15k stars 435 forks source link

NetworkTransform child in prefab spawns at wrong position for other players under certain conditions #3082

Closed SubatomicPlanets closed 1 month ago

SubatomicPlanets commented 1 month ago

Description

When I talk about the childs position here I always mean the local space relative to it's parent.

I have a player prefab with a NetworkObject component and a NetworkTransform. I then have another gameObject(a sphere) as a child of this. The child also has a NetworkTransform and I moved it to 2,2,0 to be in a different position than the parent. Both NetworkTransforms are owner-authoritative. The NetworkTransform on the child also has "In Local Space" set to true. When I start as host everything works fine. I see the prefab spawn at 0,0,0 and it's child at 2,2,0. When I start another player as a client it also works and both player prefabs are at 0,0,0 and the children at 2,2,0.

However, when I set the position of the actual prefab root to 1,1,1 strange things start happening. It also happens if I keep it at 0,0,0 and use connection approval to set the players position to 1,1,1 (but connection approval is kinda broken in 2.0.0, so for that example I used the develop-2.0.0 branch where connection approval is fixed) So when I then start the host it seems fine (player spawns at 1,1,1 with child at 2,2,0). When I now start a client it also does the same. But this time the host displays the clients player wrong. The clients player is at 1,1,1 but the child is at 1,1,-1 instead of 2,2,0.

Basically the position of NetworkTransforms on children of my player prefab get synchronized wrongly if "In Local Space" is set to true, it is owner-authoritative, and the player doesn't spawn at 0,0,0 (I don't know if that all the requirements to reproduce it but I think so). This is a strange issue and I don't really know how to put it into words... I came across it in my game where the player prefab has hands that have NetworkTransforms. The player spawned at a spawn point but the hands were at some strange location.

Reproduce Steps

  1. Use the Bootstrap sample
  2. Add another gameObject (like a sphere or cube) with a NetworkTransform as a child in the player prefab
  3. Move the child object a bit (I set it to 2,2,0) so that it's offset from its parent
  4. Set both NetworkTransforms to be owner-authoritative
  5. Set "In Local Space" on the childs NetworkTransform to be true
  6. Set the position of the player prefab to something else than 0,0,0 (or use connection approval to set the position using the develop-2.0.0 branch)

Actual Outcome

The player prefab spawns correctly but the children inside spawn at strange positions for other players

Expected Outcome

The children should spawn correctly

Environment

NoelStephensUnity commented 1 month ago

@SubatomicPlanets Have you tried this using the fix for #3074? That would require you to update your manifest with this entry:

"com.unity.netcode.gameobjects":"https://github.com/Unity-Technologies/com.unity.netcode.gameobjects.git?path=com.unity.netcode.gameobjects#develop-2.0.0",

If the initial player position is not synchronized properly then the child's position will be offset improperly on the non-authority side.

SubatomicPlanets commented 1 month ago

Yes I have tried the develop-2.0.0 branch but the issue still persists. I will do some more testing later, I might also make an example project. I don't think this issue has anything to do with connection approval itself. I think it's a bug in the NetworkTransform.

SubatomicPlanets commented 1 month ago

@NoelStephensUnity I have an example project for you now. I made a new unity project in 6000.0.20f1 and added the netcode and multiplayer playmode packages. I also changed netcode to

"com.unity.netcode.gameobjects":"https://github.com/Unity-Technologies/com.unity.netcode.gameobjects.git?path=com.unity.netcode.gameobjects#develop-2.0.0",

in the manifest to use connection approval correctly.

Just open the example scene and test it as host. It will be correct up until now. The player spawns at 1,1,1 because I set that in the connection approval, and the child will be located at 1,1,0 in local space or 2,2,1 in world space. When you then join as a client (by using multiplayer play mode or a build) both players will be at 1,1,1 and both children at 2,2,1 world space. But on the hosts display this is not the case. Both players are at 1,1,1 but only the hosts child is at 2,2,1. The clients child is at 0,0,0!

Check the positions of both children on the host when testing. They should be the same, but they are not.

NetcodeExample.zip

Hope this helps!

NoelStephensUnity commented 1 month ago

Hi @SubatomicPlanets,

I ran through your example and was able to replicate the issue. It appears as if the child is losing its flags/settings under specific conditions which removes the local space flag which appears to be the most likely cause. Looking further into this.

NoelStephensUnity commented 1 month ago

@SubatomicPlanets I am still working on testing, but I believe I found where the issue was. Attached below is a semi-modified version of your project that also dynamically spawns a prefab upon a client connecting to the host (wanted to cover both player and dynamic prefab spawning to make sure). The attached project also points to the branch with the fix. NetcodeExample_Update.zip

NoelStephensUnity commented 1 month ago

The fixes in #3099 should be in the up-coming (it is being processed) NGO v2.1.0 update. 👍