public virtual Vector3 Move(SimpleCharacterInput input, SimpleCharacterResult current)
    {
        Vector3 velocity      = TempRigidbody.velocity;
        var     moveDirection = new Vector3(input.horizontal, 0, input.vertical);

        {
            var moveDirectionMagnitude = moveDirection.sqrMagnitude;
            if (moveDirectionMagnitude > 1)
            {
                moveDirection = moveDirection.normalized;
            }

            var targetVelocity = moveDirection * moveSpeed;

            // Apply a force that attempts to reach our target velocity
            Vector3 velocityChange = (targetVelocity - velocity);
            velocityChange.x = Mathf.Clamp(velocityChange.x, -moveSpeed, moveSpeed);
            velocityChange.y = 0;
            velocityChange.z = Mathf.Clamp(velocityChange.z, -moveSpeed, moveSpeed);
            TempRigidbody.AddForce(velocityChange, ForceMode.VelocityChange);
        }
        if (input.isJump)
        {
            TempRigidbody.velocity = new Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
        }
        return(TempTransform.position);
    }
    private void SendResultCallback(SimpleCharacterResult resultParam)
    {
        var result = resultParam;

        // Discard out of order results
        if (result.timestamp <= lastTimestamp)
        {
            return;
        }

        lastTimestamp = result.timestamp;
        // Non-owner client
        if (!IsOwnerClient && !IsServer)
        {
            //Adding results to the results list so they can be used in interpolation process
            result.timestamp = Time.time;
            resultList.Add(result);
        }

        // Owner client
        // Server client reconciliation process should be executed in order to client's rotation and position with server values but do it without jittering
        if (IsOwnerClient && !IsServer)
        {
            // Update client's position and rotation with ones from server
            tempResult.rotation = result.rotation;
            tempResult.position = result.position;
            var foundIndex = -1;
            // Search recieved time stamp in client's inputs list
            for (var i = 0; i < inputList.Count; i++)
            {
                // If time stamp found run through all inputs starting from needed time stamp
                if (inputList[i].timestamp > result.timestamp)
                {
                    foundIndex = i;
                    break;
                }
            }
            if (foundIndex == -1)
            {
                // Clear Inputs list if no needed records found
                inputList.Clear();
                return;
            }
            // Replay recorded inputs
            for (var i = foundIndex; i < inputList.Count; ++i)
            {
                tempResult.rotation = Rotate(inputList[i], tempResult);
                tempResult.position = Move(inputList[i], tempResult);
            }
            // Remove all inputs before time stamp
            int targetCount = inputList.Count - foundIndex;
            while (inputList.Count > targetCount)
            {
                inputList.RemoveAt(0);
            }
        }
    }
 private void SendResult(SimpleCharacterResult result)
 {
     CallNetFunction("SendResult", DeliveryMethod.ReliableOrdered, FunctionReceivers.All, result);
 }
 public virtual Quaternion Rotate(SimpleCharacterInput input, SimpleCharacterResult current)
 {
     TempTransform.rotation = current.rotation;
     return(TempTransform.rotation);
 }