Search Unity

[Solved] How to stop game objects from spazzing out when initiating a transform Lerp?

Discussion in 'Multiplayer' started by asperatology, Oct 17, 2015.

  1. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    I would like to know what is the best way to get the remote client to say the game object is currently Lerping from point A to point B, and that the game object is not supposed to collide with a clone of itself. Currently, the game object would spaz out when it is moving through another game object.

    I was thinking about disabling colliders, but I don't know how to do so in [Command] and [ClientRPC].

    Here's what it looks like:



    And here's what my network code shows:

    Code (CSharp):
    1.     [Command]
    2.     public void CmdSplit(GameObject obj) {
    3.         //This is profoundly one of the hardest puzzles I had tackled. Non-player object spawning non-player object.
    4.         //Instead of the usual spawning design used in the Spawner script, the spawning codes here are swapped around.
    5.         //In Spawner, you would called on NetworkServer.SpawnWithClientAuthority() in the [ClientRpc]. Here, it's in [Command].
    6.         //I am guessing it has to do with how player objects and non-player objects interact with UNET.
    7.         GameObject split = MonoBehaviour.Instantiate(this.gameUnitPrefab) as GameObject;
    8.         split.transform.position = obj.transform.position;
    9.         NetworkIdentity managerIdentity = this.GetComponent<NetworkIdentity>();
    10.         NetworkServer.SpawnWithClientAuthority(split, managerIdentity.clientAuthorityOwner);
    11.         float angle = UnityEngine.Random.Range(-180f, 180f);
    12.         RpcSplit(obj, split, angle);
    13.     }
    14.  
    15.     [ClientRpc]
    16.     public void RpcSplit(GameObject obj, GameObject split, float angle) {
    17.         //We do not call on NetworkServer methods here. This is used only to sync up with the original game unit for all clients.
    18.         //This includes adding the newly spawned game unit into the Selection Manager that handles keeping track of all game units.
    19.         GameUnit original = obj.GetComponent<GameUnit>();
    20.         GameUnit copy = split.GetComponent<GameUnit>();
    21.         Copy(original, copy);
    22.         NavMeshAgent originalAgent = obj.GetComponent<NavMeshAgent>();
    23.         originalAgent.ResetPath();
    24.         NavMeshAgent copyAgent = copy.GetComponent<NavMeshAgent>();
    25.         copyAgent.ResetPath();
    26.  
    27.         this.splitGroupList.Add(new SplitGroup(original, copy, angle));
    28.         if (this.selectionManager == null) {
    29.             GameObject[] objs = GameObject.FindGameObjectsWithTag("SelectionManager");
    30.             foreach (GameObject select in objs) {
    31.                 SelectionManager manager = select.GetComponent<SelectionManager>();
    32.                 if (manager.hasAuthority) {
    33.                     this.selectionManager = manager;
    34.                 }
    35.             }
    36.         }
    37.         this.selectionManager.allObjects.Add(split);
    38.     }
    And the update code:

    Code (CSharp):
    1.     public void Update() {
    2.         this.ownerUnit.isSelected = false;
    3.         this.splitUnit.isSelected = false;
    4.  
    5.         //Known Bug: When splitting, the local client will have smooth transitions, but the remote clients will see stuttering animations caused by
    6.         //constant updates to the NavMeshAgent.
    7.         //If it's a bug that I couldn't fix, then make it a feature!
    8.         //Making splitting animations an obvious cue for the players to see.
    9.         Vector3 pos = Vector3.Lerp(this.origin, this.origin + this.rotationVector, this.elapsedTime);
    10.         if (this.ownerUnit == null || this.ownerUnit.gameObject == null) {
    11.             this.elapsedTime = 1f;
    12.             return;
    13.         }
    14.         this.ownerUnit.gameObject.transform.position = pos;
    15.         pos = Vector3.Lerp(this.origin, this.origin - this.rotationVector, this.elapsedTime);
    16.         if (this.splitUnit == null || this.splitUnit.gameObject == null) {
    17.             this.elapsedTime = 1f;
    18.             return;
    19.         }
    20.         this.splitUnit.gameObject.transform.position = pos;
    21.     }
    Code (CSharp):
    1.     public void UpdateSplitGroup() {
    2.         if (this.splitGroupList != null && this.splitGroupList.Count > 0) {
    3.             for (int i = 0; i < this.splitGroupList.Count; i++) {
    4.                 SplitGroup group = this.splitGroupList[i];
    5.                 if (group.elapsedTime > 1f) {
    6.                     group.Stop();
    7.                     if (group.splitUnit != null && !this.selectionManager.allObjects.Contains(group.splitUnit.gameObject)) {
    8.                         this.selectionManager.allObjects.Add(group.splitUnit.gameObject);
    9.                     }
    10.                     if (!this.selectionManager.allObjects.Contains(group.ownerUnit.gameObject)) {
    11.                         this.selectionManager.allObjects.Add(group.ownerUnit.gameObject);
    12.                     }
    13.                     this.removeList.Add(group);
    14.                 }
    15.                 else {
    16.                     //Some weird C# language design...
    17.                     group.Update();
    18.                     group.elapsedTime += Time.deltaTime / 3f;
    19.                     this.splitGroupList[i] = group;
    20.                 }
    21.             }
    22.         }
    23.  
    24.         if (this.removeList != null && this.removeList.Count > 0) {
    25.             foreach (SplitGroup group in this.removeList) {
    26.                 this.splitGroupList.Remove(group);
    27.             }
    28.             this.removeList.Clear();
    29.         }
    30.     }
    If more information is requested, I'll provide as much as possible.
     
  2. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    I solved this issue.

    The "spazzing" out animation on servers and clients are due to NetworkTransforms on the prefabs syncing the positions during the Lerping. When syncing NetworkTransforms, colliders are taken into account, and the positions are corrected after the Lerping finishes calculating the position during that elapsed time frame. This creates the spazzing out animation.

    To fix this, I just need to deactivate NetworkTransform.transformSyncMode to NetworkTransform.TransformSyncMode.SyncNone during the Lerping, and back to NetworkTransform.TransformSyncMode.SyncTransform once the Lerping has ended.

    Code (CSharp):
    1. //Enable syncing once the Lerping animation ends.
    2.  
    3. NetworkTransform transform = this.ownerUnit.GetComponent<NetworkTransform>();
    4. if (transform != null) {
    5.     transform.transformSyncMode = NetworkTransform.TransformSyncMode.SyncTransform;
    6. }
    7. transform = this.splitUnit.GetComponent<NetworkTransform>();
    8. if (transform != null) {
    9.     transform.transformSyncMode = NetworkTransform.TransformSyncMode.SyncTransform;
    10. }
    11.  
    12. //Replace NetworkTransform.TransformSyncMode.SyncTransform with NetworkTransform.TransformSyncMode.SyncNone to disable syncing.
    13.  
    The end result is a much more smoother Lerping animation when compared without the NetworkTransform.TransformSyncMode setup.