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 wesleywh · Sep 16, 2018 at 12:23 AM · networkingsynchronizationbonesrotations

Photon PUN 2 - Bone Rotations Not Syncing

This should work from what I have seen but isn't. I want to sync the rotations of target bones across the network. Here is how I am doing it:

 private Transform local_head, local_neck, local_spine, local_chest = null;
     private Quaternion server_head, server_neck, server_spine, server_chest = Quaternion.identity;
 ...
 ...
 
 public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) //this function called by Photon View component
     {
         if (_syncBones == true)
         {
             if (stream.IsWriting)   //Authoritative player sending data to server
             {
                 //Bone Rotations
                 stream.SendNext(local_head.localRotation);
                 stream.SendNext(local_neck.localRotation);
                 stream.SendNext(local_spine.localRotation);
                 stream.SendNext(local_chest.localRotation);
             }
             else  //Network player copies receiving data from server
             {
                 //Bone Rotations
                 server_head = (Quaternion)stream.ReceiveNext();
                 server_neck = (Quaternion)stream.ReceiveNext();
                 server_spine = (Quaternion)stream.ReceiveNext();
                 server_chest = (Quaternion)stream.ReceiveNext();
 
                 lag = Mathf.Abs((float)(PhotonNetwork.Time - info.timestamp));
             }
         }
     }
 void LateUpdate()
     {
         if (GetComponent<PhotonView>().IsMine == false)
         {
             SyncBoneRotation();
         }
     }
     void SyncBoneRotation()
     {
         local_head.localRotation = Quaternion.Lerp(local_head.localRotation, server_head, Time.deltaTime * _boneLerpRate);
         local_neck.localRotation = Quaternion.Lerp(local_neck.localRotation, server_neck, Time.deltaTime * _boneLerpRate);
         local_spine.localRotation = Quaternion.Lerp(local_spine.localRotation, server_spine, Time.deltaTime * _boneLerpRate);
         local_chest.localRotation = Quaternion.Lerp(local_chest.localRotation, server_chest, Time.deltaTime * _boneLerpRate);
     }

I think what is happening is that the line stream.ReceiveNext() is setting the rotation to Quaternion.identity every other frame. Honestly I am just not sure if I am missing something obvious here....

Note: All of the local_* are getting set like the following:

 local_head = animator.GetBoneTransform(HumanBodyBones.Head).transform;
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 NoDumbQuestion · Sep 17, 2018 at 08:17 AM 0
Share

Did you set bone next frame after receive it?

In Editor, yes the editor. Did you see public property server_head/ server_neck change when receive new data or not?

avatar image wesleywh · Sep 17, 2018 at 10:22 PM 0
Share

I do see it change for one frame right when it receives it and reset back to the Quaternion.identity value every other frame. I viewed the change via a debug.log value since these are not public/Serialized variables.

The linked documentation is for an I$$anonymous$$ pass. This isn't ik, at least in terms of using OnAnimatorI$$anonymous$$() function.

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

ok now you have to check is it really sending quaternion.Identity during stream.IsWriting.

If it is, then 100% due to several animator bugs 2017.3+ related which I know they still can't fix it at 2018.3. All you have to do is not rotate when server_head = quaternion.Identity

If not, it can happen if you lost package or data (which not suppose to happen because PUN I know of not always check if full package have arrive in full and intact)

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

$$anonymous$$y //HAC$$anonymous$$ for animator bugs for my project is caching "local_head.localRotation" stuff during Update() and LateUpdate() so it can't be reset during whatever happen after LateUpdate() and FixedUpdate(). Which also the time Photon serialized got called.

avatar image wesleywh wesleywh · Jan 02, 2019 at 03:42 AM 0
Share

FYI you are right in that it is setting it back to quaternion.identity. However, this is failing... not sure why...

  tmp_headRot = (Quaternion)stream.ReceiveNext();
  ...
  ...
 
                 Debug.Log(tmp_headRot.GetType());
                 Debug.Log(tmp_headRot+ " == "+Quaternion.identity);
                 if (tmp_headRot != Quaternion.identity && tmp_headRot != this.correctBoneHeadRot)
                 {
                     Debug.Log("SETTING WITH VALUE: " + tmp_headRot);
                     headTime = 0.0f;
                     curHead = local_head.localRotation;
                     this.correctBoneHeadRot = tmp_headRot;
                 }


However, I see in the log SETTING WITH VALUE: (0.0f, 0.0f, 0.0f, 1.0f).... uuuuhhh what?

3 Replies

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

Answer by wesleywh · Jan 03, 2019 at 01:44 AM

I did the same thing I did for UNet: https://answers.unity.com/questions/1548530/unet-sync-bone-rotations-jittering.html

I didn't use Photons Method to send my updates across the network because it's insanely buggy. I did it manually:

     [SerializeField] private bool _syncBones = true;
     [SerializeField] private int _syncBonesRate = 5;
     [SerializeField] private float _boneLerpRate = 90.0f;
     private int currentBoneRate = 0;
 
 ..
 ..
 
 void FixedUpdate()
     {
         if (_syncBones == true && GetComponent<PhotonView>().IsMine == true)
         {
             if (currentBoneRate == _syncBonesRate)
             {
                 currentBoneRate = 0;
                 photonView.RPC("SyncRotations", RpcTarget.Others, local_head.localRotation, local_neck.localRotation, local_spine.localRotation, local_chest.localRotation);
             }
             else
             {
                 currentBoneRate += 1;
             }
         }
     }
     void SyncBoneRotation()
     {
         if (_syncBones == true && GetComponent<PhotonView>().IsMine == false)
         {
             local_head.localRotation = Quaternion.Lerp(local_head.localRotation, correctBoneHeadRot, Time.deltaTime * _boneLerpRate);
             local_neck.localRotation = Quaternion.Lerp(local_neck.localRotation, correctBoneNeckRot, Time.deltaTime * _boneLerpRate);
             local_spine.localRotation = Quaternion.Lerp(local_spine.localRotation, correctBoneSpineRot, Time.deltaTime * _boneLerpRate);
             local_chest.localRotation = Quaternion.Lerp(local_chest.localRotation, correctBoneChestRot, Time.deltaTime * _boneLerpRate);
         }
     }
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 Ooggaboogaloid · Feb 24, 2019 at 06:41 PM

mind posting your full script, here is what I have done

void OnAnimatorIK() { if(PV.IsMine) { anim.SetLookAtWeight(0.7f, 0.5f); anim.SetLookAtPosition(targetFocus.position); } }

 void Update()
 {
     if(PV.IsMine == true && _syncBones == true)
     {
         if (currentBoneRate == _syncBonesRate)
         {
             
             currentBoneRate = 0;
             PV.RPC("RPC_UpdateBoneRotations", RpcTarget.AllBuffered, local_head.localRotation, local_neck.localRotation, local_spine.localRotation, local_chest.localRotation);
         
         }
         else
         {
             currentBoneRate += 1;
         }
     }
     if (_syncBones == true && PV.IsMine == false)
     {
         Debug.Log("Attempting to sync bones for other clients");
         local_head.localRotation = Quaternion.Lerp(local_head.localRotation, correctBoneHeadRot, Time.deltaTime *  _boneLerpRate);
         local_neck.localRotation = Quaternion.Lerp(local_neck.localRotation, correctBoneNeckRot, Time.deltaTime * _boneLerpRate);
         local_spine.localRotation = Quaternion.Lerp(local_spine.localRotation, correctBoneSpineRot, Time.deltaTime * _boneLerpRate);
         local_chest.localRotation = Quaternion.Lerp(local_chest.localRotation, correctBoneChestRot, Time.deltaTime * _boneLerpRate);
     }
 }

 [PunRPC]
 void RPC_UpdateBoneRotations (Quaternion h, Quaternion n, Quaternion s, Quaternion c)
 {
     Debug.Log("SyncingBones");
     correctBoneHeadRot = h;
     correctBoneNeckRot = n;
     correctBoneSpineRot = s;
     correctBoneChestRot = c;
    
 }


and it aint syncing

Comment
Add comment · Show 6 · 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 wesleywh · Mar 05, 2019 at 04:13 AM 0
Share

Take it out of the Update() function it wont work there. I used to know why but I can't remember. That's why I have this in a fixed update function with the lerp functionality to smooth out the motion. Without the lerp it will be very jerky.

avatar image unity_x6Zl-zvtB8Mp_g · Aug 31, 2021 at 05:06 PM 0
Share

Hey man, I think it's pretty late to ask, but did u make it work?

avatar image wesleywh · Aug 31, 2021 at 05:26 PM 0
Share

Yes I did get this working. I was using the onvector package for this and they do some custom logic that required me to do this in the fixed update. I have since found a much better way to do this. Just sync all player inputs and the camera position. Then the bone rotation logic will be the same across all clients. You don't need to explicitly sync the individual bones. Saves on bandwidth too

avatar image unity_x6Zl-zvtB8Mp_g wesleywh · Aug 31, 2021 at 06:09 PM 0
Share

What do you mean by syncing camera pos? Add a photon view and photon transform on the camera?

avatar image wesleywh wesleywh · Aug 31, 2021 at 06:20 PM 0
Share

Yes I mean the physical position and rotation of the camera between clients needs to be exact. So you will need to make a dummy camera(just a empty gameobject not a real camera) for the none owned players. Then the owned player will send their real cameras position and rotation across the network to all the none owned versions dummy camera. Just make sure the none owned players are all looking at their own dummy cameras. That way its like everyone has their own camera but in reality are just following what the real player is sending.

For the above reason you CANNOT use the photon provided component to sync this. Its too stupid to figure it out. You have to have another custom component that is watching the camera (or receiving) position and rotation and sending it across the network. Then, across the network, that same component will set the dummy cameras position and rotation. No need to interpolate, it can be choppy because no one will see it.

Its complicated but this is a way that will allow you to have perfectly smooth syncing, always.

avatar image unity_x6Zl-zvtB8Mp_g wesleywh · Aug 31, 2021 at 06:37 PM 0
Share

Ty so much man! I hope it'll work.

avatar image
0

Answer by unity_x6Zl-zvtB8Mp_g · Aug 31, 2021 at 11:14 PM

Thank you for your help man! I used this method because it works better for me. This is my script if anyone is struggling with it.

 private Quaternion server_head;
 [SerializeField] private Transform Head;
 private void LateUpdate()
     {
         if (photonView.IsMine == false)
         {
             Head.localRotation = server_head;
         }
     }

     private void FixedUpdate()
     {
         if (photonView.IsMine == true)
         {
             Move();
             switch (stance)
             {
                 case CharacterStance.Standing:
                     if (inputs.Crouch.PressedDown()) { RequestStanceChange(CharacterStance.Crouching); }
                     break;

                 case CharacterStance.Crouching:
                     if (inputs.Crouch.PressedDown()) { RequestStanceChange(CharacterStance.Standing); }
                     break;
             }
             photonView.RPC("RPC_UpdateBoneRotations", RpcTarget.AllBuffered, Head.localRotation);
         }

     }


     [PunRPC]
     private void RPC_UpdateBoneRotations(Quaternion h)
     {
         server_head = h;
     }    


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

192 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 avatar image avatar image

Related Questions

UNet Sync Bone Rotations - Jittering 1 Answer

What is the best way to send data from a client to the server using Mirror? 1 Answer

uNet Network Sync Problem With Non-Player Object 0 Answers

Delay in synchronization in unity3d Unet 0 Answers

UNET Door sync 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