Failing to sync a localEurlerAngles value
Options
chaozz
✭
I am working on a multiplayer game and have a script called Bend.cs that handles rotating a spine bone of my player to look up and down.
I use an RPC to do the actual rotation, and for testing purposes I use this RPC to do the rotation on all photontargets including myself. But it only makes my local player bend his spine, not on any of my clients. What am I doing wrong here?
I have been battling this problem for weeks, but I just don't see it.
I use an RPC to do the actual rotation, and for testing purposes I use this RPC to do the rotation on all photontargets including myself. But it only makes my local player bend his spine, not on any of my clients. What am I doing wrong here?
using UnityEngine; using System.Collections; public class Bend : MonoBehaviour { float sensitivityZ = 8F; float minimumZ = -60F; float maximumZ = 60F; float rotationZ = 0F; public GameObject Bone; PhotonView pv; void Start() { pv = this.GetComponent<PhotonView>(); } [RPC] void BendSpine_RPC (float rotz) { Bone.transform.localEulerAngles = new Vector3(0, Bone.transform.localEulerAngles.y,rotz); } void LateUpdate () { if (pv.isMine) { rotationZ += Input.GetAxis("Mouse Y") * sensitivityZ; rotationZ = Mathf.Clamp (rotationZ, minimumZ, maximumZ); pv.RPC ("BendSpine_RPC", PhotonTargets.All, rotationZ); } } }
I have been battling this problem for weeks, but I just don't see it.
0
Comments
-
Can you check if other clients get RPC calls and rotz is properly set?
How are objects instantiated? How is script attached to them?0 -
it's a multiplayer third person game, and all other RPC calls like syncing and ARMED pose are working.
rotz MUST be properly set, because it's responsible for the local animation as well, and that works.
the bend script posted here is a script on the player object, just like the movement script, shooting script etc. all which have working RPC calls. For movement I use onserialize routines.0 -
If RPC called properly and rotz is ok then setting transform for your object does not work for some reason. May be it is reset somewhere else in you code. Can you log Bone.transform.localEulerAngles right after setting in RPC?0
-
Can you log Bone.transform.localEulerAngles right after setting in RPC?
As soon as I debug.log the rotation in the RPC call, unity hangs. So something is pretty wrong.
Would anyone be willing to check out my project? Not exactly sure how, but this bone rotation thing is really putting a break on development.0 -
I updated my script. I have the bend.cs on every player, but only enabled on the local player.
The new script looks like this:using UnityEngine; using System.Collections; public class Bend : Photon.MonoBehaviour { float sensitivityZ = 8F; float minimumZ = -60F; float maximumZ = 60F; float rotationZ = 0F; public GameObject HeadMount; GameObject Bone; [RPC] void BendSpine_RPC (float rotZ) { GameObject rotBone; rotBone = GameObject.Find("CMan0010-M4-FBX/CMan0010-M3-CS_Hips/CMan0010-M3-CS_Spine/CMan0010-M3-CS_Spine1/CMan0010-M3-CS_Spine2"); rotBone.transform.localEulerAngles = new Vector3(0, rotBone.transform.localEulerAngles.y,rotZ); } void Start () { Bone = GameObject.Find("CMan0010-M4-FBX/CMan0010-M3-CS_Hips/CMan0010-M3-CS_Spine/CMan0010-M3-CS_Spine1/CMan0010-M3-CS_Spine2"); } void LateUpdate () { //if (photonView.isMine) { rotationZ += Input.GetAxis("Mouse Y") * sensitivityZ; rotationZ = Mathf.Clamp (rotationZ, minimumZ, maximumZ); Bone.transform.localEulerAngles = new Vector3(0, Bone.transform.localEulerAngles.y,rotationZ); HeadMount.transform.localEulerAngles = new Vector3(rotationZ * -1, 0, 0); // rotate the camera along with the spine. //} photonView.RPC ("BendSpine_RPC", PhotonTargets.Others, rotationZ); } }
When I add another network client that moves his mouse to rotates his spine, I get this warning in my console:Received unknown status code: QueueIncomingReliableWarning
UnityEngine.Debug:LogError(Object)
PhotonHandler:DebugReturn(DebugLevel, String) (at Assets/_IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/PhotonHandler.cs:170)
NetworkingPeer:DebugReturn(DebugLevel, String) (at Assets/_IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:802)
NetworkingPeer:OnStatusChanged(StatusCode) (at Assets/_IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:1330)
ExitGames.Client.Photon.EnetPeer:QueueIncomingCommand(NCommand)
ExitGames.Client.Photon.EnetPeer:ExecuteCommand(NCommand)
ExitGames.Client.Photon.<>c__DisplayClass11:<ReceiveIncomingCommands>b__f()
ExitGames.Client.Photon.EnetPeer:DispatchIncomingCommands()
ExitGames.Client.Photon.PhotonPeer:DispatchIncomingCommands()
PhotonHandler:Update() (at Assets/_IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/PhotonHandler.cs:76)
I feel I'm getting closer. Anyone have any ideas?0 -
QueueIncomingReliableWarning tells that too much incoming messages, may be because of too frequent rpc calls. It' hardly related to your issue directly.
For transforms, implementing OnPhotonSerializeView and interpolating is more appropriate solution than rpc call on every update.
Btw, may be transform for the bone set somewhere else that resets angles that you calculate in rpc.0 -
yes, i switched to OnPhotonSerializeView but without much luck
using UnityEngine; using System.Collections; public class NetworkCharacter : Photon.MonoBehaviour { Vector3 realPosition = Vector3.zero; Quaternion realRotation = Quaternion.identity; GameObject Bone; Animator anim; bool gotFirstUpdate = false; // Use this for initialization void Start () { anim = GetComponent<Animator>(); Bone = GameObject.Find("CMan0010-M4-FBX/CMan0010-M3-CS_Hips/CMan0010-M3-CS_Spine/CMan0010-M3-CS_Spine1/CMan0010-M3-CS_Spine2"); } // Update is called once per frame void Update () { if(!photonView.isMine ) { transform.position = Vector3.Lerp(transform.position, realPosition, 0.1f); transform.rotation = Quaternion.Lerp(transform.rotation, realRotation, 0.1f); } } public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) { if(stream.isWriting) { // This is OUR player. We need to send our actual position to the network. stream.SendNext(transform.position); stream.SendNext(transform.rotation); stream.SendNext(Bone.transform.localEulerAngles); stream.SendNext(anim.GetFloat("VerticalMove")); stream.SendNext(anim.GetFloat("HorizontalMove")); } else { // This is someone else's player. We need to receive their position (as of a few // millisecond ago, and update our version of that player. realPosition = (Vector3)stream.ReceiveNext(); realRotation = (Quaternion)stream.ReceiveNext(); Bone.transform.eulerAngles = (Vector3)stream.ReceiveNext(); anim.SetFloat("VerticalMove", (float)stream.ReceiveNext()); anim.SetFloat("HorizontalMove", (float)stream.ReceiveNext()); if(gotFirstUpdate == false) { transform.position = realPosition; transform.rotation = realRotation; gotFirstUpdate = true; } } } }
It all works, except for the bone rotation. I am not rotation the bone on other places.0 -
Why do you use Bone.transform.localEulerAngles for serialization? Can you send Bone.transform.rotation as you do for main object?0
-
let me try!0
-
Doesn't work. Neither .localRotation or .Rotation. But I am not setting the rotation, see here a snipplet of my bone bend routine, it follows the mouse Y movement and works great:
rotationZ += Input.GetAxis("Mouse Y") * sensitivityZ; rotationZ = Mathf.Clamp (rotationZ, minimumZ, maximumZ); Bone.localEulerAngles = new Vector3(0, Bone.transform.localEulerAngles.y,rotationZ-defaultBend);
it's that localEulerAngles that I need to sync over the network. but I have tried almost everything but CAN NOT get it to work0 -
You are sending 1 RPC per frame. This won't work.
You don't get 60 packages per second through our server but that's also not needed: You can send the current state and if that is different on the receiving client, that client will move the bone accordingly.
Please do the Marco Polo Tutorial and see how we use OnPhotonSerializeView(). With the help of that method and observing a single script on the GameObject, you can send the needed values and interpolate the rest.
http://doc.exitgames.com/en/pun/current ... marco-polo0 -
Hi Tobias, I am well aware of the fact RPC is not the way to go, it was for testing.
If you read two posts back you can see I already use OnPhotonSerializeView() and have added the bone rotation code. But it's not updating the bone rotation. I used the Quill18creates guides on Youtube and have been succesful so far, except for the bone
Here it is again and slightly updated:using UnityEngine; using System.Collections; public class NetworkCharacter : Photon.MonoBehaviour { Vector3 realPosition = Vector3.zero; Quaternion realRotation = Quaternion.identity; Vector3 realSpinepos = Vector3.zero; GameObject Bone; Animator anim; bool gotFirstUpdate = false; // Use this for initialization void Start () { anim = GetComponent<Animator>(); Bone = transform.Find("CMan0010-M4-FBX/CMan0010-M3-CS_Hips/CMan0010-M3-CS_Spine/CMan0010-M3-CS_Spine1/CMan0010-M3-CS_Spine2").gameObject; } // Update is called once per frame void Update () { if(!photonView.isMine ) { transform.position = Vector3.Lerp(transform.position, realPosition, 0.1f); transform.rotation = Quaternion.Lerp(transform.rotation, realRotation, 0.1f); Bone.transform.localEulerAngles = Vector3.Lerp(Bone.transform.localEulerAngles, realSpinepos, 0.1f); } } public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) { if(stream.isWriting) { // This is OUR player. We need to send our actual position to the network. stream.SendNext(transform.position); stream.SendNext(transform.rotation); stream.SendNext(Bone.transform.localEulerAngles); stream.SendNext(anim.GetFloat("VerticalMove")); stream.SendNext(anim.GetFloat("HorizontalMove")); } else { // This is someone else's player. We need to receive their position (as of a few // millisecond ago, and update our version of that player. realPosition = (Vector3)stream.ReceiveNext(); realRotation = (Quaternion)stream.ReceiveNext(); realSpinepos = (Vector3)stream.ReceiveNext(); anim.SetFloat("VerticalMove", (float)stream.ReceiveNext()); anim.SetFloat("HorizontalMove", (float)stream.ReceiveNext()); if(gotFirstUpdate == false) { transform.position = realPosition; transform.rotation = realRotation; Bone.transform.localEulerAngles = realSpinepos; gotFirstUpdate = true; } } } }
0 -
Doesn't work. Neither .localRotation or .Rotation.0
-
Did you manage to solve this problem? I'm having the same problem; I'm unable to synchronize my player's spine bone localRotation over the network.0
-
Yes, via serialization.0
-
Care to show your code? I'm also trying to do this inside OnPhotonSerializeView() and applying the rotation in the LastUpdate() because of the animation updates.
Thanks in advance!0 -
Yes, in short I ended up doing this: In mechanim, I made a float called Angle
Then in the spinal bend code on the player I do:anim.SetFloat ("Angle", angle);
Then in the serialization code, in isWriting:stream.SendNext(anim.GetFloat("Angle"));
And in the receive part:Angle = (float)stream.ReceiveNext();
And in the update of the serialization code:anim.SetFloat("Angle", Mathf.Lerp (anim.GetFloat ("Angle"), Angle, 0.1f));
0 -
Ah, you misunderstand, or I wasn't clear enough.
My problem is that I don't have a "bend back" animation, so I need to retrieve the spine bone and rotate it;void Start () { skinnedMeshRenderer = GetComponentInChildren<SkinnedMeshRenderer>(); foreach ( Transform boneTransform in skinnedMeshRenderer.bones ) { if ( boneTransform.name == "Bip01 Spine1" ) { // TODO: Really?! spineTransform = boneTransform; break; } } if ( spineTransform == null ) { Debug.LogError( "Failed to find the player's spine!" ); } } void Update () { upDownRotation -= Input.GetAxis("Mouse Y") * mouseSensitivity; upDownRotation = Mathf.Clamp( upDownRotation, minUpDownRotation, maxUpDownRotation ); } void LateUpdate () { float spineUpDownRotation = -upDownRotation / 2; spineTransform.localRotation = Quaternion.Euler( 0, 0, spineUpDownRotation ); }
This code works just fine for the local player, but I'm unable to synchronize it over the network;void OnPhotonSerializeView ( PhotonStream stream, PhotonMessageInfo info ) { // Our player? if ( stream.isWriting ) { stream.SendNext( transform.position ); stream.SendNext( transform.rotation ); stream.SendNext( playerAnimator.GetFloat("Speed") ); stream.SendNext( SpineController.spineTransform.localRotation ); } else { realPosition = (Vector3)stream.ReceiveNext(); realRotation = (Quaternion)stream.ReceiveNext(); playerAnimator.SetFloat( "Speed", (float)stream.ReceiveNext() ); SpineController.spineTransform.localRotation = (Quaternion)stream.ReceiveNext(); } }
This simply doesn't work. No error messages or anything...0 -
Read my previous post. Don't send the localrotation directly. Use a float in Mechanim.0
-
...and where/how should I use this float?0
-
The moment you set/change the angle on your local player. And how is in the first snippet of code I gave you.0
-
But - this doesn't have anything to do with the animations...?0
-
Then I suggest you ignore my approach and figure out a better way. This worked for me.0
-
But did your animation(s) include looking up/down? I have to "manually" adjust the player model's spine bone.0
-
No, I am manually adjusting the spine according to the Y-movement of the mouse.0
-
Can you show me the code where you actually adjust the rotation/angle of your model?1