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.1k stars 430 forks source link

How does the client synchronize to the serve #2844

Open BensonMaZIHao opened 3 months ago

BensonMaZIHao commented 3 months ago

Hello guys, I am developing a project using LAN synchronization, I encountered a problem when I do it again, two player information synchronization I have done, but there are other objects in my scene also need to synchronize, for example, there is a ball in the scene, the ball can be caught in the hand or (client + server), (Client + server) Sync to client I found no problem, but in my client there is no way to move this ball it should be locked all the time in sync? The object has a Network GameObject and ClientNetworkTransform attached to it. I can't find the way, whether there is a solution my project is about to reach node.

netcode for gameobjects version :1.7.1 Unity version 2022.3.2 image image

NoelStephensUnity commented 3 months ago

Changing ownership of the in-scene placed NetworkObject will resolve the issue. By default, an in-scene placed NetworkObject is owned by the host-server. With ClientNetworkTransform (a.k.a owner authoritative), whoever the owner is of the NetworkObject has the authority to move the object.

Let me know if this resolves your issue?

BensonMaZIHao commented 3 months ago

ClientNetworkTransform

ClientNetworkTransform has been mounted on the object. I don't know why the client can't operate it.

The project is a VR project that wants to realize that objects in the scene can grasp the real-time synchronous position of each client. These have been realized, that is, there is no way to grasp objects on the client side like they have been set.

BensonMaZIHao commented 3 months ago

NetCodeWork.zip This is a Demo I tested, can you show me where the Settings are wrong, this Demo is PC

更改场景中放置的 NetworkObject 的所有权将解决该问题。默认情况下,场景中放置的 NetworkObject 归主机服务器所有。使用 ClientNetworkTransform(又称所有者权威),无论 NetworkObject 的所有者是谁,都有权移动对象。

让我知道这是否解决了您的问题?

BensonMaZIHao commented 3 months ago

Changing ownership of the in-scene placed NetworkObject will resolve the issue. By default, an in-scene placed NetworkObject is owned by the host-server. With ClientNetworkTransform (a.k.a owner authoritative), whoever the owner is of the NetworkObject has the authority to move the object.

Let me know if this resolves your issue?

Once I check Spawn With Observers, which I can't do on the client (move, scale, rotate), I see Position XYZ in the Inspector panel keeps getting assigned.

NoelStephensUnity commented 3 months ago

@BensonMaZIHao Hello! There were several places in your project that I went ahead and updated to save you some time and possibly provide you with alternate ways to handle things like selecting and moving an object in 3D space.

Regarding the Netcode side of things, your primary issue was that you were never changing the ownership of the interactable objects and so the ClientNetworkTransform (owner authoritative) would only synchronize to the Host player. I reduced your scripts down to 2 scripts:

PlayerLogic: All player oriented motion and selection happens here (you only want the player object to handle the ray casts). InteractableLogic: This is placed on all interactable objects. It uses a NetworkVariable to signal if a player has selected an object to avoid other players from grabbing the same object (you could expand on this, but for testing purposes I went ahead and set it up that way).

Anyway, I attached the updated project. Let me know if this resolves your issue and if it all makes sense? (I added a lot of comments for reference purposes).

InteractableObjects.zip

BensonMaZIHao commented 3 months ago

Thank you very, very much! I tested the Demo and it really saved my day.

There is also a question about whether I can assign values to GlobalobjectidHash manually, because all objects in our main project are generated dynamically and there is only one parent node. It bothers me that it is only generated in the Editor. There's no other way to solve this.

微信截图_20240322120303

In our project these are all different nodes, and they are all dynamically generated. How should I hang on NetWorkObjecks, only parentNode is not dynamically generated?

你好!在你的项目中,我继续更新了几个地方,以节省你一些时间,并可能为你提供处理事情的替代方法,比如在3D空间中选择和移动对象。

关于Netcode方面,您的主要问题是您从未更改可交互对象的所有权,因此ClientNetworkTransform(所有者权威)只会同步到主机播放器。我将您的脚本减少到 2 个脚本:

玩家逻辑:所有面向玩家的运动和选择都发生在这里(您只希望玩家对象处理光线投射)。 InteractableLogic:将其放置在所有可交互对象上。它使用 NetworkVariable 来指示玩家是否选择了某个对象,以避免其他玩家抓取相同的对象(您可以对此进行扩展,但出于测试目的,我继续以这种方式进行设置)。

无论如何,我附上了更新的项目。让我知道这是否解决了您的问题,以及这一切是否有意义? (我添加了很多评论以供参考)。

InteractableObjects.zip

NoelStephensUnity commented 3 months ago

With scenes you can just create one or more blank scenes (or scenes that contain a commonly shared set of in-scene GameObjects and components). You would then just load one of the blank scenes additively. You can load more than one instance of the same scene additively (i.e. the scenes are like a blank canvas but also are known by all clients).

For dynamically generating network prefabs, you will need to provide me with the details of how you are breaking apart/configuring your dynamically generated network prefabs in order for me to provide you with a more focused solution. There are many ways to handle this, but which one is the correct one depends upon how you are constructing your dynamically generated instances.

BensonMaZIHao commented 3 months ago

使用场景,您可以只创建一个或多个空白场景(或包含一组共同共享的场景内游戏对象和组件的场景)。然后,您只需以附加方式加载其中一个空白场景。您可以以附加方式加载同一场景的多个实例(即场景就像一个空白画布,但也被所有客户端知道)。

对于动态生成的网络预制件,您需要向我提供有关如何分解/配置动态生成的网络预制件的详细信息,以便我为您提供更有针对性的解决方案。有很多方法可以处理这个问题,但哪一种是正确的取决于你如何构建动态生成的实例。

Taking AssetsBundle as an example, I planned to mount NetWorkObjects directly when I made AssetsBundle, and then print AssetsBundle and load it into the project through network. But I found that the GlobalobjectidHash of the AssetsBundle that came in was the same, but not the same when I edited the AssetsBundle.

Our project is divided into editor and player. We plan to allow users to create objects by themselves (we will assign a unique ID to each object) to mark whether they can be synchronized during editing, and finally package them to the player side to dynamically add synchronization related Settings according to the mark. Obviously, the ID of NetworkObjects cannot be dynamically generated during runtime. There is no way to set this dynamically (I also understand why the ID is not generated at run time, so that each connected client uses the same ID to determine the object related information synchronization).

If we have to hang on Networkobjecks components when editing, it is impossible for us to execute every project in UnityEditor, which is contrary to our project. I can't find relevant cases of Demo, is there any relevant cases or solutions for this?

NoelStephensUnity commented 3 months ago

But I found that the GlobalobjectidHash of the AssetsBundle that came in was the same, but not the same when I edited the AssetsBundle.

That would be correct. Depending upon the modifications made to the AssetBundle and/or the project that opened it, the GlobalObjectIdHash value could be updated/changed since the GlobalObjectId is the hash value of the GlobalObjectId.GetGlobalObjectIdSlow value returned.

You might find this thread useful for what you are trying to do. It is a long thread, but towards the end (last several posts) a solution is presented.

Really, what I was wanting to know the details on was what aspects (i.e. just properties, adding additional NetworkBehaviours, etc) of your network prefabs (in the AssetBundle) would users be allowed to modify? Exposing the ability to modify/add NetworkBehaviours changes the network prefab which will definitely change the GlobalObjectIdHash value.

Read over the above thread provided and see if anything covered there helps you to resolve your issue, but I would recommend looking over your approach and determine if you could abstract away the need to update the network prefabs. Example:

The thread provided above addresses the complexities of allowing users to create their own content using NGO directly. The high-level alternate approach reduces your users' content creation down to a given set of classes (you provide) and interfaces they can implement and can be assigned to change the behavior of existing network prefabs. The former provides a wider range of flexibility for your users, but greatly increases the complexity on your side. The later has a reduce range of flexibility, but is much less complex for you in the end.

BensonMaZIHao commented 3 months ago

Many thanks! I have a hunch that this solution will work, I will try to test it, and if it works, it will be a perfect solution for us. Thank you very much for your patient answer! @NoelStephensUnity