Author Topic: TNET Controller and Lerp Animation  (Read 3164 times)

gobble

  • Guest
TNET Controller and Lerp Animation
« on: November 05, 2013, 08:39:37 AM »
Hi and thanks for the server, bought the server last night and spent about 10 hours on it today messing around with the demo's.

I have a problem, see i am not a great programmer, and i am really struggling on this. Please go easy on me.

I have a script that took me like 2 weeks to make  :-[ but it works with unity's networking, but a cannot work out how to get it going using Tnet.

My problem. I am trying to sync animation and really not sure how to get my script working

  1. using UnityEngine;
  2. using TNet;
  3.  
  4. public class PlayerInput : TNBehaviour {
  5.        
  6.         public enum CharacterState {
  7.                 idle,
  8.                 walking
  9.         }
  10.        
  11.         public CharacterState _state;
  12.         public string idleAnimName;
  13.         public string walkAnimName;
  14.        
  15.     public int turnSpeed;
  16.     public int moveSpeed;
  17.  
  18.         void Awake() {
  19.         if (!tno.isMine) {
  20.          GetComponentInChildren<Camera>().enabled = false; // disable the camera of the non-owned Player;
  21.          GetComponentInChildren<AudioListener>().enabled = false; // Disables AudioListener of non-owned Player - prevents multiple AudioListeners from being present in scene.
  22.          }
  23.         }
  24.         void Start() {
  25.                 animation.wrapMode = WrapMode.Loop;
  26.         }
  27.        
  28.     void Update() {    
  29.                 if (tno.isMine) {
  30.                         InputMovement();
  31.                         CheckKey();
  32.                 } else {
  33.                         SyncedMovement();      
  34.                 }
  35.         }
  36.        
  37.        
  38.     void InputMovement() {
  39.             float h = Input.GetAxis("Horizontal");
  40.             float v = Input.GetAxis("Vertical");
  41.            
  42.             transform.Rotate( 0, h * turnSpeed * Time.deltaTime, 0 );
  43.             Vector3 moveAmount = transform.forward * v * moveSpeed;
  44.             rigidbody.MovePosition( transform.position + moveAmount * Time.deltaTime );
  45.             rigidbody.velocity = moveAmount + Vector3.Scale(rigidbody.velocity, new Vector3(0,1,0));
  46.     }
  47.        
  48.         void CheckKey()
  49.         {
  50.                 if(Input.GetKeyDown(KeyCode.W)) {
  51.                         _state = CharacterState.walking;
  52.                 } else if (Input.GetKeyUp(KeyCode.W)) {
  53.                         _state = CharacterState.idle;
  54.                 }
  55.                 PlayAnimation();
  56.         }
  57.        
  58.     void PlayAnimation() {      
  59.                 tno.SendQuickly("SyncAnimation",TNet.Target.AllSaved, _state);
  60.     }
  61.  
  62.         [RFC]
  63.         void SyncAnimation() {
  64.                 switch(_state)
  65.                 {
  66.                    case CharacterState.idle:
  67.                         animation.CrossFade(idleAnimName);
  68.                         break;
  69.                
  70.                    case CharacterState.walking:
  71.                         animation.CrossFade(walkAnimName);
  72.                         break; 
  73.                 }                      
  74.         }
  75.  
  76.         private float lastSynchronizationTime = 0f;
  77.         private float syncDelay = 0f;
  78.         private float syncTime = 0f;
  79.         private Vector3 syncStartPosition = Vector3.zero;
  80.         private Vector3 syncEndPosition = Vector3.zero;
  81.        
  82.         private void SyncedMovement() {
  83.             syncTime += Time.deltaTime;
  84.             rigidbody.position = Vector3.Lerp(syncStartPosition, syncEndPosition, syncTime / syncDelay);
  85.         }
  86.        
  87.         void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info) {
  88.             Vector3 syncPosition = Vector3.zero;
  89.             Vector3 syncVelocity = Vector3.zero;
  90.                 Quaternion syncRotation = Quaternion.Euler(0,0,0);
  91.                
  92.             if (stream.isWriting)
  93.             {
  94.                 syncPosition = rigidbody.position;
  95.                 stream.Serialize(ref syncPosition);
  96.          
  97.                 syncVelocity = rigidbody.velocity;
  98.                 stream.Serialize(ref syncVelocity);
  99.                        
  100.                         syncRotation = transform.rotation;
  101.                         stream.Serialize(ref syncRotation);
  102.             }
  103.             else
  104.             {
  105.                 stream.Serialize(ref syncPosition);
  106.                 stream.Serialize(ref syncVelocity);
  107.          
  108.                 syncTime = 0f;
  109.                 syncDelay = Time.time - lastSynchronizationTime;
  110.                 lastSynchronizationTime = Time.time;
  111.          
  112.                 syncEndPosition = syncPosition + syncVelocity * syncDelay;
  113.                 syncStartPosition = rigidbody.position;
  114.  
  115.                         stream.Serialize(ref syncRotation);
  116.                         transform.rotation = syncRotation;
  117.             }
  118.         }
  119.  
  120. }

I dont know if OnSerializeNetworkView is a thing in TNet, and tno.SendQuickly("SyncAnimation",TNet.Target.AllSaved, _state); is wrong but I dont understand why.

this script is my "multiplayer template" that i have made and converting to work has literally taken a full day and i still cant get it going (and i have only changed like 3 lines  :-[.


Once i see how it will work in this script i will be able to work everything out for the rest of my game. Please could you help me?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: TNET Controller and Lerp Animation
« Reply #1 on: November 05, 2013, 01:04:32 PM »
Your Awake() function gets called before tno.isMine gets set. You need to remove it and move the code into your Start() function.

Instead of setting rigidbody velocity and moving your rigidbody in update, you should do this in FixedUpdate -- this is where physics should take place, not Update.

Furthermore... You see your code where you do Input.GetAxis? Why not save the "h" and "v" values as member variables, and if (!tno.isMine) tno.Send("SetInput", Target.OthersSaved, h, v); ?

This way the value will be saved on all clients at once. Furthermore, also do this in FixedUpdate, not Update -- or add a check to only do a tno.Send when something changes by a notable margin (such as 5%).

With the Input.GetAxis only happening inside if (tno.isMine), and the input values synchronized across the network, your character will move predictably on all connected players.

You will still want to add a SyncRigidbody script onto your player though (but you can set it to sync infrequently -- twice per second should be more than enough).

Your animation should be synchronized when it actually changes as well, not every update. You're basically flooding the network.

gobble

  • Guest
Re: TNET Controller and Lerp Animation
« Reply #2 on: November 05, 2013, 02:00:31 PM »
Thanks Aren for the reply but im really lost now. ive updated the script trying to follow what your suggested but im getting an error.
do you have a super simple first/3rd person controller script(character controller or rigidbody) with 2 animations that you could share as an example? im not understanding this i thought it was the same as unity networking just with a few changes, but i cant seem to comprehend them. anyways started on trying to do this 9:30am and its now 3am  so im quite agitated. Thanks for your time, all i need is an example and i'll be on my way :)


  1. using UnityEngine;
  2. using TNet;
  3.  
  4. public class PlayerInput : TNBehaviour {
  5.        
  6.         public enum CharacterState {
  7.                 idle,
  8.                 walking
  9.         }
  10.        
  11.         public CharacterState _state;
  12.         public string idleAnimName;
  13.         public string walkAnimName;
  14.        
  15.     public int turnSpeed;
  16.     public int moveSpeed;
  17.        
  18.         private float h;
  19.         private float v;
  20.  
  21.         void Start() {
  22.                 animation.wrapMode = WrapMode.Loop;
  23.         if (!tno.isMine) {
  24.                 GetComponentInChildren<Camera>().enabled = false; // disable the camera of the non-owned Player;
  25.                 GetComponentInChildren<AudioListener>().enabled = false; // Disables AudioListener of non-owned Player - prevents multiple AudioListeners from being present in scene.
  26.         }
  27.         }
  28.        
  29.     void FixedUpdate() {       
  30.                 if (tno.isMine)
  31.                 {      
  32.                         InputMovement();
  33.                         CheckKey();
  34.                 } else {
  35.                         SyncedMovement();      
  36.                 }
  37.  
  38.                 if (!tno.isMine)
  39.                 {
  40.                         tno.Send("InputMovement", Target.OthersSaved, h, v);           
  41.                 }
  42.         }
  43.        
  44.         [RFC]
  45.     void InputMovement() {
  46.                 h = Input.GetAxis("Horizontal");
  47.         v = Input.GetAxis("Vertical");
  48.                
  49.             transform.Rotate( 0, h * turnSpeed * Time.deltaTime, 0 );
  50.             Vector3 moveAmount = transform.forward * v * moveSpeed;
  51.             rigidbody.MovePosition( transform.position + moveAmount * Time.deltaTime );
  52.             rigidbody.velocity = moveAmount + Vector3.Scale(rigidbody.velocity, new Vector3(0,1,0));
  53.     }
  54.        
  55.         void CheckKey()
  56.         {
  57.                 if(Input.GetKeyDown(KeyCode.W)) {
  58.                         _state = CharacterState.walking;
  59.                 } else if (Input.GetKeyUp(KeyCode.W)) {
  60.                         _state = CharacterState.idle;
  61.                 }
  62.                 SyncAnimation();
  63.         }
  64.        
  65.     void PlayAnimation() {      
  66.                 tno.SendQuickly("SyncAnimation",TNet.Target.AllSaved, _state);
  67.     }
  68.  
  69.         //[RFC]
  70.         void SyncAnimation() {
  71.                 switch(_state)
  72.                 {
  73.                    case CharacterState.idle:
  74.                         animation.CrossFade(idleAnimName);
  75.                         break;
  76.                
  77.                    case CharacterState.walking:
  78.                         animation.CrossFade(walkAnimName);
  79.                         break; 
  80.                 }                      
  81.         }
  82.  
  83.         private float lastSynchronizationTime = 0f;
  84.         private float syncDelay = 0f;
  85.         private float syncTime = 0f;
  86.         private Vector3 syncStartPosition = Vector3.zero;
  87.         private Vector3 syncEndPosition = Vector3.zero;
  88.        
  89.         private void SyncedMovement() {
  90.             syncTime += Time.deltaTime;
  91.             rigidbody.position = Vector3.Lerp(syncStartPosition, syncEndPosition, syncTime / syncDelay);
  92.         }
  93.        
  94.         void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info) {
  95.             Vector3 syncPosition = Vector3.zero;
  96.             Vector3 syncVelocity = Vector3.zero;
  97.                 Quaternion syncRotation = Quaternion.Euler(0,0,0);
  98.                
  99.             if (stream.isWriting)
  100.             {
  101.                 syncPosition = rigidbody.position;
  102.                 stream.Serialize(ref syncPosition);
  103.          
  104.                 syncVelocity = rigidbody.velocity;
  105.                 stream.Serialize(ref syncVelocity);
  106.                        
  107.                         syncRotation = transform.rotation;
  108.                         stream.Serialize(ref syncRotation);
  109.             }
  110.             else
  111.             {
  112.                 stream.Serialize(ref syncPosition);
  113.                 stream.Serialize(ref syncVelocity);
  114.          
  115.                 syncTime = 0f;
  116.                 syncDelay = Time.time - lastSynchronizationTime;
  117.                 lastSynchronizationTime = Time.time;
  118.          
  119.                 syncEndPosition = syncPosition + syncVelocity * syncDelay;
  120.                 syncStartPosition = rigidbody.position;
  121.  
  122.                         stream.Serialize(ref syncRotation);
  123.                         transform.rotation = syncRotation;
  124.             }
  125.         }
  126.  
  127. }



Getting this error
  1. parameters do not match signature
  2. PlayerInput.InputMovement (System.Single, System.Single)
  3. UnityEngine.Debug:LogError(Object)
  4. TNet.UnityTools:PrintException(Exception, CachedFunc, Object[]) (at Assets/TNet/Client/TNUnityTools.cs:83)
  5. TNet.UnityTools:ExecuteAll(List`1, String, Object[]) (at Assets/TNet/Client/TNUnityTools.cs:192)
  6. TNObject:Execute(String, Object[]) (at Assets/TNet/Client/TNObject.cs:316)
  7. TNObject:FindAndExecute(UInt32, String, Object[]) (at Assets/TNet/Client/TNObject.cs:361)
  8. TNManager:OnForwardedPacket(BinaryReader) (at Assets/TNet/Client/TNManager.cs:822)
  9. TNet.GameClient:ProcessPacket(Buffer, IPEndPoint) (at Assets/TNet/Client/TNGameClient.cs:684)
  10. TNet.GameClient:ProcessPackets() (at Assets/TNet/Client/TNGameClient.cs:627)
  11. TNManager:Update() (at Assets/TNet/Client/TNManager.cs:834)

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: TNET Controller and Lerp Animation
« Reply #3 on: November 06, 2013, 06:50:34 AM »
That's because you're sending 2 float values, but your function doesn't have any parameters.
  1.     void FixedUpdate() {       
  2.         if (tno.isMine)
  3.         {      
  4.             InputMovement();
  5.             CheckKey();
  6.         } else {
  7.             SyncedMovement();  
  8.         }
  9.  
  10.         if (!tno.isMine)
  11.         {
  12.                         h = Input.GetAxis("Horizontal");
  13.                         v = Input.GetAxis("Vertical");
  14.                         tno.Send("InputMovement", Target.AllSaved, h, v);
  15.         }
  16.     }
  17.    
  18.     [RFC]
  19.     void InputMovement(float h, float v) {
  20.        
  21.         this.h = h;
  22.         this.v = v;
  23.         transform.Rotate( 0, h * turnSpeed * Time.deltaTime, 0 );
  24.         Vector3 moveAmount = transform.forward * v * moveSpeed;
  25.         rigidbody.MovePosition( transform.position + moveAmount * Time.deltaTime );
  26.         rigidbody.velocity = moveAmount + Vector3.Scale(rigidbody.velocity, new Vector3(0,1,0));
  27.     }

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: TNET Controller and Lerp Animation
« Reply #4 on: November 06, 2013, 06:59:12 AM »
However what you're doing is not correct. You should be synchronizing the values causing the movement. Here's an example of doing it properly:
  1.         Vector2 mInput = Vector2.zero;
  2.    
  3.     void FixedUpdate()
  4.         {
  5.                 // Only the object's owner processes input
  6.         if (tno.isMine)
  7.         {
  8.                         mInput.x = Input.GetAxis("Horizontal");
  9.                         mInput.y = Input.GetAxis("Vertical");
  10.                         tno.Send("SetAxes", Target.OthersSaved, mInput);       
  11.         }
  12.                
  13.                 // Everyone moves the rigidbody using the input values
  14.                 transform.Rotate( 0, mInput.x * turnSpeed * Time.deltaTime, 0 );
  15.         Vector3 moveAmount = transform.forward * mInput.y * moveSpeed;
  16.         rigidbody.MovePosition( transform.position + moveAmount * Time.deltaTime );
  17.         rigidbody.velocity = moveAmount + Vector3.Scale(rigidbody.velocity, new Vector3(0,1,0));
  18.     }
  19.        
  20.         [RFC] void SetAxes (Vector2 v) { mInput = v; }

gobble

  • Guest
Re: TNET Controller and Lerp Animation
« Reply #5 on: November 06, 2013, 12:39:34 PM »
Thanks Aren ive got a basic idea on how it works and got my animations syncing, so thank you. I just want to check if the way im doing it is good practice, is it efficient? I have the TNSyncRigidbody script updates per second set to 1 and it is only slightly jerky which I am working on now.

  1. tno.Send("PlayAnimation", Target.All, _state.ToString());      

  1.         [RFC]
  2.         void PlayAnimation(string anim)
  3.         {
  4.                 switch(anim)
  5.                 {
  6.                    case "idle":
  7.                         animation.CrossFade(idleAnimName);
  8.                         break;
  9.                
  10.                    case "walking":
  11.                                 animation["Walk"].speed = 2;
  12.                         animation.CrossFade(walkAnimName);
  13.                         break; 
  14.                 }      
  15.         }

on another note, is there a way to view network bandwidth? eg upload KB/s?

Thanks for you help I really appreciate it.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: TNET Controller and Lerp Animation
« Reply #6 on: November 07, 2013, 05:12:33 AM »
I haven't added a way to check bandwidth (yet). It's something I still want to add, but haven't gotten around to just yet.

Yes, your function looks good to me, but make sure to call it only when the animation state changes. I'd also suggest changing the Target.All to be Target.AllSaved. This way new players that join your game will see the correct animation state right away.

gobble

  • Guest
Re: TNET Controller and Lerp Animation
« Reply #7 on: November 07, 2013, 08:51:35 AM »
Awesome thanks for the help Aren