Search Unity

PUN 2 cannot fix laggy movement

Discussion in 'Scripting' started by Andreas12345, Jul 8, 2019.

  1. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    I have setup up my char with this settings:

    upload_2019-7-8_21-20-45.png


    My code for for the networkPlayer is:

    Code (CSharp):
    1. public class NetworkPlayer : MonoBehaviourPunCallbacks, IPunObservable
    2. {
    3.  
    4.    
    5.     private Vector3 networkPosition;
    6.     private Quaternion networkRotation;
    7.     private float smoothing = 10.0f;
    8.  
    9.  
    10.     // Start is called before the first frame update
    11.     void Start()
    12.     {
    13.         if(!GetComponent<PhotonView>().IsMine)
    14.         {
    15.             Destroy(GetComponent<SplineFollower>());
    16.             tag = "OtherPlayer";
    17.         }
    18.      
    19.         networkPosition = transform.position;
    20.         networkRotation = transform.rotation;
    21.     }
    22.  
    23.       void Update()
    24.     {
    25.         if (!photonView.IsMine)
    26.         {
    27.          
    28.              transform.position = Vector3.Lerp(transform.position, networkPosition, Time.deltaTime * smoothing);
    29.              transform.rotation = Quaternion.Lerp(transform.rotation, networkRotation, Time.deltaTime * smoothing);
    30.         }
    31.     }
    32.  
    33.  
    34.  
    35.  
    36.     /// <summary>
    37.     /// Used to customize synchronization of variables in a script watched by a photon network view.
    38.     /// </summary>
    39.     /// <param name="stream">The network bit stream.</param>
    40.     /// <param name="info">The network message information.</param>
    41.     public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    42.     {
    43.      
    44.  
    45.        
    46.         if (stream.IsWriting)
    47.         {
    48.             stream.SendNext(transform.position);
    49.             stream.SendNext(transform.rotation);
    50.         }
    51.         else
    52.         {
    53.             networkPosition = (Vector3)stream.ReceiveNext();
    54.             networkRotation = (Quaternion)stream.ReceiveNext();
    55.         }
    56.     }
    57. }
    i have tried changing the smooth factor, but without success, the movement is local horrible :(

    Here is a video with my problem:

     
  2. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    I don't know much about Photon so sorry if this isn't useful, but I notice that you have a PhotonTransformView with synchronization settings for both position and rotation, but your script is also trying to update the position and rotation. Does the PhotonTransformView do that for you, or is what you are doing how it is supposed to work?
     
    goldcloud144 and Andreas12345 like this.
  3. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    The screenshot is a bit confusing. I have tried both: code solution and photon script solution. the problem is the same.
     
  4. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    You don't have bittorrent or anything on in the background do you? And have you checked to make sure that you are connected to your actual region rather than one which might cause lag?
     
  5. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    There is nothing in background, i also think that the code is ok, thats why i have no idea.
    The LAG is local. Local you should not see this big lags.
    The player moves with a fixed update on a spline (Dreamteck splines), but photon use update.
    I have no idea to solve this. maybe i need to deactivate player scripts on remote side?
    :(
     
  6. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Try Vector3.MoveTowards / Quaternion.RotateTowards instead with high speed value.
    Lerp doesn't work in the way you've wrote it.

    If you want a proper interpolation, there's way more to tackle than you think.
    You'd need to receive a time stamp from the server, and check against time stamp on the client to determine where that position should be in the current time frame. Then determine percentage between updates, and interpolate accordingly.

    Before you start diving into this rabbit hole, make sure there's no Photon interpolation available somewhere along those Photon scripts.

    I haven't used Photon, so you might probably want to ask on the Multiplayer sub-forum or specifically in the Photon thread instead.
     
    Andreas12345 likes this.
  7. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    I thought it is much easier with photon :(
     
  8. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    MoveTowards make more LAG
    I have tried this settings:
    upload_2019-7-9_19-24-30.png

    Extrapolate on/off makes no difference and network script is:

    Code (CSharp):
    1. public class NetworkPlayer : MonoBehaviour
    2. {
    3.     // Start is called before the first frame update
    4.     void Start()
    5.     {
    6.         if(!GetComponent<PhotonView>().IsMine)
    7.         {
    8.             Destroy(GetComponent<SplineFollower>());
    9.             tag = "OtherPlayer";
    10.         }
    11.     }
    12.  
    13.     // Update is called once per frame
    14.     void Update()
    15.     {
    16.        
    17.     }
    18. }
     
  9. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    The problem is the Photon forum is actually pretty inactive and there's just barely anyone there to respond, I myself have lost temper with Photon quite a few times over stuff like this and let's be real these guys aren't doing their asset for free they're looking to make money from it.

    The unity forums is oddly the only place you can get proper responses for these types of questions. I really hope that Unity hurry up and upgrade to their latest UNet alternative, I want to see multiplayer unity with proper support. I've gotten a bit off topic but I came across this weird issue where I had the editor making my other play move but the other play would move individually absolutely fine which is weird and no mention of this on the forums or anywhere else.

    I totally understand this guy's frustration.
     
    Andreas12345 likes this.
  10. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    I had the same yesterday, player moves without a reason.
    I need for my game multiplayer, because otherwise the game is a bit senseless.
    photon forum is dead, thats a bit idiotic with the photon forum, because i like to have a plan for 100 users, but without multiplayer support i dont need it.

    thats the reason why i wrote here, photon forum did not answer.
     
  11. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    Back to topic:
    You mean something like this for a solution?

    https://github.com/Landixus/Mobile-Multiplayer-Action-Game-in-Unity/blob/master/Underdog City/Assets/Scripts/Player/NetworkPlayer.cs

    Code (CSharp):
    1. using Photon.Pun;
    2. using UnityEngine;
    3.  
    4. namespace UnderdogCity
    5. {
    6.  
    7.     public class NetworkPlayer : MonoBehaviourPun, IPunObservable
    8.     {
    9.  
    10.         protected Player Player;
    11.         protected Vector3 RemotePlayerPosition;
    12.         protected float RemoteLookX;
    13.         protected float RemoteLookZ;
    14.         protected float LookXVel;
    15.         protected float LookZVel;
    16.  
    17.         private void Awake()
    18.         {
    19.             Player = GetComponent<Player>();
    20.  
    21.             //destroy the controller if the player is not controlled by me
    22.             if (!photonView.IsMine && GetComponent<Controller>() != null)
    23.                 Destroy(GetComponent<Controller>());
    24.         }
    25.  
    26.         public void Update()
    27.         {
    28.             if (photonView.IsMine)
    29.                 return;
    30.  
    31.             var LagDistance = RemotePlayerPosition - transform.position;
    32.  
    33.             //High distance => sync is to much off => send to position
    34.             if (LagDistance.magnitude > 5f)
    35.             {
    36.                 transform.position = RemotePlayerPosition;
    37.                 LagDistance = Vector3.zero;
    38.             }
    39.  
    40.             //ignore the y distance
    41.             LagDistance.y = 0;
    42.  
    43.             if (LagDistance.magnitude < 0.11f)
    44.             {
    45.                 //Player is nearly at the point
    46.                 Player.Input.RunX = 0;
    47.                 Player.Input.RunZ = 0;
    48.             }
    49.             else
    50.             {
    51.                 //Player has to go to the point
    52.                 Player.Input.RunX = LagDistance.normalized.x;
    53.                 Player.Input.RunZ = LagDistance.normalized.z;
    54.             }
    55.  
    56.             //jump if the remote player is higher than the player on the current client
    57.             Player.Input.Jump = RemotePlayerPosition.y - transform.position.y > 0.2f;
    58.  
    59.             //Look Smooth
    60.             Player.Input.LookX = Mathf.SmoothDamp(Player.Input.LookX, RemoteLookX, ref LookXVel, 0.2f);
    61.             Player.Input.LookZ = Mathf.SmoothDamp(Player.Input.LookZ, RemoteLookZ, ref LookZVel, 0.2f);
    62.  
    63.         }
    64.  
    65.         public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    66.         {
    67.             if (stream.IsWriting)
    68.             {
    69.                 stream.SendNext(transform.position);
    70.                 stream.SendNext(Player.Input.LookX);
    71.                 stream.SendNext(Player.Input.LookZ);
    72.                 stream.SendNext(Player.State);
    73.             }
    74.             else
    75.             {
    76.                 RemotePlayerPosition = (Vector3)stream.ReceiveNext();
    77.                 RemoteLookX = (float)stream.ReceiveNext();
    78.                 RemoteLookZ = (float)stream.ReceiveNext();
    79.                 var state = (Player.PlayerState)stream.ReceiveNext();
    80.  
    81.                 //Enter
    82.                 if (state == Player.PlayerState.TRANSITION && Player.State == Player.PlayerState.NORMAL)
    83.                     Player.StartCoroutine(Player.EnterCarAnimation());
    84.                 //Exit
    85.                 if (state == Player.PlayerState.TRANSITION && Player.State == Player.PlayerState.IN_CAR)
    86.                     Player.StartCoroutine(Player.ExitCarAnimation());
    87.  
    88.  
    89.                 Player.State = state;
    90.             }
    91.         }
    92.     }
    93. }
     
  12. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    If your character was moved with physics, RPC calling the positional and angular velocity to the rigidbody along with the actual position and rotation makes for relatively convincing in-between movement, between networked update calls.

    In your case of course, it probably isn't possible to cheat using physics since your guy doesnt have a rigidbody in the first place. Using lerp however follows the same logic. You want to make in-betweens, between networked update calls, not every frame.

    I don't recall the sample scenes in photon having such issues though, maybe check those out in more detail to see what they use and what they are doing?
     
    Andreas12345 likes this.
  13. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    i dont use a rigidbody
    the player move on a spline
    the legs are an animation
     
    Last edited: Jul 10, 2019
  14. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    I was actually referring Unity's Multiplayer Games (sub-forum), I'm pretty sure there's a photon thread. (At least it was there 2 years ago).
     
  15. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    This means something else modifies the position / rotation. Well, unless network position is a bit out of sync.

    MoveTowards on its own won't produce laggy results.
    Can you double check that you're not altering position / rotation anywhere else?

    Also, are you by any chance running server on the same machine?
    It could be that server receives less process quota (when Unity server is not focused), potentially reducing FPS, which may lead to stuttering on the clients as well.
     
    Andreas12345 likes this.
  16. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    I am running on the same machine, but i have in both windows stable 60FPS
    i have only one dreamteck spline follow controller that moves the player.

    I destroy the client component when it is not mine:
    Code (CSharp):
    1.  if(!GetComponent<PhotonView>().IsMine)
    2.         {
    3.             Destroy(GetComponent<SplineFollower>());
    4.             tag = "OtherPlayer";
    5.         }
    thats why i am confused, because local i should not have any problem with this stutter.
     
  17. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Try removing PhotonTransformView completely and syncing only via NetworkPlayer instead.
     
    Andreas12345 likes this.
  18. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    same issue:
    Here is my complete moving code:
    I use a snap code to snap to ground

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Events;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. namespace Dreamteck.Splines
    7. {
    8.     public delegate void SplineReachHandler();
    9.     [AddComponentMenu("Dreamteck/Splines/Spline Follower")]
    10.     public class SplineFollower : SplineTracer
    11.     {
    12.         public enum FollowMode { Uniform, Time }
    13.         public enum Wrap { Default, Loop, PingPong }
    14.         [HideInInspector]
    15.         public Wrap wrapMode = Wrap.Default;
    16.         [HideInInspector]
    17.         public FollowMode followMode = FollowMode.Uniform;
    18.  
    19.         [HideInInspector]
    20.         public bool autoStartPosition = false;
    21.  
    22.         [HideInInspector]
    23.         public bool autoFollow = true;
    24.         /// <summary>
    25.         /// Used when follow mode is set to Uniform. Defines the speed of the follower
    26.         /// </summary>
    27.         public float followSpeed
    28.         {
    29.             get { return _followSpeed; }
    30.             set
    31.             {
    32.                 if (_followSpeed != value)
    33.                 {
    34.                     if (value < 0f) value = 0f;
    35.                     _followSpeed = value;
    36.                 }
    37.             }
    38.         }
    39.  
    40.         /// <summary>
    41.         /// Used when follow mode is set to Time. Defines how much time it takes for the follower to travel through the path
    42.         /// </summary>
    43.         public float followDuration
    44.         {
    45.             get { return _followDuration; }
    46.             set
    47.             {
    48.                 if (_followDuration != value)
    49.                 {
    50.                     if (value < 0f) value = 0f;
    51.                     _followDuration = value;
    52.                 }
    53.             }
    54.         }
    55.  
    56.         [System.Obsolete("Deprecated in 1.0.8. Use result instead")]
    57.         public SplineResult followResult
    58.         {
    59.             get { return _result; }
    60.         }
    61.  
    62.         [System.Obsolete("Deprecated in 1.0.8. Use offsettedResult instead")]
    63.         public SplineResult offsettedFollowResult
    64.         {
    65.             get { return offsettedResult;  }
    66.         }
    67.  
    68.         public event SplineReachHandler onEndReached;
    69.         public event SplineReachHandler onBeginningReached;
    70.  
    71.         [SerializeField]
    72.         [HideInInspector]
    73.         private float _followSpeed = 1f;
    74.  
    75.         [SerializeField]
    76.         [HideInInspector]
    77.         private float _followDuration = 1f;
    78.  
    79.         private double lastClippedPercent = -1.0;
    80.  
    81.         private SplineResult from = new SplineResult();
    82.         private SplineResult to = new SplineResult();
    83.         private bool followStarted = false;
    84.  
    85.         //Snap Object
    86.         public GameObject road; //used to snap the bike on the road  //hide in inspector?
    87.         //GameObject computer;
    88.         //Animation
    89.         public Animator riderAnimator; //to play the pedaling animation when needed
    90.         public Animator wheelsAnimator; //to make the wheels play their rotate animation when needed
    91.         public Transform target; //waypoint target
    92.         public GameObject player;
    93.  
    94.        
    95.  
    96.  
    97.  
    98. #if UNITY_EDITOR
    99.         public bool editorSetPosition = false;  //true
    100. #endif
    101.  
    102.         private BicyclePowerSim bicycleSim;
    103.        
    104.  
    105.         protected override void Start()
    106.         {
    107.             bicycleSim = GetComponent<BicyclePowerSim>(); //get the BicyclePower Sim component
    108.             base.Start();
    109.             if (autoFollow && autoStartPosition) SetPercent(Project(GetTransform().position).percent);
    110.             //road = GameObject.FindWithTag("ground");
    111.             road = GameObject.Find("Level/ground");
    112.  
    113.             computer = GameObject.FindWithTag("SplinePath").GetComponent<SplineComputer>();
    114.  
    115.             //What Bicycle is active?
    116.             //CheckBicycle();
    117.  
    118.  
    119.         }
    120.  
    121.         protected override void LateRun()
    122.         {
    123.             base.LateRun();
    124.             if (autoFollow) AutoFollow();
    125.         }
    126.  
    127.         protected override void PostBuild()
    128.         {
    129.             base.PostBuild();
    130.             if (samples.Length == 0) return;
    131.             EvaluateClipped(_result, ClipPercent(_result.percent));
    132.             if (autoFollow && !autoStartPosition) ApplyMotion();
    133.         }
    134.  
    135.  
    136.  
    137.         private bool isInAeroPosition = false; //toggle to change the frontal area, affecting aero drag
    138.         private float power = 0; //the leg power we input on the bike
    139.                                  //Snap bike to the ground
    140.  
    141.         private float posShifter = 0.0f;
    142.        
    143.        // private float maxShifter = 0.0f;
    144.         void Update()
    145.         {
    146.             if (Input.GetKeyUp("left"))
    147.             {
    148.                 shiftLeft();
    149.                 /*if (splineFollower.motion.offset.x <= -2.1f)
    150.                 {
    151.                     splineFollower.motion.offset = new Vector3(0f, 0f);
    152.                 }*/
    153.             }
    154.  
    155.             if (splineFollower.motion.offset.x <= -2.0f)
    156.             {
    157.                 splineFollower.motion.offset = new Vector3(0f, 0f);
    158.             }
    159.  
    160.             if (Input.GetKeyUp("right"))
    161.             {
    162.                 shiftRight();
    163.                 if (splineFollower.motion.offset.x >= 2.1f)
    164.                 {
    165.                     splineFollower.motion.offset = new Vector3(0f, 0f);
    166.                 }
    167.             }
    168.  
    169.            
    170.            
    171.  
    172.  
    173.         }
    174.  
    175.         public void shiftLeft()
    176.         {
    177.             posShifter -= 0.2f;
    178.           //  Mathf.Clamp(posShifter, -2f, 2f);
    179.             splineFollower.motion.offset = new Vector3(posShifter, 0f);
    180.             Debug.Log("left pressed");
    181.         }
    182.  
    183.         public void shiftRight()
    184.         {
    185.  
    186.             posShifter += 0.2f;
    187.         //    Mathf.Clamp(posShifter, -2f, 2f);
    188.             splineFollower.motion.offset = new Vector3(posShifter, 0f);
    189.             Debug.Log("right pressed");
    190.            
    191.         }
    192.  
    193.  
    194.         public void Snap()
    195.         {
    196.             if (gameObject.tag == "Player")
    197.             {
    198.  
    199.                 //Raycast to get the slope normal and the road Y position to snap the bike on the road
    200.  
    201.                 RaycastHit hit = new RaycastHit();
    202.  
    203.                 float snapYPosition = this.transform.position.y;
    204.                 Vector3 normal = Vector3.up;
    205.  
    206.                 if (motion.applyPositionY == true)
    207.                 {
    208.                     motion.applyPositionY = false;
    209.                     Debug.Log("Set me false");
    210.                 }
    211.  
    212.  
    213.  
    214.  
    215.  
    216.                 if (Physics.Raycast(new Vector3(transform.position.x, transform.position.y + 0.1f, transform.position.z), -Vector3.up, out hit, Mathf.Infinity))
    217.                 {
    218.                     snapYPosition = hit.point.y;
    219.                     normal = hit.normal;
    220.                 }
    221.  
    222.  
    223.                 Vector3 position = this.transform.position;
    224.                 position.y = snapYPosition;
    225.  
    226.                 this.transform.position = position;
    227.  
    228.                 //get the inclinaison angle
    229.                 Vector3 temp = Vector3.Cross(normal, transform.forward);
    230.                 Vector3 d = Vector3.Cross(temp, normal);
    231.                 float angle = Mathf.Sign(d.y) * Mathf.Acos(Mathf.Clamp(normal.y, -1f, 1f));
    232.  
    233.                 //set the slope grade
    234.                 bicycleSim.slopeGrade = Mathf.Lerp(bicycleSim.slopeGrade, Mathf.Tan(angle) * 100, Time.deltaTime * 5);
    235.  
    236.                 //control input
    237.  
    238.                 power = 0; // no input we set the power at 0
    239.  
    240.                 // if (Input.GetKey(KeyCode.Space))
    241.                 //               power = 200; //force 200 watts of power on the bike
    242.                 //
    243.                 //           if (Input.GetMouseButton(0))
    244.                 //               power = bicycleSim.GetPowerforSpeed(20); //find the power needed to reach 20 km/h
    245.                 //
    246.                 //
    247.                 if (Input.GetMouseButton(1))
    248.                     bicycleSim.SetBrakeForce(1); //apply full brake force
    249.                 else
    250.                     bicycleSim.SetBrakeForce(0);
    251.  
    252.                 if (Input.GetKeyDown(KeyCode.T))
    253.                 {
    254.  
    255.                     if (isInAeroPosition)
    256.                     {
    257.                         isInAeroPosition = false;
    258.                         bicycleSim.frontalArea = 0.5f;
    259.  
    260.                     }
    261.                     else
    262.                     {
    263.                         isInAeroPosition = true;
    264.                         bicycleSim.frontalArea = 0.4f;
    265.                     }
    266.                     riderAnimator.SetBool("aero", isInAeroPosition); //set mecanim to aero position
    267.                 }
    268.  
    269.  
    270.                 //set the input power on the bike
    271.                 bicycleSim.SetPower(power);
    272.  
    273.                 //move the gameObject
    274.                 Vector3 direction = (target.transform.position - this.transform.position).normalized;  //target
    275.                 Vector3 newPos = transform.position + direction * (bicycleSim.speed / 3.6f) * Time.deltaTime;
    276.                 newPos.y = snapYPosition;
    277.                 // transform.position = newPos;
    278.  
    279.                 //rotate the gameObject
    280.  
    281.  
    282.                 Vector3 viewingVector = target.transform.position - transform.position;
    283.                 viewingVector.y = 0;
    284.                 if (viewingVector != Vector3.zero)
    285.                 {
    286.                     Quaternion targetRotation = Quaternion.LookRotation(viewingVector);
    287.                     transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 2f * Time.deltaTime);
    288.                 }
    289.  
    290.                 Quaternion slopeRotation = Quaternion.LookRotation(Vector3.Cross(transform.right, normal), normal);
    291.                 transform.rotation = Quaternion.Slerp(transform.rotation, slopeRotation, 5f * Time.deltaTime);
    292.  
    293.                 //Animation of the Rider
    294.                 //riderAnimator.speed = Mathf.Min(power / 50f, 2);
    295.                 riderAnimator.speed = 0;
    296.                 if (bicycleSim.centralSensor.GetCadence() > 0)
    297.                 {
    298.                     riderAnimator.speed = Mathf.Min(bicycleSim.centralSensor.GetCadence() / 50f, 2);
    299.                 }
    300.                 // riderAnimator.speed = Mathf.Min(GameObject.Find("FitnessEquipmentDisplay").GetComponent<FitnessEquipmentDisplay>().cadence / 50f, 2);
    301.                 wheelsAnimator.speed = Mathf.Min(bicycleSim.speed / 3.6f, 3);
    302.             }
    303.         }
    304.  
    305.         //end try
    306.  
    307.        
    308.  
    309.  
    310.         void AutoFollow()
    311.         {
    312.             if (gameObject.tag == "Player")
    313.             {
    314.                 _followSpeed = bicycleSim.speed;
    315.             }
    316.             else
    317.             {
    318.                 _followSpeed = followSpeed;
    319.             }
    320.             if (!followStarted && autoStartPosition) SetPercent(Project(GetTransform().position).percent);
    321.             followStarted = true;
    322.             switch (followMode)
    323.                  {
    324.  
    325.                //   case FollowMode.Uniform: Move(Time.deltaTime * _followSpeed); break;  //our bicycleSimSpeed here!?
    326.               //  case FollowMode.Uniform: Move ((Time.deltaTime + _followSpeed) * (bicycleSim.speed / 3.6f)); break;
    327.              //   case FollowMode.Uniform: Move (_followSpeed * (bicycleSim.speed / 3.6f)); break;
    328.                 case FollowMode.Uniform: Move(_followSpeed * Time.deltaTime / 3.6f); break;
    329.  
    330.  
    331.  
    332.                 case FollowMode.Time:
    333.                     if(_followDuration == 0.0) Move(0.0);
    334.                     else Move((double)Time.deltaTime / _followDuration);
    335.                     break;
    336.             }
    337.         }
    338.  
    339.         public void Restart(double startPosition = 0.0)
    340.         {
    341.             ResetTriggers();
    342.             followStarted = false;
    343.             SetPercent(startPosition);
    344.         }
    345.  
    346.         public override void SetPercent(double percent, bool checkTriggers = false)
    347.         {
    348.             if (clippedSamples.Length == 0) GetClippedSamplesImmediate();
    349.             base.SetPercent(percent, checkTriggers);
    350.             lastClippedPercent = percent;
    351.         }
    352.  
    353.         public override void SetDistance(float distance, bool checkTriggers = false)
    354.         {
    355.             base.SetDistance(distance, checkTriggers);
    356.             lastClippedPercent = ClipPercent(_result.percent);
    357.             if (samplesAreLooped && clipFrom == clipTo && distance > 0f && lastClippedPercent == 0.0) lastClippedPercent = 1.0;
    358.         }
    359.  
    360.         public void Move(double percent)
    361.         {
    362.             if(percent == 0.0) return;
    363.             if (clippedSamples.Length <= 1)
    364.             {
    365.                 if (clippedSamples.Length == 1)
    366.                 {
    367.                     _result.CopyFrom(clippedSamples[0]);
    368.                     ApplyMotion();
    369.                 }
    370.                 return;
    371.             }
    372.            
    373.             EvaluateClipped(_result, ClipPercent(_result.percent));
    374.             double startPercent = ClipPercent(_result.percent);
    375.             if (wrapMode == Wrap.Default && lastClippedPercent >= 1.0 && startPercent == 0.0) startPercent = 1.0;
    376.             double p = startPercent + (_direction == Spline.Direction.Forward ? percent : -percent);
    377.             bool callOnEndReached = false, callOnBeginningReached = false;
    378.             lastClippedPercent = p;
    379.             if(_direction == Spline.Direction.Forward && p >= 1.0)
    380.             {
    381.                 if (onEndReached != null && startPercent < 1.0) callOnEndReached = true;
    382.                 switch (wrapMode)
    383.                 {
    384.                     case Wrap.Default:
    385.                         p = 1.0;
    386.                         break;
    387.                     case Wrap.Loop:
    388.                         CheckTriggersClipped(UnclipPercent(startPercent), UnclipPercent(1.0));
    389.                         while (p > 1.0) p -= 1.0;
    390.                         startPercent = 0.0;
    391.                         break;
    392.                     case Wrap.PingPong:
    393.                         p = DMath.Clamp01(1.0-(p-1.0));
    394.                         startPercent = 1.0;
    395.                         _direction = Spline.Direction.Backward;
    396.                         break;
    397.                 }
    398.             } else if(_direction == Spline.Direction.Backward && p <= 0.0)
    399.             {
    400.                 if (onBeginningReached != null && startPercent > 0.0) callOnBeginningReached = true;
    401.                 switch (wrapMode)
    402.                 {
    403.                     case Wrap.Default:
    404.                         p = 0.0;
    405.                         break;
    406.                     case Wrap.Loop:
    407.                         CheckTriggersClipped(UnclipPercent(startPercent), UnclipPercent(0.0));
    408.                         while (p < 0.0) p += 1.0;
    409.                         startPercent = 1.0;
    410.                         break;
    411.                     case Wrap.PingPong:
    412.                         p = DMath.Clamp01(-p);
    413.                         startPercent = 0.0;
    414.                         _direction = Spline.Direction.Forward;
    415.                         break;
    416.                 }
    417.             }
    418.             CheckTriggersClipped(UnclipPercent(startPercent), UnclipPercent(p));
    419.             Evaluate(_result, UnclipPercent(p));
    420.             ApplyMotion();
    421.             if (callOnEndReached) onEndReached();
    422.             else if (callOnBeginningReached) onBeginningReached();
    423.             InvokeTriggers();
    424.         }
    425.  
    426.         public void Move(float distance)
    427.         {
    428.             if (distance < 0f) distance = 0f;
    429.             if (distance == 0f) return;
    430.             if (samples.Length <= 1)
    431.             {
    432.                 if (samples.Length == 1)
    433.                 {
    434.                     _result.CopyFrom(samples[0]);
    435.                     ApplyMotion();
    436.                 }
    437.                 return;
    438.             }
    439.             bool callOnEndReached = false, callOnBeginningReached = false;
    440.  
    441.             float moved = 0f;
    442.             int nextIndex = 0;
    443.             double clippedPercent = ClipPercent(_result.percent);
    444.             if (clippedPercent == 0.0 && lastClippedPercent == 1.0 && clipFrom == clipTo) clippedPercent = 1.0;
    445.             from.CopyFrom(_result);
    446.             to.CopyFrom(_result);
    447.  
    448.             if (_direction == Spline.Direction.Forward)
    449.             {
    450.  
    451.                 nextIndex = DMath.FloorInt(clippedPercent * (clippedSamples.Length - 1))-1;
    452.                 if (nextIndex < 0) nextIndex = 0;
    453.                 for (int i = nextIndex; i < clippedSamples.Length-1; i++)
    454.                 {
    455.                     if (ClipPercent(clippedSamples[i].percent) > clippedPercent) break;
    456.                     nextIndex = i;
    457.                 }
    458.             }
    459.             else
    460.             {
    461.                 nextIndex = DMath.CeilInt(clippedPercent * (clippedSamples.Length - 1)) + 1;
    462.                 if (nextIndex >= clippedSamples.Length) nextIndex = clippedSamples.Length - 1;
    463.                 for (int i = nextIndex; i >= 1; i--)
    464.                 {
    465.                     double percent = ClipPercent(clippedSamples[i].percent);
    466.                     if (i == clippedSamples.Length - 1) percent = 1.0;
    467.                     if (percent < clippedPercent) break;
    468.                     nextIndex = i;
    469.                 }
    470.             }
    471.             while (moved < distance)
    472.             {
    473.                 from.CopyFrom(to); //Get the current sample
    474.                 if (_direction == Spline.Direction.Forward)
    475.                 {
    476.                     nextIndex++;
    477.                     if ((samplesAreLooped && _result.percent >= clippedSamples[clippedSamples.Length - 1].percent && _result.percent < clippedSamples[0].percent) || (!samplesAreLooped && _result.percent >= clippedSamples[clippedSamples.Length - 1].percent) || nextIndex >= clippedSamples.Length)
    478.                     {
    479.                         if (onEndReached != null && lastClippedPercent < 1.0) callOnEndReached = true;
    480.                         if (wrapMode == Wrap.Default)
    481.                         {
    482.                             lastClippedPercent = 1.0;
    483.                             _result.CopyFrom(clippedSamples[clippedSamples.Length - 1]);
    484.                             CheckTriggersClipped(from.percent, _result.percent);
    485.                             break;
    486.                         }
    487.                         else if (wrapMode == Wrap.Loop)
    488.                         {
    489.                             CheckTriggersClipped(from.percent, clippedSamples[clippedSamples.Length-1].percent);
    490.                             from.CopyFrom(clippedSamples[0]);
    491.                             nextIndex = 1;
    492.                         }
    493.                         else if (wrapMode == Wrap.PingPong)
    494.                         {
    495.                             _direction = Spline.Direction.Backward;
    496.                             CheckTriggersClipped(from.percent, clippedSamples[clippedSamples.Length - 1].percent);
    497.                             from.CopyFrom(clippedSamples[clippedSamples.Length - 1]);
    498.                             nextIndex = clippedSamples.Length - 2;
    499.                         }
    500.                     }
    501.                 }
    502.                 else
    503.                 {
    504.                     nextIndex--;
    505.                     if ((samplesAreLooped && _result.percent <= clippedSamples[0].percent && _result.percent > clippedSamples[clippedSamples.Length - 1].percent) || (!samplesAreLooped && _result.percent <= clippedSamples[0].percent) || nextIndex < 0)
    506.                     {
    507.                         if (onBeginningReached != null && lastClippedPercent > 0.0) callOnBeginningReached = true;
    508.                         if (wrapMode == Wrap.Default)
    509.                         {
    510.                             lastClippedPercent = 0.0;
    511.                             _result.CopyFrom(clippedSamples[0]);
    512.                             CheckTriggersClipped(from.percent, _result.percent);
    513.                             break;
    514.                         }
    515.                         else if (wrapMode == Wrap.Loop)
    516.                         {
    517.                             CheckTriggersClipped(from.percent, clippedSamples[0].percent);
    518.                             from.CopyFrom(clippedSamples[clippedSamples.Length - 1]);
    519.                             nextIndex = clippedSamples.Length - 2;
    520.                         }
    521.                         else if (wrapMode == Wrap.PingPong)
    522.                         {
    523.                             _direction = Spline.Direction.Forward;
    524.                             CheckTriggersClipped(from.percent, clippedSamples[0].percent);
    525.                             from.CopyFrom(clippedSamples[0]);
    526.                             nextIndex = 1;
    527.                         }
    528.                     }
    529.                 }
    530.                 lastClippedPercent = ClipPercent(_result.percent);
    531.                 to.CopyFrom(clippedSamples[nextIndex]); //Get the next sample
    532.                 float traveled = Vector3.Distance(to.position, from.position);
    533.                 moved += traveled;
    534.                 if (moved >= distance)
    535.                 {
    536.                     float excess = moved - distance;
    537.                     double lerpPercent = 1.0 - excess / traveled;
    538.                     SplineResult.Lerp(from, to, lerpPercent, _result);
    539.                     if (samplesAreLooped)
    540.                     {
    541.                         if (_direction == Spline.Direction.Forward && from.percent > to.percent) _result.percent = DMath.Lerp(from.percent, 1.0, lerpPercent);
    542.                         else if (_direction == Spline.Direction.Backward && from.percent < to.percent) _result.percent = DMath.Lerp(1.0, to.percent, lerpPercent);
    543.                     }
    544.                     CheckTriggersClipped(from.percent, _result.percent);
    545.                     break;
    546.                 }
    547.                 CheckTriggersClipped(from.percent, to.percent);
    548.             }
    549.  
    550.             ApplyMotion();
    551.             if (callOnEndReached) onEndReached();
    552.             else if (callOnBeginningReached) onBeginningReached();
    553.             InvokeTriggers();
    554.         }
    555.     }
    556. }
    557.  
     
  19. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    hmm i have Camera in scene with the target Player view: MayBe it is better to put the camera to the player direct?

    its the same i tried :(

    makes no sense i deactivate the dreamteck spline when is not mine.
    i also deactivate other parts. The remote player have this:
    upload_2019-7-10_19-27-21.png
     
    Last edited: Jul 10, 2019
  20. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    I think i got it, will see how it work @ the end
     
  21. Martichoras

    Martichoras

    Joined:
    Aug 8, 2017
    Posts:
    3
    I have the same problem with PUN, and SmoothSyncPUN2 cannot solve it completely. Did you figure out how to solve this?
     
    radiantboy likes this.
  22. Andreas12345

    Andreas12345

    Joined:
    Oct 17, 2013
    Posts:
    526
    This was working for me: upload_2020-2-15_14-18-59.png
     
  23. ElSabadero

    ElSabadero

    Joined:
    Dec 7, 2018
    Posts:
    7
    Also worked for me thanks.
     
  24. radiantboy

    radiantboy

    Joined:
    Nov 21, 2012
    Posts:
    1,633
    Time correct speed 0 and position easing speed 0, they seem to make it smooth for me, would be good to know what u guys use :)