Guest User

Updated PlayerMovement

a guest
Aug 16th, 2023
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 34.00 KB | None | 0 0
  1.  
  2. using System.Collections;
  3. using UnityEngine;
  4. using DG.Tweening;
  5. using FishNet.Connection;
  6. using FishNet.Object;
  7. using FishNet.Managing.Timing;
  8. using FishNet.Object.Prediction;
  9. using FishNet.Transporting;
  10.  
  11. /*
  12. *
  13. * See TransformPrediction.cs for more detailed notes.
  14. *
  15. */
  16.  
  17. [RequireComponent(typeof(Rigidbody))]
  18. public class PlayerMovement : NetworkBehaviour
  19. {
  20.     #region delegates
  21.     public delegate void OnLand();
  22.     public static event OnLand onLand;
  23.  
  24.     public delegate void OnAirborne();
  25.     public static event OnAirborne onAirborne;
  26.  
  27.     public delegate void OnCrouch();
  28.     public static event OnCrouch onCrouch;
  29.  
  30.     public delegate void OnUncrouch();
  31.     public static event OnUncrouch onUncrouch;
  32.  
  33.     public delegate void OnJump();
  34.     public static event OnJump onJump;
  35.     #endregion
  36.  
  37.     #region values
  38.     [ReadOnlyInspector] public bool isSliding;
  39.     [ReadOnlyInspector] public bool isVaulting;
  40.     [ReadOnlyInspector] public bool isCrouching;
  41.     [ReadOnlyInspector] public bool isStepping;
  42.  
  43.     [Header("Input")]
  44.     [SerializeField] private KeyCode _jumpKey = KeyCode.Space;
  45.     [SerializeField] private KeyCode _sprintKey = KeyCode.LeftShift;
  46.     [SerializeField] private KeyCode _crouchKey = KeyCode.C;
  47.     [SerializeField] private KeyCode _vaultKey = KeyCode.Space;
  48.  
  49.     [Header("References")]
  50.     [SerializeField] private StaminaSystem _staminaSystem;
  51.     [SerializeField] private PlayerStateManager _playerStateManager;
  52.     [SerializeField] private Transform _orientation;
  53.  
  54.     [Header("Movement")]
  55.     [SerializeField] private float _walkSpeed = 1.75f;
  56.     [SerializeField] private float _sprintSpeed = 5f;
  57.     [SerializeField] private float _crouchSpeed = 0.75f;
  58.     [SerializeField] private float _groundDrag = 5f;
  59.     [SerializeField] private float _airSpeed = 3.5f;
  60.     [SerializeField] private float _lerpGroundSpeedRate = 3f;
  61.     [SerializeField] private float _lerpCrouchSpeedRate = 10f;
  62.     [SerializeField] private float _lerpSprintSpeedRate = 10f;
  63.     [HideInInspector] public Vector3 moveDirection;
  64.  
  65.     [Header("Sliding")]
  66.     [SerializeField] private float _slideSpeed = 20f;
  67.     [SerializeField] private float _slideSpeedMultiplier = 0.15f;
  68.     [SerializeField] private float _speedIncreaseSlideTimeMultiplier = 1.5f;
  69.     [SerializeField] private float _slopeIncreaseSlideTimeMultiplier = 2.75f;
  70.  
  71.     [Header("Ground Check")]
  72.     [SerializeField] private LayerMask _groundMask;
  73.     [SerializeField] private float _groundCheckRadius = 0.2f;
  74.     [HideInInspector] public bool isGrounded;
  75.  
  76.     [Header("Slopes")]
  77.     [SerializeField] private float _maxSlopeAngle = 40f;
  78.     [SerializeField] private float _exitSlopeDownwardForce = 2f;
  79.     [SerializeField] private float _minYVelocityToApplyDownwardForce = 0.1f;
  80.  
  81.     [Header("Jump/Airborne")]
  82.     [SerializeField] private float _jumpForce = 8f;
  83.     [SerializeField] private float _jumpCooldown = 0.25f;
  84.     [SerializeField] private float _airControlMultiplier = 0.05f;
  85.     [SerializeField] private float _fallDistanceRequiredToShake = 0.525f;
  86.     [SerializeField] private float _jumpKeyStayPressedTime = 0.05f;
  87.     [SerializeField] private float _minAirMagnitude = 1.5f;
  88.     [HideInInspector] public bool readyToJump;
  89.  
  90.     [Header("Crouch")]
  91.     [SerializeField] private HeadCheck _headCheck;
  92.     [SerializeField] private float _crouchHeight = 0.6f;
  93.     [SerializeField, Range(0f, 0.5f)] private float _crouchDownDuration = 0.35f;
  94.     [SerializeField, Range(0f, 0.5f)] private float _crouchUpDuration = 0.25f;
  95.     [HideInInspector] public Tween crouchTween;
  96.  
  97.  
  98.     #endregion
  99.  
  100.     #region private
  101.     private Rigidbody _rigidbody;
  102.     private RaycastHit _slopeHit;
  103.  
  104.     private float _desiredMoveSpeed;
  105.     private float _lastDesiredMoveSpeed;
  106.     private float _speedMultiplier;
  107.     private float _startYPosition;
  108.     private float _moveSpeed;
  109.     private float _currentWalkSpeed;
  110.     private float _currentCrouchSpeed;
  111.     private float _currentSprintSpeed;
  112.     private float _airborneYPosition;
  113.     private float _airborneHighestYPosition;
  114.     private float _velocityWhenLeftGround;
  115.     private float _startHeight;
  116.  
  117.     private bool _exitingSlope;
  118.     private bool _boostedSlowDown;
  119.     private bool _sprintFOVEnabled;
  120.     private bool _downwardForceApplied = true;
  121.     private bool _keepMomentum;
  122.     private bool _canSprint = true;
  123.  
  124.     private Vaulting _vaultingReference;
  125.     private Sliding _slidingReference;
  126.     private CameraLook _cameraLookReference;
  127.     #endregion
  128.  
  129.     #region movestate
  130.     [ReadOnlyInspector] public MovementState _movementState;
  131.     public enum MovementState
  132.     {
  133.         walking,
  134.         sprinting,
  135.         sliding,
  136.         vaulting,
  137.         airborne,
  138.         crouching
  139.     }
  140.     #endregion
  141.  
  142.  
  143.     #region network data
  144.     public struct MoveData : IReplicateData
  145.     {
  146.         public float Horizontal;
  147.         public float Vertical;
  148.         public bool VaultHeld;
  149.         public bool Jumped;
  150.         public bool CrouchPressed;
  151.         public bool CrouchHeld;
  152.         public bool CrouchReleased;
  153.         public bool SprintPressed;
  154.         public bool SprintReleased;
  155.         public bool SprintHeld;
  156.         public Quaternion OrientationRotation;
  157.         public MoveData(float horizontal, float vertical, bool vaultHeld, bool jump, bool crouchPressed, bool crouchHeld, bool crouchReleased, bool sprintPressed, bool sprintReleased, bool sprintHeld, Quaternion orientationRotation)
  158.         {
  159.             Horizontal = horizontal;
  160.             Vertical = vertical;
  161.             VaultHeld = vaultHeld;
  162.             Jumped = jump;
  163.             CrouchPressed = crouchPressed;
  164.             CrouchHeld = crouchHeld;
  165.             CrouchReleased = crouchReleased;
  166.             SprintPressed = sprintPressed;
  167.             SprintReleased = sprintReleased;
  168.             SprintHeld = sprintHeld;
  169.             OrientationRotation = orientationRotation;
  170.             _tick = 0;
  171.         }
  172.         public void Dispose() { }
  173.         private uint _tick;
  174.  
  175.         public uint GetTick() => _tick;
  176.         public void SetTick(uint value) => _tick = value;
  177.  
  178.     }
  179.     public struct ReconcileData : IReconcileData
  180.     {
  181.         public Vector3 Position;
  182.         public Quaternion Rotation;
  183.         public Vector3 Velocity;
  184.         public Vector3 AngularVelocity;
  185.         public MovementState MoveState;
  186.         public bool IsVaulting;
  187.         public bool IsSliding;
  188.         public bool IsCrouching;
  189.         public bool IsStepping;
  190.         public bool IsGrounded;
  191.         public bool ReadyToJump;
  192.         //Purge
  193.         public Vector3 MoveDirection;
  194.         public float DesiredMoveSpeed;
  195.         public float LastDesiredMoveSpeed;
  196.         public float SpeedMultiplier;
  197.         public float StartYPosition;
  198.         public float MoveSpeed;
  199.         public float CurrentWalkSpeed;
  200.         public float CurrentCrouchSpeed;
  201.         public float CurrentSprintSpeed;
  202.         public float AirborneYPosition;
  203.         public float AirborneHighestYPosition;
  204.         public float VelocityWhenLeftGround;
  205.         public float StartHeight;
  206.  
  207.         public bool ExitingSlope;
  208.         public bool BoostedSlowDown;
  209.         public bool DownwardForceApplied;
  210.         public bool KeepMomentum;
  211.         public bool CanSprint;
  212.         public ReconcileData(Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 angularVelocity,
  213.             MovementState moveState, bool isVaulting, bool isSliding, bool isCrouching, bool isStepping, bool isGrounded, bool readyToJump, Vector3 moveDirection,
  214.             float desiredMoveSpeed, float lastDesiredMoveSpeed, float speedMultiplier, float startYPosition, float moveSpeed, float currentWalkSpeed, float currentCrouchSpeed,
  215.             float currentSprintSpeed, float airborneYPosition, float airborneHighestYPosition, float velocityWhenLeftGround, float startHeight, bool exitingSlope, bool boostedSlowDown,
  216.             bool downwardForceApplied, bool keepMomentum, bool canSprint)
  217.         {
  218.             Position = position;
  219.             Rotation = rotation;
  220.             Velocity = velocity;
  221.             AngularVelocity = angularVelocity;
  222.             MoveState = moveState;
  223.             IsVaulting = isVaulting;
  224.             IsSliding = isSliding;
  225.             IsCrouching = isCrouching;
  226.             IsStepping = isStepping;
  227.             IsGrounded = isGrounded;
  228.             ReadyToJump = readyToJump;
  229.             //Purge
  230.             MoveDirection = moveDirection;
  231.             DesiredMoveSpeed = desiredMoveSpeed;
  232.             LastDesiredMoveSpeed = lastDesiredMoveSpeed;
  233.             SpeedMultiplier = speedMultiplier;
  234.             StartYPosition = startYPosition;
  235.             MoveSpeed = moveSpeed;
  236.             CurrentWalkSpeed = currentWalkSpeed;
  237.             CurrentCrouchSpeed = currentCrouchSpeed;
  238.             CurrentSprintSpeed = currentSprintSpeed;
  239.             AirborneYPosition = airborneYPosition;
  240.             AirborneHighestYPosition = airborneHighestYPosition;
  241.             VelocityWhenLeftGround = velocityWhenLeftGround;
  242.             StartHeight = startHeight;
  243.  
  244.             ExitingSlope = exitingSlope;
  245.             BoostedSlowDown = boostedSlowDown;
  246.             DownwardForceApplied = downwardForceApplied;
  247.             KeepMomentum = keepMomentum;
  248.             CanSprint = canSprint;
  249.             _tick = 0;
  250.         }
  251.  
  252.         private uint _tick;
  253.         public void Dispose() { }
  254.         public uint GetTick() => _tick;
  255.         public void SetTick(uint value) => _tick = value;
  256.  
  257.     }
  258.     private bool _vaultHeld = false;
  259.     private bool _jumpQueued = false;
  260.     private bool _crouchPressed = false;
  261.     private bool _crouchHeld = false;
  262.     private bool _crouchReleased = false;
  263.     private bool _sprintPressed = false;
  264.     private bool _sprintReleased = false;
  265.     private bool _sprintHeld = false;
  266.  
  267.     #endregion
  268.  
  269.     [SerializeField]
  270.     private float _moveRate = 15f;
  271.  
  272.     #region unity methods
  273.     private void OnEnable()
  274.     {
  275.         PlayerLifeSystem.onKillPlayer += KillPlayer;
  276.     }
  277.     private void OnDisable()
  278.     {
  279.         PlayerLifeSystem.onKillPlayer -= KillPlayer;
  280.     }
  281.     private void Start()
  282.     {
  283.         _rigidbody.freezeRotation = true;
  284.         _startHeight = transform.localScale.y;
  285.         _startYPosition = transform.position.y;
  286.         readyToJump = true;
  287.         //We need to do this in start as well
  288.         _rigidbody.isKinematic = false;
  289.     }
  290.  
  291.     private void LateUpdate()
  292.     {
  293.         //if player movement not locked, update look direction
  294.         if (_playerStateManager.playerState != PlayerStateManager.PlayerState.MovementDisabled && base.IsOwner)
  295.             _cameraLookReference.Look();
  296.     }
  297.     private void Update()
  298.     {
  299.  
  300.        
  301.  
  302.         if (base.IsOwner)
  303.         {
  304.             _vaultHeld = Input.GetKey(_vaultKey);
  305.             _crouchHeld = Input.GetKey(_crouchKey);
  306.             _sprintHeld = Input.GetKey(_sprintKey);
  307.  
  308.             if (Input.GetKeyDown(_jumpKey))
  309.             {
  310.                 _jumpQueued = true;
  311.             }
  312.             if (Input.GetKeyDown(_crouchKey))
  313.             {
  314.                 _crouchPressed = true;
  315.                 _crouchReleased = false;
  316.             }
  317.             if (Input.GetKeyUp(_crouchKey))
  318.             {
  319.                 _crouchReleased = true;
  320.                 _crouchPressed = false;
  321.                 _crouchHeld = false;
  322.             }
  323.             if (Input.GetKeyDown(_sprintKey))
  324.             {
  325.                 _sprintPressed = true;
  326.                 _sprintReleased = false;
  327.             }
  328.             if (Input.GetKeyUp(_sprintKey))
  329.             {
  330.                 _sprintReleased = true;
  331.                 _sprintPressed = false;
  332.                 _sprintHeld = false;
  333.             }
  334.         }
  335.  
  336.     }
  337.     #endregion
  338.  
  339.     #region network methods
  340.     public override void OnStopNetwork()
  341.     {
  342.         if (base.TimeManager != null)
  343.         {
  344.             base.TimeManager.OnTick -= TimeManager_OnTick;
  345.             base.TimeManager.OnPostTick -= TimeManager_OnPostTick;
  346.         }
  347.     }
  348.     public override void OnStartNetwork()
  349.     {
  350.         _playerStateManager = GetComponent<PlayerStateManager>();
  351.         _rigidbody = GetComponent<Rigidbody>();
  352.         _rigidbody.isKinematic = false;
  353.         _vaultingReference = GetComponent<Vaulting>();
  354.         _slidingReference = GetComponent<Sliding>();
  355.         _cameraLookReference = GetComponent<CameraLook>();
  356.         base.TimeManager.OnTick += TimeManager_OnTick;
  357.         base.TimeManager.OnPostTick += TimeManager_OnPostTick;
  358.     }
  359.     #endregion
  360.  
  361.  
  362.     private void TimeManager_OnTick()
  363.     {
  364.  
  365.  
  366.        
  367.  
  368.         if (_playerStateManager.playerState != PlayerStateManager.PlayerState.MovementDisabled)
  369.         {
  370.             Move(BuildMoveData());
  371.         }
  372.         else
  373.         {
  374.             _jumpQueued = false; //prevents unwanted jumping after disabling/reenabling movement (ie: after vaulting)
  375.         }
  376.     }
  377.  
  378.     private MoveData BuildMoveData()
  379.     {
  380.         if (!base.IsOwner)
  381.             return default;
  382.         float _horizontal = Input.GetAxisRaw("Horizontal");
  383.         float _vertical = Input.GetAxisRaw("Vertical");
  384.         Quaternion _orientationRotation = _cameraLookReference.GetOrientationRotation();
  385.         MoveData md = new MoveData
  386.         {
  387.             Horizontal = _horizontal,
  388.             Vertical = _vertical,
  389.             VaultHeld = _vaultHeld,
  390.             Jumped = _jumpQueued,
  391.             CrouchPressed = _crouchPressed,
  392.             CrouchHeld = _crouchHeld,
  393.             CrouchReleased = _crouchReleased,
  394.             SprintPressed = _sprintPressed,
  395.             SprintReleased = _sprintReleased,
  396.             SprintHeld = _sprintHeld,
  397.             OrientationRotation = _orientationRotation
  398.         };
  399.  
  400.         _jumpQueued = false;
  401.         _sprintPressed = false;
  402.         _sprintReleased = false;
  403.         _crouchPressed = false;
  404.         //_crouchHeld = false;
  405.         _crouchReleased = false;
  406.         //_sprintHeld = false;
  407.         //_vaultHeld = false;
  408.         return md;
  409.     }
  410.  
  411.     private MoveData? _lastMoveData;
  412.  
  413.     [ReplicateV2]
  414.     private void Move(MoveData data, ReplicateState state = ReplicateState.Invalid, Channel channel = Channel.Unreliable)
  415.     {
  416.         SpeedControl();
  417.         LerpGroundSpeed();
  418.         LerpCrouchSpeed();
  419.         LerpSprintSpeed();
  420.         //set drag when on ground to make it grippier
  421.         if (isGrounded)
  422.             _rigidbody.drag = _groundDrag;
  423.         else
  424.             _rigidbody.drag = 0f;
  425.         //update highest point reached in air
  426.         if (!isGrounded && transform.position.y > _airborneHighestYPosition)
  427.             _airborneHighestYPosition = transform.position.y;
  428.  
  429.         GroundCheck();
  430.  
  431.         #region fishnet magic
  432.         if (state == ReplicateState.Predicted && _lastMoveData.HasValue)
  433.         {
  434.             MoveData lastMd = _lastMoveData.Value;
  435.             lastMd.Horizontal *= 0.9f;
  436.             /* The tick will increase even if the data is unset.
  437.              * Cache the tick, set md to last data, then reapply the tick. */
  438.             uint tick = data.GetTick();
  439.             data = lastMd;
  440.             data.SetTick(tick);
  441.             _lastMoveData = lastMd;
  442.         }
  443.         else if (state == ReplicateState.UserCreated && !base.IsOwner && !base.IsServer)
  444.         {
  445.             _lastMoveData = data;
  446.         }
  447.         #endregion
  448.  
  449.         #region look syncing for server
  450.         if (base.IsServer)
  451.         {
  452.             _cameraLookReference.SetOrientationRotation(data.OrientationRotation);
  453.         }
  454.         #endregion
  455.  
  456.         #region movement
  457.         _vaultingReference.SetVaultingKeyInput(data.VaultHeld);
  458.         _slidingReference.SetValuesFromMoveData(data.CrouchPressed, data.CrouchHeld, data.Horizontal, data.Vertical);
  459.         //get movement vector
  460.         moveDirection = _orientation.forward * data.Vertical + _orientation.right * data.Horizontal;
  461.  
  462.         if (data.SprintReleased)
  463.             _canSprint = true;
  464.         if (data.SprintPressed && !isSliding)
  465.             _canSprint = true;
  466.  
  467.         //allows for player to jump if they pressed key right before hitting ground
  468.         //keeps key pressed for certain amount of time
  469.  
  470.         if (data.Jumped)
  471.         {
  472.             if (isCrouching && _headCheck.canStand)
  473.                 EndCrouch();
  474.  
  475.             else if (CanJump())
  476.             {
  477.                 readyToJump = false;
  478.  
  479.                 Jump();
  480.                 Invoke(nameof(ResetJump), _jumpCooldown);
  481.             }
  482.         }
  483.         if (data.CrouchPressed)
  484.         {
  485.             if (CanCrouch() && !isCrouching)
  486.             {
  487.                 StartCrouch();
  488.                 _currentCrouchSpeed = _crouchSpeed;
  489.             }
  490.  
  491.             else if (_headCheck.canStand && isCrouching)
  492.                 EndCrouch();
  493.         }
  494.         #endregion
  495.  
  496.         #region non-input movement
  497.         //adjust speed to give player less control when sliding
  498.         if (isSliding && _rigidbody.velocity.y < 0.1f)
  499.             _speedMultiplier = _slideSpeedMultiplier;
  500.         else if (isSliding && _rigidbody.velocity.y >= 0.1f)
  501.             _speedMultiplier = 0f;
  502.         else
  503.             _speedMultiplier = 1f;
  504.  
  505.         //if on slope, move along slope
  506.         if (isGrounded && OnSlope() && !_exitingSlope)
  507.         {
  508.             _downwardForceApplied = false;
  509.             _rigidbody.AddForce(GetSlopeMoveDirection(moveDirection) * _moveSpeed * 10f * _speedMultiplier, ForceMode.Force);
  510.  
  511.             //apply downforce to keep player on ground if traveling down slope
  512.             if (moveDirection != Vector3.zero && !isStepping && _rigidbody.velocity.y < -_minYVelocityToApplyDownwardForce)
  513.                 _rigidbody.AddForce(Vector3.down * 50f, ForceMode.Force);
  514.         }
  515.         //if going from uphill to not uphill surface, push player down to prevent unwanted ungrounding
  516.         if (!OnSlope() && isGrounded && _rigidbody.velocity.y > 0.01f && _rigidbody.velocity.y < 5f && !_exitingSlope && !_downwardForceApplied && !isStepping)
  517.         {
  518.             _downwardForceApplied = true;
  519.             _rigidbody.AddForce(Vector3.down * _exitSlopeDownwardForce, ForceMode.VelocityChange);
  520.         }
  521.         //if on normal ground, move normally
  522.         else if (isGrounded && !OnSteepSlope())
  523.             _rigidbody.AddForce(moveDirection.normalized * _moveSpeed * 10f * _speedMultiplier, ForceMode.Force);
  524.  
  525.         //if in air or on too steep of surface
  526.         else if (!isGrounded || OnSteepSlope())
  527.         {
  528.             //move normally but with lower amount of control
  529.             _rigidbody.AddForce(moveDirection.normalized * _moveSpeed * 10f * _airControlMultiplier, ForceMode.Force);
  530.  
  531.             //limit max speed to speed player was at when they went airborne
  532.             Vector3 flatVel = new Vector3(_rigidbody.velocity.x, 0f, _rigidbody.velocity.z);
  533.             _rigidbody.velocity = Vector3.ClampMagnitude(flatVel, _velocityWhenLeftGround < _minAirMagnitude ? _minAirMagnitude : _velocityWhenLeftGround) + Vector3.up * _rigidbody.velocity.y;
  534.  
  535.             //push player down steep slopes
  536.             if (OnSteepSlope())
  537.                 _rigidbody.AddForce(Vector3.down * 50f, ForceMode.Force);
  538.         }
  539.  
  540.         //disable gravity if on slope (prevents sliding down) or grounded or not stepping
  541.         if ((!isGrounded || !OnSlope()) && !isStepping)
  542.             _rigidbody.useGravity = true;
  543.         else
  544.             _rigidbody.useGravity = false;
  545.  
  546.  
  547.         #endregion
  548.  
  549.         #region state handling
  550.         if (isVaulting)
  551.             _movementState = MovementState.vaulting;
  552.         else if (isSliding)
  553.         {
  554.             _movementState = MovementState.sliding;
  555.             _currentCrouchSpeed = _slideSpeed;
  556.             _canSprint = false;
  557.  
  558.             //if sliding down slope
  559.             if (OnSlope() && _rigidbody.velocity.y < -0.1f)
  560.             {
  561.                 _desiredMoveSpeed = _slideSpeed;
  562.                 _keepMomentum = true;
  563.             }
  564.             else
  565.                 _desiredMoveSpeed = _slideSpeed;
  566.         }
  567.         //if crouching and not trying to sprint and grounded
  568.         else if (isCrouching && (!(data.SprintHeld && data.Vertical > 0.1f && _headCheck.canStand) || !_canSprint) && isGrounded)
  569.         {
  570.             _movementState = MovementState.crouching;
  571.             //only change to crouch speed if not jumping (helps keep momentum from slide jump)
  572.             if (readyToJump)
  573.                 _desiredMoveSpeed = _currentCrouchSpeed;
  574.         }
  575.         else if (isGrounded && data.SprintHeld && CanSprint(data))
  576.         {
  577.             if (isCrouching)
  578.                 EndCrouch();
  579.  
  580.             _movementState = MovementState.sprinting;
  581.             _desiredMoveSpeed = _currentSprintSpeed;
  582.         }
  583.         else if (isGrounded)
  584.         {
  585.             _movementState = MovementState.walking;
  586.             //set sprint speed to walk so we can lerp to it
  587.             _currentSprintSpeed = _walkSpeed;
  588.             //only update walk speed if not jumping (helps keep momentum from slide jump)
  589.             if (readyToJump)
  590.                 _desiredMoveSpeed = _currentWalkSpeed;
  591.         }
  592.         else
  593.         {
  594.             if (isCrouching && _headCheck.canStand)
  595.                 EndCrouch();
  596.  
  597.             else if (!isCrouching)
  598.             {
  599.                 _movementState = MovementState.airborne;
  600.  
  601.                 if (_moveSpeed < _airSpeed)
  602.                     _desiredMoveSpeed = _airSpeed;
  603.             }
  604.         }
  605.  
  606.         bool desiredMoveSpeedChanged = _desiredMoveSpeed != _lastDesiredMoveSpeed;
  607.  
  608.         //decide to keep momentum or instantly change desired move speed
  609.         if (desiredMoveSpeedChanged)
  610.         {
  611.             if (_keepMomentum)
  612.             {
  613.                 StopAllCoroutines();
  614.                 StartCoroutine(SmoothLerpMoveSpeed());
  615.             }
  616.             else
  617.                 _moveSpeed = _desiredMoveSpeed;
  618.         }
  619.  
  620.         _lastDesiredMoveSpeed = _desiredMoveSpeed;
  621.  
  622.         //don't keep momentum if desired move speed is close to move speed
  623.         if (Mathf.Abs(_desiredMoveSpeed - _moveSpeed) < 0.1f)
  624.             _keepMomentum = false;
  625.         #endregion
  626.  
  627.     }
  628.  
  629.     private void TimeManager_OnPostTick()
  630.     {
  631.         /* The base.IsServer check is not required but does save a little
  632.         * performance by not building the reconcileData if not server. */
  633.         if (IsServer)
  634.         {
  635.             ReconcileData rd = new ReconcileData(_rigidbody.position, transform.rotation, _rigidbody.velocity,
  636.                 _rigidbody.angularVelocity.normalized, _movementState, isVaulting, isSliding, isCrouching, isStepping, isGrounded,
  637.                 readyToJump, moveDirection, _desiredMoveSpeed, _lastDesiredMoveSpeed, _speedMultiplier, _startYPosition, _moveSpeed, _currentWalkSpeed,
  638.                 _currentCrouchSpeed, _currentSprintSpeed, _airborneYPosition, _airborneHighestYPosition, _velocityWhenLeftGround, _startHeight, _exitingSlope,
  639.                 _boostedSlowDown, _downwardForceApplied, _keepMomentum, _canSprint);
  640.             Reconciliation(rd);
  641.         }
  642.     }
  643.  
  644.     /// <summary>
  645.     /// Method that resets the player based on the servers values
  646.     /// </summary>
  647.     /// <param name="data">ReconcileData reference</param>
  648.     /// <param name="channel">Channel which data is sent or recieved</param>
  649.     [ReconcileV2]
  650.     private void Reconciliation(ReconcileData data, Channel channel = Channel.Unreliable)
  651.     {
  652.         _rigidbody.position = data.Position;
  653.         transform.rotation = data.Rotation;
  654.         _rigidbody.velocity = data.Velocity;
  655.         _rigidbody.angularVelocity = data.AngularVelocity;
  656.         _movementState = data.MoveState;
  657.         isVaulting = data.IsVaulting;
  658.         isSliding = data.IsSliding;
  659.         isCrouching = data.IsCrouching;
  660.         isStepping = data.IsStepping;
  661.         isGrounded = data.IsGrounded;
  662.         readyToJump = data.ReadyToJump;
  663.         moveDirection = data.MoveDirection;
  664.         _desiredMoveSpeed = data.DesiredMoveSpeed;
  665.         _lastDesiredMoveSpeed = data.LastDesiredMoveSpeed;
  666.         _speedMultiplier = data.SpeedMultiplier;
  667.         _startYPosition = data.StartYPosition;
  668.         _moveSpeed = data.MoveSpeed;
  669.         _currentWalkSpeed = data.CurrentWalkSpeed;
  670.         _currentCrouchSpeed = data.CurrentCrouchSpeed;
  671.         _currentSprintSpeed = data.CurrentSprintSpeed;
  672.         _airborneYPosition = data.AirborneYPosition;
  673.         _airborneHighestYPosition = data.AirborneHighestYPosition;
  674.         _velocityWhenLeftGround = data.VelocityWhenLeftGround;
  675.         _startHeight = data.StartHeight;
  676.         _exitingSlope = data.ExitingSlope;
  677.         _boostedSlowDown = data.BoostedSlowDown;
  678.         _downwardForceApplied = data.DownwardForceApplied;
  679.         _keepMomentum = data.KeepMomentum;
  680.         _canSprint = data.CanSprint;
  681.     }
  682.  
  683.  
  684.     #region movement functions
  685.     //keep momentum, usually done after coming out of a downward slide
  686.     private IEnumerator SmoothLerpMoveSpeed()
  687.     {
  688.         float time = 0;
  689.         float difference = _desiredMoveSpeed - _moveSpeed;
  690.  
  691.         if (difference < 0f)
  692.             difference = 0f;
  693.  
  694.         float startValue = _moveSpeed;
  695.         float boostFactor = 1f;
  696.  
  697.         //if not sliding, add boost factor to end momentum shift faster
  698.         if (_boostedSlowDown && !isSliding)
  699.             boostFactor = 10f;
  700.  
  701.         while (time < difference)
  702.         {
  703.             //lerp move speed from current to desired move speed
  704.             _moveSpeed = Mathf.Lerp(startValue, _desiredMoveSpeed, time / difference);
  705.  
  706.             //change lerp speed based on speed and slope angle if on slope
  707.             if (OnSlope())
  708.             {
  709.                 float slopeAngle = Vector3.Angle(Vector3.up, _slopeHit.normal);
  710.                 float slopeAngleIncrease = 1 + (slopeAngle / 90f);
  711.  
  712.                 time += Time.fixedDeltaTime * _speedIncreaseSlideTimeMultiplier * _slopeIncreaseSlideTimeMultiplier * slopeAngleIncrease * boostFactor;
  713.             }
  714.             else
  715.                 time += Time.fixedDeltaTime * _speedIncreaseSlideTimeMultiplier * boostFactor;
  716.  
  717.             yield return null;
  718.         }
  719.  
  720.         //instantly change move speed after lerp done
  721.         _moveSpeed = _desiredMoveSpeed;
  722.  
  723.         if (_boostedSlowDown)
  724.             _boostedSlowDown = false;
  725.     }
  726.  
  727.     private void Jump()
  728.     {
  729.         _exitingSlope = true;
  730.  
  731.         //Set y vel to 0
  732.         _rigidbody.velocity = new Vector3(_rigidbody.velocity.x, _rigidbody.velocity.y / 2f, _rigidbody.velocity.z);
  733.  
  734.         if (onJump != null)
  735.             onJump();
  736.  
  737.         _rigidbody.AddForce(new Vector3(0f, _jumpForce, 0f), ForceMode.Impulse);
  738.     }
  739.  
  740.     /// <summary>
  741.     /// Method that resets the player on death
  742.     /// </summary>
  743.     /// <param name="spawnPoint">The transform to spawn the player at</param>
  744.     public void Respawn(Vector3 spawnPoint)
  745.     {
  746.         //reset player
  747.         _rigidbody.isKinematic = false;
  748.         _rigidbody.velocity = Vector3.zero;
  749.         isGrounded = true;
  750.         transform.position = spawnPoint;
  751.     }
  752.     public void SlideToCrouch()
  753.     {
  754.         if (onCrouch != null)
  755.             onCrouch();
  756.     }
  757.     private void ResetJump()
  758.     {
  759.         readyToJump = true;
  760.         _exitingSlope = false;
  761.     }
  762.  
  763.     private void StartCrouch()
  764.     {
  765.         if (onCrouch != null)
  766.             onCrouch();
  767.  
  768.         isCrouching = true;
  769.  
  770.         if (crouchTween != null)
  771.             crouchTween.Kill();
  772.  
  773.         crouchTween = transform.DOScaleY(_crouchHeight, _crouchDownDuration);
  774.     }
  775.     private void EndCrouch()
  776.     {
  777.         if (onUncrouch != null)
  778.             onUncrouch();
  779.  
  780.         isCrouching = false;
  781.  
  782.         if (crouchTween != null)
  783.             crouchTween.Kill();
  784.  
  785.         crouchTween = transform.DOScaleY(_startHeight, _crouchUpDuration);
  786.     }
  787.     private void KillPlayer()
  788.     {
  789.         //_playerCamera.fieldOfView = PlayerPrefs.GetInt("FieldOfView");
  790.         transform.localScale = Vector3.one;
  791.         _movementState = MovementState.walking;
  792.  
  793.         isSliding = false;
  794.         isVaulting = false;
  795.         isCrouching = false;
  796.     }
  797.  
  798.     /// <summary>
  799.     /// Method that assigns the TimeManager
  800.     /// </summary>
  801.     /// <param name="manager">TimeManager reference</param>
  802.     //lerp ground walk speed to retain some x/z velocity when hopping
  803.     private void LerpGroundSpeed()
  804.     {
  805.         if (isGrounded && _movementState == MovementState.walking)
  806.             _currentWalkSpeed = Mathf.Lerp(_currentWalkSpeed, _walkSpeed, _lerpGroundSpeedRate * Time.fixedDeltaTime);
  807.     }
  808.     //lerp crouch speed when exiting slide so you don't lose all momentum
  809.     private void LerpCrouchSpeed()
  810.     {
  811.         Vector3 flatVel = new Vector3(_rigidbody.velocity.x, 0f, _rigidbody.velocity.z);
  812.         if (isCrouching)
  813.         {
  814.             if (Vector3.Dot(moveDirection, flatVel.normalized) > 0.5f || moveDirection.magnitude < 0.1f)
  815.                 _currentCrouchSpeed = Mathf.Lerp(_currentCrouchSpeed, _crouchSpeed, _lerpCrouchSpeedRate * Time.fixedDeltaTime);
  816.             else
  817.                 _currentCrouchSpeed = Mathf.Lerp(_currentCrouchSpeed, _crouchSpeed, _lerpCrouchSpeedRate * 3f * Time.fixedDeltaTime);
  818.         }
  819.     }
  820.     //lerp sprint speed when going from walk to sprint
  821.     //lerp to either slope sprint speed or normal sprint speed
  822.     private void LerpSprintSpeed()
  823.     {
  824.         if (isGrounded && _movementState == MovementState.sprinting)
  825.             _currentSprintSpeed = Mathf.Lerp(_currentSprintSpeed, OnSlope() ? GetSlopeSprintSpeed() : _sprintSpeed, _lerpSprintSpeedRate * Time.fixedDeltaTime);
  826.     }
  827.     private void SpeedControl()
  828.     {
  829.         //change full velocity if on slope
  830.         if (OnSlope() && !_exitingSlope)
  831.         {
  832.             if (_rigidbody.velocity.magnitude > _moveSpeed)
  833.                 _rigidbody.velocity = _rigidbody.velocity.normalized * _moveSpeed;
  834.         }
  835.         //only change x/z if not on slope
  836.         else
  837.         {
  838.             Vector3 flatVel = new Vector3(_rigidbody.velocity.x, 0f, _rigidbody.velocity.z);
  839.  
  840.             if (flatVel.magnitude > _moveSpeed)
  841.             {
  842.                 Vector3 limitedVel = flatVel.normalized * _moveSpeed;
  843.                 _rigidbody.velocity = new Vector3(limitedVel.x, _rigidbody.velocity.y, limitedVel.z);
  844.             }
  845.         }
  846.     }
  847.     private void GroundCheck()
  848.     {
  849.         if (Physics.CheckSphere(transform.position + transform.up * (_groundCheckRadius / 2f), _groundCheckRadius, _groundMask) && !isGrounded)
  850.         {
  851.             if (onLand != null && !isVaulting)
  852.             {
  853.                 //onLand();
  854.  
  855.                 //if player fallen far enough to land with enough force
  856.                 if (_airborneHighestYPosition - transform.position.y >= _fallDistanceRequiredToShake)
  857.                 {
  858.                     //ScreenShake.instance.Shake(1);
  859.                     onLand();
  860.                 }
  861.                 else
  862.                     _currentWalkSpeed = _walkSpeed;
  863.             }
  864.  
  865.             isGrounded = true;
  866.         }
  867.         else if (!Physics.CheckSphere(transform.position, _groundCheckRadius, _groundMask) && isGrounded && !isStepping)
  868.         {
  869.             //start checking for highest y position reached in air
  870.             isGrounded = false;
  871.             _airborneYPosition = transform.position.y;
  872.             _airborneHighestYPosition = _startYPosition;
  873.  
  874.             //get x/z velocity when airborne so we can clamp airborne maximum speed to that speed
  875.             _velocityWhenLeftGround = new Vector3(_rigidbody.velocity.x, 0f, _rigidbody.velocity.z).magnitude;
  876.             _currentWalkSpeed = _airSpeed;
  877.  
  878.             if (onAirborne != null)
  879.                 onAirborne();
  880.         }
  881.     }
  882.     #endregion
  883.  
  884.  
  885.  
  886.  
  887.  
  888.     /// <summary>
  889.     /// Method that checks if the player is currently on a slope by raycasting and checking the hit normal
  890.     /// </summary>
  891.     /// <returns>True if a player is on a slope, otherwise false</returns>
  892.     public bool OnSlope()
  893.     {
  894.         return false;
  895.  
  896.         //check ground slope angle to determine if on slope
  897.         if (Physics.Raycast(transform.position, Vector3.down, out _slopeHit, 0.25f, _groundMask))
  898.         {
  899.             float angle = Vector3.Angle(Vector3.up, _slopeHit.normal);
  900.             return angle < _maxSlopeAngle && angle != 0f;
  901.         }
  902.  
  903.         return false;
  904.     }
  905.     /// <summary>
  906.     /// Method that checks the direction of a slope
  907.     /// </summary>
  908.     /// <param name="direction"></param>
  909.     /// <returns>The direction a slope is facing</returns>
  910.     public Vector3 GetSlopeMoveDirection(Vector3 direction)
  911.     {
  912.         return Vector3.zero;
  913.  
  914.         return Vector3.ProjectOnPlane(direction, _slopeHit.normal).normalized;
  915.     }
  916.  
  917.     private bool OnSteepSlope()
  918.     {
  919.         return false;
  920.  
  921.         //check ground slope angle to determine if on slope
  922.         if (Physics.Raycast(transform.position, Vector3.down, out _slopeHit, 0.25f, _groundMask))
  923.         {
  924.             float angle = Vector3.Angle(Vector3.up, _slopeHit.normal);
  925.             return angle >= _maxSlopeAngle && angle != 0f;
  926.         }
  927.  
  928.         return false;
  929.     }
  930.     private bool CanCrouch()
  931.     {
  932.         return true;
  933.  
  934.         return _movementState != MovementState.airborne && _movementState != MovementState.crouching && _movementState != MovementState.sprinting && !isVaulting && !isSliding;
  935.     }
  936.     //get slope sprint speed using linear equation to calculate how much we want the player to be slowed by steeper slopes
  937.     private float GetSlopeSprintSpeed()
  938.     {
  939.         return _sprintSpeed;
  940.  
  941.  
  942.         if (Vector3.Dot(GetSlopeMoveDirection(moveDirection), Vector3.up) > -0.01f)
  943.             return _sprintSpeed * (Vector3.Dot(GetSlopeMoveDirection(moveDirection), Vector3.up) * -0.3f + 1f);
  944.         else
  945.             return _sprintSpeed;
  946.     }
  947.     //clamp velocity to match current state, only clamp x/z when on slopes
  948.  
  949.     private bool CanSprint(MoveData data)
  950.     {
  951.         return true;
  952.  
  953.         return data.Vertical > 0.1f && _staminaSystem.GetStamina() > 0f;
  954.     }
  955.     private bool CanJump()
  956.     {
  957.         return true;
  958.  
  959.         return (!isCrouching && readyToJump && isGrounded && !OnSteepSlope()) && !isVaulting && !(!OnSlope() && _rigidbody.velocity.y > 4f);
  960.     }
  961. }
  962.  
  963.  
  964.  
  965.  
Advertisement
Add Comment
Please, Sign In to add comment