Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
1
Question by LutzKellen · Nov 15, 2016 at 08:46 AM · networkingmultiplayermultiplayer-networkingsynchronization

[UNET] Syncing the position of a non-player object such as a trap (no player authority whatsoever)

I have a game where players are dropped into an arena from a Lobby. Everything is working well, except the traps. There are animated sawblades that slide back and forth in the Z direction. On the host, everything is okay, as is expected. On the clients, their position is shifted (so that they dont even reach the same place as the host's). However, because I am properly using commands, the player still dies appropriately only when they are hit by the sawblades actual position (server/host position).

The issue is, when using a custom script, their position is not synced. When using a Network Transform component, their transform is constantly flickering, however one of the two flickering positions is the actual correct position.

Here is my custom sync position script: using UnityEngine; using System.Collections; using UnityEngine.Networking;

 public class CTFSawMove : NetworkBehaviour {
 
     [SyncVar (hook="SyncPositionValues")] private Vector3 syncPos;
     private Vector3 lastPos;
     private float threshold = 0.2f;
     private float lerpRate = 16.0f;
     [SerializeField] private Transform myTransform;
 
     public int speed;
     public int length;
 
     private float offset;
     public int bladeDamage;
     public Animator sawAnimation;
 
     public override void OnStartLocalPlayer() {
         sawAnimation = myTransform.GetComponent<Animator> ();
     }
 
     public override void OnStartClient() {
         sawAnimation = myTransform.GetComponent<Animator> ();
     }
 
     void Start () {
         offset = myTransform.position.z;
         syncPos = new Vector3(myTransform.position.x, myTransform.position.y, myTransform.position.z);
     }
 
     void Update() {
         MoveSaw ();
         LerpPosition ();
     }
 
     void MoveSaw() {
         myTransform.position = new Vector3(transform.position.x, transform.position.y, offset + (Mathf.PingPong(Time.time * speed, length)));    
     }
 
     void LerpPosition() {
         myTransform.position = Vector3.Lerp (myTransform.position, syncPos, Time.deltaTime * lerpRate);
     }
 
     void FixedUpdate () {
         TransmitPosition ();
     }
 
     [Command]
     void CmdProvidePositionToServer(Vector3 pos) {
         syncPos = pos;
     }
 
     [ClientCallback]
     void TransmitPosition() {
         if( isLocalPlayer && Vector3.Distance(myTransform.position, lastPos) > threshold ) {
             CmdProvidePositionToServer(myTransform.position);
             lastPos = myTransform.position;
         }
     }
 
     [Client]
     void SyncPositionValues(Vector3 latestPos) {
         syncPos = latestPos;
     }
 
     void OnTriggerEnter(Collider o){
         if (o.transform.tag == "Player" || o.transform.tag == "You") {
             CmdTellServerWhoWasHitByBlades (o.transform.name, bladeDamage);
         }
     }
 
     [Command]
     void CmdTellServerWhoWasHitByBlades(string hitName, int dmg) {
         GameObject go = GameObject.Find (hitName);
         go.GetComponent<CTFPlayerHealth> ().DeductHealth (dmg);
     }
 }
 

I've been googling this for quite some time, but it seems there isn't a single person who has ever had trouble with syncing non-player objects. Everyone just has issues with non-player objects that need authority.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by LutzKellen · Apr 20, 2017 at 03:02 AM

@ThinhHB I actually solved this issue some time back. I refactored all of my code to use a more structured Server Authoritative system. Client only ever sends inputs and just runs a local simulation of the server's scene. Along with that I had an issue where if I had movement turned on from the beginning (in the prefab), it would cause desync's in the movement.

So I solved that by turning off the movement script in the prefab, spawning the prefab, and then using an RPC to turn on the movement script for all clients.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ThinhHB · Apr 20, 2017 at 11:27 AM 0
Share

Nice solution then ;)

avatar image
0

Answer by ThinhHB · Apr 19, 2017 at 01:44 PM

I've worked on some multiplayer projects with UNET, and faced the same problem with sync NPC objects states. My solution was (It worked for me already) :

  • The NPC on server will take the authority (both transform + physics collision)

  • Server NPC will transmit it's position to clients (include Local clients).

  • Client replicate the positions they received from Server.

  • So, the lerping task will execute only on clients, not on Server.

  • The same with physics collisions, I would disable NPC's collider on clients, so the OnTriggerEnter() will only be called on Server.

Take a look into your code, I see some problems:

  • The local take the authority on Transform, it transmit it's position to server, but also do the lerping task, I think It cause position flicking on clients.

  • It look like you let the Local take the physics collision authority too. But, if you not disable the Collider on other places (Server, remote clients), the OnTriggerEnter() will be call in all places, may cause some warning messages. I think it not good ;)

Some more suggestions :

  • With the simple moving (in your case, the trap only moving in one coordinate, and just slide back and forth), we dont need to sync all of it positions, just need to sync when and where it start sliding, that enought infomation for clients to replicating NPC's state, instead of sending too much positions, in case you have a lot of network bandwidth.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by jeck001 · May 30, 2017 at 01:27 PM

hello @LutzKellen I am facing same problem. Host can easily drag a non player object which is seen from client side also. but when client try to drag that same object then client not able to do it.

    public class OnTouchTest :  NetworkBehaviour
     {
 private Transform myTransform;
 [SerializeField] float lerpRate = 15;
 [SyncVar] private Vector3 syncPos;
 [SyncVar]
 private GameObject objectID;
 private NetworkIdentity objNetId;

 private Vector3 lastPos;
 private float threshold = 0.5f;

 void Start () {
     if (isLocalPlayer) {
         objectID = GameObject.FindGameObjectWithTag ("cubeObject"); 
         myTransform = objectID.GetComponent<Transform> ();
     }
 }


 void FixedUpdate () {
     TransmitPosition ();
     LerpPosition ();
 }

 void LerpPosition () {
     if (!isLocalPlayer) {
         objectID.transform.position = Vector3.Lerp (objectID.transform.position, syncPos, Time.deltaTime * lerpRate);
     }
 }

 [Command]
 void Cmd_ProvidePositionToServer (Vector3 pos) {
     syncPos = pos;
 }

 [ClientCallback]
 void TransmitPosition () {
         Cmd_ProvidePositionToServer (objectID.transform.position);
         lastPos = objectID.transform.position;
 }

}

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image LutzKellen · May 30, 2017 at 05:12 PM 0
Share

Read below for information I wrote regarding your question before reading your code.

The issue in your code is that you have Cmd_ProvidePositionToServer(objectID.transform.position); inside of a ClientCallback.

ClientCallbacks can only be run on clients, and cannot be run on the server/host. However, ClientCallbacks can only be called from the server/host. Everything inside of that function will run on the clients.

Commands can only be run on the server/host, but can only be called from clients. Everything inside of the Command function will run on the server/host.

With this knowledge you can see that you are only ever calling Cmd_ProvidePositionToServer in a ClientCallback, which means that your Command is only executed after the server/host calls the ClientCallback. You need to call the Command when your local client tries to move the object.

Example of how your current game runs:

  1. The host attempts to drag the object.

  2. The object is moved, the host sends a ClientCallback called TransmitPosition() to update the clients on where the object's new position is.

  3. The client receives the ClientCallback TransmitPosition() and runs the code:

            Cmd_ProvidePositionToServer (objectID.transform.position);
              lastPos = objectID.transform.position;
    
    
  4. The client calls the Command Cmd_ProvidePositionToServer()

  5. The server/host receives the Command and says syncPos = pos; This effectively updates the host with information the host already knows.

  6. The client attempts to drag the object but nothing happens (or nothing is sync'd) because no information is ever sent across the network when the client drags the object.


I am assu$$anonymous$$g by "client not able to do it" you mean the client can move the object in their scene, but no one else sees the object has moved?

If that is the case, you are not properly telling the server that you are attempting to move it. If you are unable to move the object, then it is either your code is incorrect (I would check your variables/click listener), or the input you are sending to the host is not being applied on the host.

If the input you are sending is not being applied on the host, then I would double check that you are sending the information, then double check that you are attempting to move the object with the new information.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

119 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

how to split player objects over network? 0 Answers

local scale network 0 Answers

Error when using NetworkList "Don't know how to serialize List`1 " 0 Answers

How to make my game multiplayer? 1 Answer

UDP Client receiving Disposed error 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges