Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 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
0
Question by wesleywh · Aug 31, 2018 at 11:07 PM · networkingbonessync

UNet Sync Bone Rotations - Jittering

I'm so close but there is something I am still not doing right here.

All I need to do is sync the bone rotations across the network without having a crazy jitter effect. I'm using the basic components while I figure this out.


Here is the player gameobject. Everything that is disabled doesn't become enabled unless "isLocalPlayer == true". Everything that is disabled is not a network behavior either. Please note: I cannot show you any "V" scripts because they are not written by myself but are from the Invector Third Person Shooter package.

alt text


Setup Local Player Script:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.Networking;
 using Invector.vCharacterController;                    //to access "vThirdPersonController","vThirdPersonInput"
 using Invector.vShooter;                                //to access "vShooterMeleeInput"
 using Invector.vItemManager;                            //to access "vAmmoManager"
 using Invector.vCharacterController.vActions;           //to access "vGenericAction"
 
 [RequireComponent(typeof(NetworkIdentity))]             //needed by this script
 [RequireComponent(typeof(NetworkTransform))]            //not needed by this script, used to sync movements
 [RequireComponent(typeof(NetworkAnimator))]             //not needed by this script, used to sync animations
 public class SetupLocalPlayer : NetworkBehaviour {
 
     private Animator animator = null;
     private Quaternion head, neck, spine, chest;
     private Transform t_head, t_neck, t_spine, t_chest = null;
 
     void Start()
     {
         animator = GetComponent<Animator>();
         if (isLocalPlayer == true)
         {
             GetComponent<vThirdPersonController>().enabled = true;
             if (GetComponent<vThirdPersonInput>())
             {
                 GetComponent<vThirdPersonInput>().enabled = true;
             }
             if (GetComponent<vShooterMeleeInput>())
             {
                 GetComponent<vShooterMeleeInput>().enabled = true;
                 GetComponent<vShooterManager>().enabled = true;
                 GetComponent<vAmmoManager>().enabled = true;
                 GetComponent<vGenericAction>().enabled = true;
             }
             GetComponent<vHeadTrack>().enabled = true;
         }
         VerifyBones();
     }
 
     public override void PreStartClient()
     {
         GetComponent<NetworkAnimator>().SetParameterAutoSend(0, true);
         GetComponent<NetworkAnimator>().SetParameterAutoSend(1, true);
         GetComponent<NetworkAnimator>().SetParameterAutoSend(2, true);
         GetComponent<NetworkAnimator>().SetParameterAutoSend(3, true);
     }
 
     void VerifyBones()
     {
         if (t_head == null)
         {
             try
             {
                 t_head = animator.GetBoneTransform(HumanBodyBones.Head).transform;
             }
             catch (System.Exception e)
             {
                 Debug.LogError(e);
             }
         }
         if (t_neck == null)
         {
             try
             {
                 t_neck = animator.GetBoneTransform(HumanBodyBones.Neck).transform;
             }
             catch (System.Exception e)
             {
                 Debug.LogError(e);
             }
         }
         if (t_spine == null)
         {
             try
             {
                 t_spine = animator.GetBoneTransform(HumanBodyBones.Spine).transform;
             }
             catch (System.Exception e)
             {
                 Debug.LogError(e);
             }
         }
         if (t_chest == null)
         {
             try
             {
                 t_chest = animator.GetBoneTransform(HumanBodyBones.Chest).transform;
             }
             catch (System.Exception e)
             {
                 Debug.LogError(e);
             }
         }
     }
 
     void LateUpdate()
     {
         if (isLocalPlayer == true)
         {
             Cmd_RecieveRotations(t_head.localRotation, t_neck.localRotation, t_spine.localRotation, t_chest.localRotation);
         }
         else
         {
             SetLocalRotation();
         }
     }
 
     void SetLocalRotation()
     {
         t_head.localRotation = head;
         t_neck.localRotation = neck;
         t_spine.localRotation = spine;
         t_chest.localRotation = chest;
     }
 
     //Local Client -> Server
     [Command]
     void Cmd_RecieveRotations(Quaternion s_head, Quaternion s_neck, Quaternion s_spine, Quaternion s_chest)
     {
         RpcSetRotations(s_head, s_neck, s_spine, s_chest);
     }
 
     //Server -> All Connected Clients
     [ClientRpc]
     void RpcSetRotations(Quaternion s_head, Quaternion s_neck, Quaternion s_spine, Quaternion s_chest)
     {
         if (isLocalPlayer == false) //To prevent from calling on yourself in Lan Host Mode
         {
             head = s_head;
             neck = s_neck;
             spine = s_spine;
             chest = s_chest;
         }
     }
     
     //private void OnAnimatorIK()
     //{
     //    if (isLocalPlayer == false)
     //    {
     //        animator.SetBoneLocalRotation(HumanBodyBones.Head, head);
     //        animator.SetBoneLocalRotation(HumanBodyBones.Head, neck);
     //        animator.SetBoneLocalRotation(HumanBodyBones.Head, spine);
     //        animator.SetBoneLocalRotation(HumanBodyBones.Head, chest);
     //    }
     //}
 
 }

   

So this script works. I can see them look around but they snap back to their original rotations on what seems like every update and on every LateUpdate snap back to the synced rotation. So I get the effect like they are listening to some heavy death metal all day (jittering).

What am I doing wrong here?


Here you can see that the rotations are clearly coming through the network but is getting reset client side somehow. Not sure what...

alt text

playergameobject.png (34.8 kB)
jitter-opt.gif (376.8 kB)
Comment
Add comment · Show 5
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 wesleywh · Aug 31, 2018 at 11:10 PM 0
Share

Another note.

I am using the "Lan Host" and "Lan Client" options while I figure this out.

Also... I have tried this with OnAnimatorI$$anonymous$$() using "animator.SetBoneLocalRotation" but it has the same effect as the code above.

avatar image NoDumbQuestion · Sep 01, 2018 at 01:06 AM 0
Share

I am not sure how Unet work with [Command]. But the problem here is t_head.localRotation = head;

Over Network, Command can be lost and it might fail to send "c_head" value and on client, they will see as Quaternion.Identity (Or it might be the script called before and after receive network value). So your character head back and forth between default position + network position.

I would try to smooth head rotation to prevent this as HAC$$anonymous$$. Since I am not sure how Unet work.

And show us OnAnimatorIk() code. Also might be something wrong with execute Animation code.

avatar image wesleywh NoDumbQuestion · Sep 01, 2018 at 05:33 AM 0
Share

Tried adding in

 t_head.localRotation = Quaternion.Lerp(t_head.localRotation, head, Time.time * 0.1f);

with the same effect. I added a gif to help visualize what is happening for me. The animation for the head look is being taken care of by another script (this wasn't written by me). I am just referencing rotation values in this script without modifying anything else. The head look script is completely disabled on the Non - Network Identity players. Only this script is enabled on both Network ID players and Non Network ID players.

avatar image NoDumbQuestion wesleywh · Sep 01, 2018 at 06:01 AM 0
Share

Show us. The player gameobject. All script attach to it. You can try delete script 1 by 1. To see what wrong/script affect player.

I have a similar problem when all player on client side share same camera look. I kinda forgot to seperate main player and another player. Your problem might be the same

Show more comments

1 Reply

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

Answer by wesleywh · Sep 01, 2018 at 07:08 PM

Got it working. I switched everything around and made it so the server wasn't actually calling to the clients. The clients would always check the server for updates on rotations. I did this via "SyncVar".

So the [Client] function will tell the server to update its global variables (`[Command]` function) and wouldn't do anything else. Since I put [SyncVar] on my variables I don't need to explicitly call functions on clients anymore since the clients are always constantly checking for updates with the server. So it will notice the change in the variable and will update itself.

Now I smooth out the movements by running Lerp like @NoDumbQuestion suggested. Bam! It works like a charm. Here is my final code for anyone else trying to do what I just went through.

Nice thing about this is it will work with animations from mecanim quite nicely.

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.Networking;
 using Invector.vCharacterController;                    //to access "vThirdPersonController","vThirdPersonInput"
 using Invector.vShooter;                                //to access "vShooterMeleeInput"
 using Invector.vItemManager;                            //to access "vAmmoManager"
 using Invector.vCharacterController.vActions;           //to access "vGenericAction"
 
 [RequireComponent(typeof(NetworkIdentity))]             //needed by this script
 [RequireComponent(typeof(NetworkTransform))]            //not needed by this script, used to sync movements
 [RequireComponent(typeof(NetworkAnimator))]             //not needed by this script, used to sync animations
 public class SetupLocalPlayer : NetworkBehaviour {
 
     private Animator animator = null;
     [SyncVar] private Quaternion head;
     [SyncVar] private Quaternion neck;
     [SyncVar] private Quaternion spine;
     [SyncVar] private Quaternion chest;
     private Transform t_head, t_neck, t_spine, t_chest = null;
     [SerializeField] private float lerpRate = 90.0f;
 
     void Start()
     {
         animator = GetComponent<Animator>();
         if (isLocalPlayer == true)
         {
             GetComponent<vThirdPersonController>().enabled = true;
             if (GetComponent<vThirdPersonInput>())
             {
                 GetComponent<vThirdPersonInput>().enabled = true;
             }
             if (GetComponent<vShooterMeleeInput>())
             {
                 GetComponent<vShooterMeleeInput>().enabled = true;
                 GetComponent<vShooterManager>().enabled = true;
                 GetComponent<vAmmoManager>().enabled = true;
                 GetComponent<vGenericAction>().enabled = true;
             }
             GetComponent<vHeadTrack>().enabled = true;
         }
         VerifyBones();
     }
 
     public override void PreStartClient()
     {
         GetComponent<NetworkAnimator>().SetParameterAutoSend(0, true);
         GetComponent<NetworkAnimator>().SetParameterAutoSend(1, true);
         GetComponent<NetworkAnimator>().SetParameterAutoSend(2, true);
         GetComponent<NetworkAnimator>().SetParameterAutoSend(3, true);
     }
 
     void VerifyBones()
     {
         if (t_head == null)
         {
             try
             {
                 t_head = animator.GetBoneTransform(HumanBodyBones.Head).transform;
             }
             catch (System.Exception e)
             {
                 Debug.LogError(e);
             }
         }
         if (t_neck == null)
         {
             try
             {
                 t_neck = animator.GetBoneTransform(HumanBodyBones.Neck).transform;
             }
             catch (System.Exception e)
             {
                 Debug.LogError(e);
             }
         }
         if (t_spine == null)
         {
             try
             {
                 t_spine = animator.GetBoneTransform(HumanBodyBones.Spine).transform;
             }
             catch (System.Exception e)
             {
                 Debug.LogError(e);
             }
         }
         if (t_chest == null)
         {
             try
             {
                 t_chest = animator.GetBoneTransform(HumanBodyBones.Chest).transform;
             }
             catch (System.Exception e)
             {
                 Debug.LogError(e);
             }
         }
     }
 
     void LateUpdate()
     {
         if (isLocalPlayer == false)
         {
             t_head.localRotation = Quaternion.Lerp(t_head.localRotation, head, Time.deltaTime * lerpRate);
             t_neck.localRotation = Quaternion.Lerp(t_neck.localRotation, neck, Time.deltaTime * lerpRate);
             t_spine.localRotation = Quaternion.Lerp(t_spine.localRotation, spine, Time.deltaTime * lerpRate);
             t_chest.localRotation = Quaternion.Lerp(t_chest.localRotation, chest, Time.deltaTime * lerpRate);
         }
     }
 
     private void FixedUpdate()
     {
         if (isLocalPlayer == true)
         {
             TransmitRotations();
         }
     }
 
     [Client]
     void TransmitRotations()
     {
         if (isLocalPlayer == true)
         {
             Cmd_RecieveRotations(t_head.localRotation, t_neck.localRotation, t_spine.localRotation, t_chest.localRotation);
         }
     }
 
     [Command]
     void Cmd_RecieveRotations(Quaternion s_head, Quaternion s_neck, Quaternion s_spine, Quaternion s_chest)
     {
         head = s_head;
         neck = s_neck;
         spine = s_spine;
         chest = s_chest;
     }
 }
 

Here is what I looks like now:

alt text


fixed.gif (425.9 kB)
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

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

190 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 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

Sync Mecanim Trigger over network 1 Answer

Bad collision detection in client's view when using Networking (Mirror) 0 Answers

SyncVar, Command and Authority problem 1 Answer

How to sync SetActive at NetworkServer.Spawn() ? 1 Answer

how do i sync a GameObject? HELP PLZ!! 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