Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

First-person camera stutter issue

Discussion in 'Physics' started by nscrivanich112325, Jun 6, 2020.

  1. nscrivanich112325

    nscrivanich112325

    Joined:
    Aug 14, 2018
    Posts:
    12
    Hello, I have been dealing with this issue for a couple of weeks now and could not resolve it. I'm making a first-person horror game and the main camera for my player character seems to be slightly stuttering at a rapid pace. This is evident because the objects and props in the scene seem to be jittering around when the player moves. It does not happen when the player is still. Here is a short video demonstrating the stuttering (Watch full screen):




    I displayed the velocity of the rigidbody in the top left-hand corner of the screen. The arms are rendered on a separate camera that has its culling mask set to the arms. As you can see, the battery and the bed looks like its staggering back and forth as the player moves. This happens with other objects in the scene as well. I think it may be the rigidbody that is causing this issue because the stuttering is not visible when I move around using a free camera that has no rigidbody component attached to it.

    Here is the script I use for the player controller that I got from the asset store:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Linq;
    4. using System.Collections;
    5. using System.Collections.Generic;
    6. #if UNITY_EDITOR
    7.     using UnityEditor;
    8. #endif
    9.  
    10. [RequireComponent(typeof(CapsuleCollider)),RequireComponent(typeof(Rigidbody)),AddComponentMenu("First Person AIO")]
    11.  
    12. public class FirstPersonAIO : MonoBehaviour {
    13.  
    14.  
    15.     public AudioClip[] concreteFootSteps;
    16.  
    17.     public AudioClip[] grassFootSteps;
    18.  
    19.     public AudioClip[] woodFootSteps;
    20.  
    21.     public bool grass = false;
    22.     public bool wood = false;
    23.     Vector3 gravity = new Vector3(0, -9.81f, 0);
    24.     Vector3 dMove = Vector3.zero;
    25.  
    26.  
    27.     #region Variables
    28.  
    29.     #region Input Settings
    30.  
    31.     #endregion
    32.  
    33.     #region Look Settings
    34.     public bool above = false;
    35.     public bool enableCameraMovement = true;
    36.     public enum InvertMouseInput{None,X,Y,Both}
    37.     public InvertMouseInput mouseInputInversion = InvertMouseInput.None;
    38.     public float verticalRotationRange = 170;
    39.     public float mouseSensitivity = 10;
    40.     public float mouseSensitivityInternal;
    41.     public  float   fOVToMouseSensitivity = 1;
    42.     public float cameraSmoothing = 5f;
    43.     public bool lockAndHideCursor = false;
    44.     public Camera playerCamera;
    45.     public bool enableCameraShake=false;
    46.     internal Vector3 cameraStartingPosition;
    47.     float baseCamFOV;
    48.     Camera mainCamera;
    49.  
    50.  
    51.  
    52.     public bool autoCrosshair = false;
    53.     public bool drawStaminaMeter = true;
    54.  
    55.     float smoothRef;
    56.     Image StaminaMeter;
    57.     Image StaminaMeterBG;
    58.     public Sprite Crosshair;
    59.     public Vector3 targetAngles;
    60.     public Vector3 followAngles;
    61.     private Vector3 followVelocity;
    62.     public Vector3 originalRotation;
    63.     #endregion
    64.  
    65.     #region Movement Settings
    66.  
    67.     public bool playerCanMove = true;
    68.     public bool walkByDefault = true;
    69.     public float walkSpeed = 4f;
    70.     public KeyCode sprintKey = KeyCode.LeftShift;
    71.     public float sprintSpeed = 8f;
    72.     public float jumpPower = 5f;
    73.     public bool canJump = true;
    74.     public bool canHoldJump;
    75.     bool didJump;
    76.     public bool useStamina = true;
    77.     public float staminaDepletionSpeed = 5f;
    78.     public float staminaLevel = 50;
    79.     public float speed;
    80.     public float staminaInternal;
    81.     internal float walkSpeedInternal;
    82.     internal float sprintSpeedInternal;
    83.     internal float jumpPowerInternal;
    84.  
    85.     [System.Serializable]
    86.     public class CrouchModifiers {
    87.         public bool useCrouch = true;
    88.         public bool toggleCrouch = false;
    89.         public KeyCode crouchKey = KeyCode.LeftControl;
    90.         public float crouchWalkSpeedMultiplier = 0.5f;
    91.         public float crouchJumpPowerMultiplier = 0f;
    92.         public float crouchHeight = 2f;
    93.         public bool crouchOverride;
    94.      
    95.         internal float colliderHeight;
    96.      
    97.     }
    98.     public CrouchModifiers _crouchModifiers = new CrouchModifiers();
    99.     [System.Serializable]
    100.     public class FOV_Kick
    101.     {
    102.         public bool useFOVKick = false;
    103.         public float FOVKickAmount = 4;
    104.         public float changeTime = 0.1f;
    105.         public AnimationCurve KickCurve = new AnimationCurve();
    106.         public float fovStart;
    107.     }
    108.     public FOV_Kick fOVKick = new FOV_Kick();
    109.     [System.Serializable]
    110.     public class AdvancedSettings {
    111.         public float gravityMultiplier = 1.0f;
    112.         public PhysicMaterial zeroFrictionMaterial;
    113.         public PhysicMaterial highFrictionMaterial;
    114.         public float _maxSlopeAngle = 70;
    115.         public float maxStepHeight = 0.2f;
    116.         internal bool stairMiniHop = false;
    117.         public RaycastHit surfaceAngleCheck;
    118.         public float lastKnownSlopeAngle;
    119.     }
    120.     public AdvancedSettings advanced = new AdvancedSettings();
    121.     private CapsuleCollider capsule;
    122.     public bool IsGrounded { get; private set; }
    123.     Vector2 inputXY;
    124.     public bool isCrouching;
    125.     float yVelocity;
    126.     public bool isSprinting = false;
    127.  
    128.     public Rigidbody fps_Rigidbody;
    129.  
    130.     #endregion
    131.  
    132.     #region Headbobbing Settings
    133.     public bool useHeadbob = true;
    134.     public Transform head = null;
    135.     public bool snapHeadjointToCapsul = true;
    136.     public float headbobFrequency = 1.5f;
    137.     public float headbobSwayAngle = 5f;
    138.     public float headbobHeight = 3f;
    139.     public float headbobSideMovement =5f;
    140.     public float jumpLandIntensity =3f;
    141.     private Vector3 originalLocalPosition;
    142.     private float nextStepTime = 0.5f;
    143.     private float headbobCycle = 0.0f;
    144.     private float headbobFade = 0.0f;
    145.     private float springPosition = 0.0f;
    146.     private float springVelocity = 0.0f;
    147.     private float springElastic = 1.1f;
    148.     private float springDampen = 0.8f;
    149.     private float springVelocityThreshold = 0.05f;
    150.     private float springPositionThreshold = 0.05f;
    151.     Vector3 previousPosition;
    152.     Vector3 previousVelocity = Vector3.zero;
    153.     Vector3 miscRefVel;
    154.     bool previousGrounded;
    155.     AudioSource audioSource;
    156.  
    157.     #endregion
    158.  
    159.     #region Audio Settings
    160.  
    161.     public float Volume = 5f;
    162.     public AudioClip jumpSound = null;
    163.     public AudioClip landSound = null;
    164.     public List<AudioClip> footStepSounds = null;
    165.     public enum FSMode{Static, Dynamic}
    166.     public FSMode fsmode;
    167.  
    168.     [System.Serializable]
    169.     public class DynamicFootStep{
    170.         public enum matMode{physicMaterial,Material};
    171.         public matMode materialMode;
    172.         public List<PhysicMaterial> woodPhysMat;
    173.         public List<PhysicMaterial> metalAndGlassPhysMat;
    174.         public List<PhysicMaterial> grassPhysMat;
    175.         public List<PhysicMaterial> dirtAndGravelPhysMat;
    176.         public List<PhysicMaterial> rockAndConcretePhysMat;
    177.         public List<PhysicMaterial> mudPhysMat;
    178.         public List<PhysicMaterial> customPhysMat;
    179.  
    180.         public List<Material> woodMat;
    181.         public List<Material> metalAndGlassMat;
    182.         public List<Material> grassMat;
    183.         public List<Material> dirtAndGravelMat;
    184.         public List<Material> rockAndConcreteMat;
    185.         public List<Material> mudMat;
    186.         public List<Material> customMat;
    187.         public List<AudioClip> currentClipSet;
    188.  
    189.         public List<AudioClip> woodClipSet;
    190.         public List<AudioClip> metalAndGlassClipSet;
    191.         public List<AudioClip> grassClipSet;
    192.         public List<AudioClip> dirtAndGravelClipSet;
    193.         public List<AudioClip> rockAndConcreteClipSet;
    194.         public List<AudioClip> mudClipSet;
    195.         public List<AudioClip> customClipSet;
    196.    
    197.     }
    198.     public DynamicFootStep dynamicFootstep = new DynamicFootStep();
    199.  
    200.     #endregion
    201.  
    202.     #region BETA Settings
    203.     /*
    204.      [System.Serializable]
    205. public class BETA_SETTINGS{
    206.  
    207. }
    208.  
    209.             [Space(15)]
    210.     [Tooltip("Settings in this feild are currently in beta testing and can prove to be unstable.")]
    211.     [Space(5)]
    212.     public BETA_SETTINGS betaSettings = new BETA_SETTINGS();
    213.      */
    214.  
    215.     #endregion
    216.  
    217.     private PlayerEnemyInteraction bossDetection;
    218.  
    219.     #endregion
    220.  
    221.     private void Awake()
    222.     {
    223.         #region Look Settings - Awake
    224.         originalRotation = transform.localRotation.eulerAngles;
    225.  
    226.         #endregion
    227.  
    228.         #region Movement Settings - Awake
    229.         walkSpeedInternal = walkSpeed;
    230.         sprintSpeedInternal = sprintSpeed;
    231.         jumpPowerInternal = jumpPower;
    232.         capsule = GetComponent<CapsuleCollider>();
    233.         IsGrounded = true;
    234.         isCrouching = false;
    235.         fps_Rigidbody = GetComponent<Rigidbody>();
    236.         _crouchModifiers.colliderHeight = capsule.height;
    237.         #endregion
    238.  
    239.  
    240.     }
    241.  
    242.     private void Start()
    243.     {
    244.         //DontDestroyOnLoad(gameObject);
    245.         #region Look Settings - Start
    246.         mainCamera = GameObject.Find("Player Camera").GetComponent<Camera>();
    247.  
    248.         if (autoCrosshair || drawStaminaMeter){
    249.             Canvas canvas = new GameObject("AutoCrosshair").AddComponent<Canvas>();
    250.             canvas.gameObject.AddComponent<CanvasScaler>().uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
    251.             canvas.renderMode = RenderMode.ScreenSpaceOverlay;
    252.             canvas.pixelPerfect = true;
    253.             canvas.transform.SetParent(mainCamera.transform);
    254.             canvas.transform.position = Vector3.zero;
    255.  
    256.             if(autoCrosshair){
    257.                 Image crossHair = new GameObject("Crosshair").AddComponent<Image>();
    258.                 crossHair.sprite = Crosshair;
    259.                 crossHair.rectTransform.sizeDelta = new Vector2(25,25);
    260.                 crossHair.transform.SetParent(canvas.transform);
    261.                 crossHair.transform.position = Vector3.zero;
    262.             }
    263.  
    264.             if(drawStaminaMeter){
    265.                 StaminaMeterBG = new GameObject("StaminaMeter").AddComponent<Image>();
    266.                 StaminaMeter = new GameObject("Meter").AddComponent<Image>();
    267.                 StaminaMeter.transform.SetParent(StaminaMeterBG.transform);
    268.                 StaminaMeterBG.transform.SetParent(canvas.transform);
    269.                 StaminaMeterBG.transform.position = Vector3.zero;
    270.                 StaminaMeterBG.rectTransform.anchorMax = new Vector2(0.5f,0);
    271.                 StaminaMeterBG.rectTransform.anchorMin = new Vector2(0.5f,0);
    272.                 StaminaMeterBG.rectTransform.anchoredPosition = new Vector2(0,15);
    273.                 StaminaMeterBG.rectTransform.sizeDelta = new Vector2(250,6);
    274.                 StaminaMeterBG.color = new Color(0,0,0,0);
    275.                 StaminaMeter.rectTransform.sizeDelta = new Vector2(250,6);
    276.                 StaminaMeter.color = new Color(0,0,0,0);
    277.             }
    278.         }
    279.         mouseSensitivityInternal = mouseSensitivity;
    280.         cameraStartingPosition = playerCamera.transform.localPosition;
    281.        // if(lockAndHideCursor) { Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; }
    282.         baseCamFOV = playerCamera.fieldOfView;
    283.         #endregion
    284.  
    285.         #region Movement Settings - Start
    286.         staminaInternal = staminaLevel;
    287.         advanced.zeroFrictionMaterial = new PhysicMaterial("Zero_Friction");
    288.         advanced.zeroFrictionMaterial.dynamicFriction =0;
    289.         advanced.zeroFrictionMaterial.staticFriction =0;
    290.         advanced.zeroFrictionMaterial.frictionCombine = PhysicMaterialCombine.Minimum;
    291.         advanced.zeroFrictionMaterial.bounceCombine = PhysicMaterialCombine.Minimum;
    292.         advanced.highFrictionMaterial = new PhysicMaterial("Max_Friction");
    293.         advanced.highFrictionMaterial.dynamicFriction =1;
    294.         advanced.highFrictionMaterial.staticFriction =1;
    295.         advanced.highFrictionMaterial.frictionCombine = PhysicMaterialCombine.Maximum;
    296.         advanced.highFrictionMaterial.bounceCombine = PhysicMaterialCombine.Average;
    297.         #endregion
    298.  
    299.         #region Headbobbing Settings - Start
    300.      
    301.         originalLocalPosition = snapHeadjointToCapsul ? new Vector3(head.localPosition.x, (capsule.height/2)*head.localScale.y ,head.localPosition.z) : head.localPosition;
    302.         if(GetComponent<AudioSource>() == null) { gameObject.AddComponent<AudioSource>(); }
    303.  
    304.         previousPosition = fps_Rigidbody.position;
    305.         audioSource = GetComponent<AudioSource>();
    306.         #endregion
    307.  
    308.         #region BETA_SETTINGS - Start
    309.         fOVKick.fovStart = playerCamera.fieldOfView;
    310.         #endregion
    311.  
    312.         bossDetection = GetComponent<PlayerEnemyInteraction>();
    313.    
    314.     }
    315.  
    316.     private void Update()
    317.     {
    318.  
    319.  
    320.  
    321.         #region Look Settings - Update
    322.  
    323.         if (enableCameraMovement && !GameManager.Instance.isPaused)
    324.         {
    325.             float mouseYInput;
    326.             float mouseXInput;
    327.             float camFOV = playerCamera.fieldOfView;
    328.             mouseYInput = mouseInputInversion == InvertMouseInput.None || mouseInputInversion == InvertMouseInput.X ? Input.GetAxis("Mouse Y") : -Input.GetAxis("Mouse Y");
    329.             mouseXInput = mouseInputInversion == InvertMouseInput.None || mouseInputInversion == InvertMouseInput.Y ? Input.GetAxis("Mouse X") : -Input.GetAxis("Mouse X");
    330.             if (targetAngles.y > 180) { targetAngles.y -= 360; followAngles.y -= 360; } else if (targetAngles.y < -180) { targetAngles.y += 360; followAngles.y += 360; }
    331.             if (targetAngles.x > 180) { targetAngles.x -= 360; followAngles.x -= 360; } else if (targetAngles.x < -180) { targetAngles.x += 360; followAngles.x += 360; }
    332.             targetAngles.y += mouseXInput * (mouseSensitivityInternal - ((baseCamFOV - camFOV) * fOVToMouseSensitivity) / 6f);
    333.             targetAngles.x += mouseYInput * (mouseSensitivityInternal - ((baseCamFOV - camFOV) * fOVToMouseSensitivity) / 6f);
    334.             targetAngles.y = Mathf.Clamp(targetAngles.y, -0.5f * Mathf.Infinity, 0.5f * Mathf.Infinity);
    335.             targetAngles.x = Mathf.Clamp(targetAngles.x, -0.5f * verticalRotationRange, 0.5f * verticalRotationRange);
    336.             followAngles = Vector3.SmoothDamp(followAngles, targetAngles, ref followVelocity, (cameraSmoothing) / 100);
    337.             playerCamera.transform.localRotation = Quaternion.Euler(-followAngles.x + originalRotation.x, 0, 0);
    338.             transform.localRotation = Quaternion.Euler(0, followAngles.y + originalRotation.y, 0);
    339.         }
    340.  
    341.         #endregion
    342.  
    343.         RaycastHit hitCrouch;
    344.         if (Physics.SphereCast(transform.position, capsule.radius + .15f, Vector3.up, out hitCrouch, .7f))
    345.         {
    346.             if (hitCrouch.transform.gameObject.CompareTag("crouch"))
    347.             {
    348.  
    349.                 _crouchModifiers.crouchOverride = true;
    350.                 above = true;
    351.             }
    352.             else
    353.             {
    354.  
    355.                 above = false;
    356.                 _crouchModifiers.crouchOverride = false;
    357.             }
    358.  
    359.         }
    360.         else
    361.         {
    362.             above = false;
    363.             _crouchModifiers.crouchOverride = false;
    364.         }
    365.  
    366.  
    367.  
    368.  
    369.         #region  Input Settings - Update
    370.         didJump = canHoldJump ? Input.GetButton("Jump") : Input.GetButtonDown("Jump");
    371.         if (!canJump) { didJump = false; }
    372.         yVelocity = fps_Rigidbody.velocity.y;
    373.         if (IsGrounded && didJump && jumpPowerInternal > 0)
    374.         {
    375.             yVelocity += jumpPowerInternal;
    376.             IsGrounded = false;
    377.             didJump = false;
    378.             if (playerCanMove) { fps_Rigidbody.velocity = (Vector3.up * yVelocity); }
    379.         }
    380.         if (advanced._maxSlopeAngle > 0 && IsGrounded && SlopeCheck() <= 0.25f) { yVelocity *= SlopeCheck(); }
    381.         //if(){didJump = false;}
    382.  
    383.         if (_crouchModifiers.useCrouch)
    384.         {
    385.             if (!_crouchModifiers.toggleCrouch)
    386.             {
    387.                 isCrouching = _crouchModifiers.crouchOverride || Input.GetKey(_crouchModifiers.crouchKey);
    388.             }
    389.             else
    390.             {
    391.                 if (Input.GetKeyDown(_crouchModifiers.crouchKey))
    392.                 {
    393.                     isCrouching = !isCrouching || _crouchModifiers.crouchOverride;
    394.                 }
    395.             }
    396.         }
    397.  
    398.  
    399.         #endregion
    400.  
    401.  
    402.  
    403.  
    404.  
    405.  
    406.  
    407.  
    408.         //Debug.Log(dMove);
    409.  
    410.  
    411.     }
    412.  
    413.  
    414.  
    415.     private void FixedUpdate()
    416.     {
    417.  
    418.  
    419.  
    420.  
    421.         #region Headbobbing Settings - FixedUpdate
    422.         float yPos = 0;
    423.         float xPos = 0;
    424.         float zTilt = 0;
    425.         float xTilt = 0;
    426.         float bobSwayFactor = 0;
    427.         float bobFactor = 0;
    428.         float strideLangthen = 0;
    429.         float flatVel = 0;
    430.         //calculate headbob freq
    431.         if (useHeadbob == true || fsmode == FSMode.Dynamic)
    432.         {
    433.             Vector3 vel = (fps_Rigidbody.position - previousPosition) / Time.deltaTime;
    434.             Vector3 velChange = vel - previousVelocity;
    435.             previousPosition = fps_Rigidbody.position;
    436.             previousVelocity = vel;
    437.             springVelocity -= velChange.y;
    438.             springVelocity -= springPosition * springElastic;
    439.             springVelocity *= springDampen;
    440.             springPosition += springVelocity * Time.deltaTime;
    441.             springPosition = Mathf.Clamp(springPosition, -0.3f, 0.3f);
    442.  
    443.             if (Mathf.Abs(springVelocity) < springVelocityThreshold && Mathf.Abs(springPosition) < springPositionThreshold) { springPosition = 0; springVelocity = 0; }
    444.             flatVel = new Vector3(vel.x, 0.0f, vel.z).magnitude;
    445.             strideLangthen = 1 + (flatVel * ((headbobFrequency * 2) / 10));
    446.             headbobCycle += (flatVel / strideLangthen) * (Time.deltaTime / headbobFrequency);
    447.             bobFactor = Mathf.Sin(headbobCycle * Mathf.PI * 2);
    448.             bobSwayFactor = Mathf.Sin(Mathf.PI * (2 * headbobCycle + 0.5f));
    449.             bobFactor = 1 - (bobFactor * 0.5f + 1);
    450.             bobFactor *= bobFactor;
    451.  
    452.             yPos = 0;
    453.             xPos = 0;
    454.             zTilt = 0;
    455.             if (jumpLandIntensity > 0 && !advanced.stairMiniHop)
    456.             {
    457.                 xTilt = -springPosition * (jumpLandIntensity * 5.5f);
    458.             }
    459.             else if (!advanced.stairMiniHop) { xTilt = -springPosition; }
    460.  
    461.             if (IsGrounded)
    462.             {
    463.                 if (new Vector3(vel.x, 0.0f, vel.z).magnitude < 0.1f) { headbobFade = Mathf.MoveTowards(headbobFade, 0.0f, 0.5f); } else { headbobFade = Mathf.MoveTowards(headbobFade, 1.0f, Time.deltaTime); }
    464.                 float speedHeightFactor = 1 + (flatVel * 0.3f);
    465.                 xPos = -(headbobSideMovement / 10) * headbobFade * bobSwayFactor;
    466.                 yPos = springPosition * (jumpLandIntensity / 10) + bobFactor * (headbobHeight / 10) * headbobFade * speedHeightFactor;
    467.                 zTilt = bobSwayFactor * (headbobSwayAngle / 10) * headbobFade;
    468.             }
    469.         }
    470.         //apply headbob position
    471.         if (useHeadbob == true)
    472.         {
    473.             if (fps_Rigidbody.velocity.magnitude > 0.1f)
    474.             {
    475.                 head.localPosition = Vector3.MoveTowards(head.localPosition, snapHeadjointToCapsul ? (new Vector3(originalLocalPosition.x, (capsule.height / 2) * head.localScale.y, originalLocalPosition.z) + new Vector3(xPos, yPos, 0)) : originalLocalPosition + new Vector3(xPos, yPos, 0), 0.5f);
    476.             }
    477.             else
    478.             {
    479.                 head.localPosition = Vector3.SmoothDamp(head.localPosition, snapHeadjointToCapsul ? (new Vector3(originalLocalPosition.x, (capsule.height / 2) * head.localScale.y, originalLocalPosition.z) + new Vector3(xPos, yPos, 0)) : originalLocalPosition + new Vector3(xPos, yPos, 0), ref miscRefVel, 0.15f);
    480.             }
    481.             head.localRotation = Quaternion.Euler(xTilt, 0, zTilt);
    482.  
    483.  
    484.         }
    485.         #endregion
    486.  
    487.    
    488.  
    489.  
    490.  
    491.  
    492.  
    493.         #region Movement Settings - FixedUpdate
    494.  
    495.         bool wasWalking = !isSprinting;
    496.         if (useStamina)
    497.         {
    498.             isSprinting = Input.GetKey(sprintKey) && !isCrouching && staminaInternal > 0 && (Mathf.Abs(fps_Rigidbody.velocity.x) > 0.01f || Mathf.Abs(fps_Rigidbody.velocity.x) > 0.01f);
    499.             if (isSprinting)
    500.             {
    501.                 staminaInternal -= (staminaDepletionSpeed * 2) * Time.deltaTime;
    502.                 if (drawStaminaMeter)
    503.                 {
    504.                     StaminaMeterBG.color = Vector4.MoveTowards(StaminaMeterBG.color, new Vector4(0, 0, 0, 0.5f), 0.15f);
    505.                     StaminaMeter.color = Vector4.MoveTowards(StaminaMeter.color, new Vector4(1, 1, 1, 1), 0.15f);
    506.                 }
    507.             }
    508.             else if ((!Input.GetKey(sprintKey) || Mathf.Abs(fps_Rigidbody.velocity.x) < 0.01f || Mathf.Abs(fps_Rigidbody.velocity.x) < 0.01f || isCrouching) && staminaInternal < staminaLevel)
    509.             {
    510.                 staminaInternal += staminaDepletionSpeed * Time.deltaTime;
    511.             }
    512.             if (drawStaminaMeter)
    513.             {
    514.  
    515.                 if (staminaInternal == staminaLevel)
    516.                 {
    517.                     StaminaMeterBG.color = Vector4.MoveTowards(StaminaMeterBG.color, new Vector4(0, 0, 0, 0), 0.15f);
    518.                     StaminaMeter.color = Vector4.MoveTowards(StaminaMeter.color, new Vector4(1, 1, 1, 0), 0.15f);
    519.                 }
    520.                 float x = Mathf.Clamp(Mathf.SmoothDamp(StaminaMeter.transform.localScale.x, (staminaInternal / staminaLevel) * StaminaMeterBG.transform.localScale.x, ref smoothRef, (1) * Time.deltaTime, 1), 0.001f, StaminaMeterBG.transform.localScale.x);
    521.                 StaminaMeter.transform.localScale = new Vector3(x, 1, 1);
    522.             }
    523.             staminaInternal = Mathf.Clamp(staminaInternal, 0, staminaLevel);
    524.         }
    525.         else { isSprinting = Input.GetKey(sprintKey); }
    526.  
    527.         dMove = Vector3.zero;
    528.         speed = walkByDefault ? isCrouching ? walkSpeedInternal : (isSprinting ? sprintSpeedInternal : walkSpeedInternal) : (isSprinting ? walkSpeedInternal : sprintSpeedInternal);
    529.  
    530.  
    531.         if (advanced._maxSlopeAngle > 0 && Physics.Raycast(transform.position - new Vector3(0, ((capsule.height / 2) * transform.localScale.y) - capsule.radius, 0), new Vector3(dMove.x, -1.5f, dMove.z), out advanced.surfaceAngleCheck, capsule.radius * 4))
    532.         {
    533.             dMove = ((transform.forward * inputXY.y * speed + transform.right * inputXY.x * walkSpeedInternal) * SlopeCheck()) + Vector3.up * fps_Rigidbody.velocity.y;
    534.         }
    535.         else
    536.         {
    537.             dMove = (transform.forward * inputXY.y * speed + transform.right * inputXY.x * walkSpeedInternal) + Vector3.up * fps_Rigidbody.velocity.y;
    538.         }
    539.  
    540.         RaycastHit WT;
    541.         if (advanced.maxStepHeight > 0 && Physics.Raycast(transform.position - new Vector3(0, ((capsule.height / 2) * transform.localScale.y) - 0.01f, 0), dMove, out WT, capsule.radius + 0.15f) && Vector3.Angle(WT.normal, Vector3.up) > 88)
    542.         {
    543.             RaycastHit ST;
    544.             if (!Physics.Raycast(transform.position - new Vector3(0, ((capsule.height / 2) * transform.localScale.y) - (advanced.maxStepHeight), 0), dMove, out ST, capsule.radius + 0.25f))
    545.             {
    546.                 advanced.stairMiniHop = true;
    547.                 transform.position += new Vector3(0, advanced.maxStepHeight * 1.2f, 0);
    548.             }
    549.         }
    550.  
    551.         float horizontalInput = Input.GetAxis("Horizontal");
    552.         float verticalInput = Input.GetAxis("Vertical");
    553.         inputXY = new Vector2(horizontalInput, verticalInput);
    554.         if (inputXY.magnitude > 1) { inputXY.Normalize(); }
    555.  
    556.  
    557.  
    558.         if (playerCanMove)
    559.         {
    560.             fps_Rigidbody.velocity = dMove;
    561.  
    562.         }
    563.         else
    564.         {
    565.  
    566.             fps_Rigidbody.velocity = Vector3.zero;
    567.         }
    568.  
    569.         if (dMove.magnitude > 0 || !IsGrounded)
    570.         {
    571.             capsule.sharedMaterial = advanced.zeroFrictionMaterial;
    572.         }
    573.         else { capsule.sharedMaterial = advanced.highFrictionMaterial; }
    574.  
    575.         fps_Rigidbody.AddForce(Physics.gravity * (advanced.gravityMultiplier - 1));
    576.  
    577.  
    578.  
    579.         if (_crouchModifiers.useCrouch)
    580.         {
    581.  
    582.             if (isCrouching)
    583.             {
    584.              
    585.                 capsule.height = Mathf.MoveTowards(capsule.height, _crouchModifiers.colliderHeight / _crouchModifiers.crouchHeight, 5 * Time.deltaTime);
    586.                 walkSpeedInternal = walkSpeed * _crouchModifiers.crouchWalkSpeedMultiplier;
    587.                 jumpPowerInternal = jumpPower * _crouchModifiers.crouchJumpPowerMultiplier;
    588.  
    589.             }
    590.             else if (!above)
    591.             {
    592.              
    593.                 capsule.height = Mathf.MoveTowards(capsule.height, _crouchModifiers.colliderHeight, 5 * Time.deltaTime);
    594.                 walkSpeedInternal = walkSpeed;
    595.                 sprintSpeedInternal = sprintSpeed;
    596.                 jumpPowerInternal = jumpPower;
    597.             }
    598.         }
    599.  
    600.  
    601.  
    602.         #endregion
    603.  
    604.  
    605.  
    606.     }
    607.  
    608.  
    609.     public void damageJerk()
    610.     {
    611.         float xTilt = -springPosition * (jumpLandIntensity * 5.5f);
    612.         float bobSwayFactor = Mathf.Sin(Mathf.PI * (2 * headbobCycle + 0.5f));
    613.         float zTilt = bobSwayFactor * (headbobSwayAngle / 10) * headbobFade;
    614.         head.localRotation = Quaternion.Euler(xTilt, 0, zTilt);
    615.     }
    616.  
    617.     public void stopCrouching()
    618.     {
    619.         capsule.height = Mathf.MoveTowards(capsule.height, _crouchModifiers.colliderHeight, 5 * Time.deltaTime);
    620.         walkSpeedInternal = walkSpeed;
    621.         sprintSpeedInternal = sprintSpeed;
    622.         jumpPowerInternal = jumpPower;
    623.     }
    624.  
    625.  
    626.  
    627.  
    628.  
    629.     float SlopeCheck(){
    630.             advanced.lastKnownSlopeAngle =  (Vector3.Angle(advanced.surfaceAngleCheck.normal, Vector3.up));
    631.             return new AnimationCurve(new Keyframe(-90.0f, 1.0f), new Keyframe(0.0f, 1.0f), new Keyframe(advanced._maxSlopeAngle, 0.0f),new Keyframe(90, 0.0f)){preWrapMode = WrapMode.Clamp, postWrapMode = WrapMode.ClampForever}.Evaluate(advanced.lastKnownSlopeAngle);
    632.     }
    633.  
    634.     public void RotateCamera(Vector2 Rotation){
    635.         enableCameraMovement = !enableCameraMovement;
    636.         targetAngles = Rotation;
    637.         enableCameraMovement = !enableCameraMovement;
    638.     }
    639.  
    640.     private void OnCollisionStay(Collision CollisionData) {
    641.         if(IsGrounded || fps_Rigidbody.velocity.y < 0.1){
    642.             IsGrounded = false;
    643.             for(int i = 0; i<CollisionData.contactCount; i++){
    644.                 if(CollisionData.GetContact(i).point.y < (transform.position.y - (capsule.radius+0.21f))){
    645.                     IsGrounded = true;
    646.                     advanced.stairMiniHop = false;
    647.                 }
    648.             }
    649.         }
    650.     }
    651. }
    652.  
    653.  

    Here is a picture of the rigidbody component on the player:
    https://imgur.com/WawRerq

    I also saw several posts, videos, and articles relating to this issue but nothing has worked for me. Here is a list of all the stuff I tried but did NOT work:

    Setting rigidbody interpolate to "Interpolate"

    Building the game using the "Exclusive Build" option -
    Building the game actually gets rid of most of the stuttering but it still can be seen in 2 areas of the level when I play it on my computer. These areas of the level are less performant since one of them is a terrain area and the other is a security room with CCTV where multiple cameras are rendering at the same time. Although, the stuttering is visible everywhere in the level when playing the build on lower-end computers, but not visible anywhere when playing on high-end computers.

    Decreasing the physics time step - Reduced the stuttering in the editor but not in the build. The performance also takes a huge hit.

    Increase the "Default Contact Offset" value in project settings

    Moving all movement code to either FixedUpdate, Update, or LateUpdate.

    Have a separate camera follow the player using "Lerp" or "SmoothDamp"
    - I made the camera its own separate object in the hierarchy. I tried moving the camera using Update, LateUpdate, and FixedUpdate but saw no improvement. Here is the script I use:
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class camFollow : MonoBehaviour
    7. {
    8.     public Transform camPos;
    9.     public Vector3 velocity = Vector3.one;
    10.     Quaternion angle = Quaternion.identity;
    11.  
    12.  
    13.  
    14.     private void LateUpdate()
    15.     {
    16.         if(!GameManager.Instance.isPaused)
    17.         {
    18.  
    19.             transform.position = Vector3.SmoothDamp(transform.position, camPos.position , ref velocity, .05f);
    20.             //transform.position = camPos.position;
    21.             transform.rotation = camPos.rotation;
    22.             //transform.rotation = SmoothDamp(transform.rotation, camPos.rotation, ref angle, .05f);
    23.         }
    24.  
    25.    
    26.  
    27.  
    28.     }
    29.  
    30.  
    31.     public static Quaternion SmoothDamp(Quaternion rot, Quaternion target, ref Quaternion deriv, float time)
    32.     {
    33.         // account for double-cover
    34.         var Dot = Quaternion.Dot(rot, target);
    35.         var Multi = Dot > 0f ? 1f : -1f;
    36.         target.x *= Multi;
    37.         target.y *= Multi;
    38.         target.z *= Multi;
    39.         target.w *= Multi;
    40.         // smooth damp (nlerp approx)
    41.         var Result = new Vector4(
    42.             Mathf.SmoothDamp(rot.x, target.x, ref deriv.x, time),
    43.             Mathf.SmoothDamp(rot.y, target.y, ref deriv.y, time),
    44.             Mathf.SmoothDamp(rot.z, target.z, ref deriv.z, time),
    45.             Mathf.SmoothDamp(rot.w, target.w, ref deriv.w, time)
    46.         ).normalized;
    47.         // compute deriv
    48.         var dtInv = 1f / Time.deltaTime;
    49.         deriv.x = (Result.x - rot.x) * dtInv;
    50.         deriv.y = (Result.y - rot.y) * dtInv;
    51.         deriv.z = (Result.z - rot.z) * dtInv;
    52.         deriv.w = (Result.w - rot.w) * dtInv;
    53.         return new Quaternion(Result.x, Result.y, Result.z, Result.w);
    54.     }
    55.  
    56.  
    57.  
    58. }
    59.  

    Move everything closer to the origin

    Turn V-sync off
    - turning v-sync off had no effect on the stuttering.

    I should also note that the stuttering issue arose after I greatly optimized the game. The batches reduced from 14,000 to only about 500. The stuttering wasn't a problem before the optimization even when running on a lower-end computer. Any suggestions on how to stop the stuttering will be much appreciated. Thanks in advance.
     
    Last edited: Jun 6, 2020
  2. Sluggy

    Sluggy

    Joined:
    Nov 27, 2012
    Posts:
    960