Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Jackv949 · Feb 24, 2014 at 09:42 AM · camerathird-personjitterperson

How do I fix this jitter problem?

I have been following some tutorials on 3D Buzz to create a 3rd person camera & control system. Everything works perfectly...almost. There is functionality that is meant to make a player slide down slopes when it is too steep, but it just creates a hug amount of jitter while doing so. Here's a video example: link text. There is also jitter when going up the steep slope, but it doesn't show on the 30fps video, which has lead me to believe that it has something to do with frame-rate. The system is made of 3 .cs files so I will post them below. Any help is appreciated.

TP_Camera:

 using UnityEngine;
 using System.Collections;
 
 public class TP_Camera : MonoBehaviour 
 {
     public static TP_Camera Instance;
 
     public Transform TargetLookAt;
 
     public float Distance = 5.0f;
     public float DistanceMin = 1.0f;
     public float DistanceMax = 15.0f;
     public float DistanceSmooth = 0.05f;
     public float DistanceResumeSmooth = 1f;
     public float X_MouseSensitivity = 5.0f;
     public float Y_MouseSensitivity = 5.0f;
     public float MouseWheelSensitivity = 5.0f;
     public float X_Smooth = 0.05f;
     public float Y_Smooth = 0.1f;
     public float Y_MinLimit = -40f;
     public float Y_MaxLimit = 80f;
     public float OcclusionDistanceStep = 0.5f;
     public int MaxOcclusionChecks = 10;
 
     private bool isMouseVisible = true;
     private bool useRightMouseToOrbitCamera = true;
     private float mouseX = 0.0f;
     private float mouseY = 0.0f;
     private float velX = 0.0f;
     private float velY = 0.0f;
     private float velZ = 0.0f;
     private float velDistance = 0.0f;
     private float startDistance = 0.0f;
     private Vector3 position = Vector3.zero;
     private Vector3 desiredPosition = Vector3.zero;
     private float desiredDistance = 0.0f;
     private float distanceSmooth = 0f;
     private float preOccludedDistance = 0;
 
     void Awake()
     {
         Instance = this;
     }
 
     void Start() 
     {
         Distance = Mathf.Clamp(Distance, DistanceMin, DistanceMax);
         startDistance = Distance;
         Reset();
     }
 
     void Update()
     {
         if (Input.GetButtonUp("ToggleMouseVisibility"))
             ToggleMouseVisibility();
     }
 
     void LateUpdate() 
     {
         if (TargetLookAt == null)
             return;
 
         HandlePlayerInput();
 
         var count = 0;
         do
         {
             CalculateDesiredPosition();
             count++;
         } while (CheckIfOccluded(count));
 
         UpdatePosition();
     }
 
     void ToggleMouseVisibility()
     {
         isMouseVisible = !isMouseVisible;
 
         if (isMouseVisible)
         {
            Screen.showCursor = true;
             Screen.lockCursor = false;
         }
         else
         {
             Screen.showCursor = false;
             Screen.lockCursor = true;
         }
 
         useRightMouseToOrbitCamera = isMouseVisible;
     }
 
     void HandlePlayerInput()
     {
         float deadZone = 0.01f;
 
         if (Input.GetMouseButton(1) || useRightMouseToOrbitCamera == false)
         {
             // The RMB is down get mouse axis input.
             mouseX += Input.GetAxis("Mouse X") * X_MouseSensitivity;
             mouseY -= Input.GetAxis("Mouse Y") * Y_MouseSensitivity;
         }
 
         // This is where we will limit mouseY
         mouseY = Helper.ClampAngle(mouseY, Y_MinLimit, Y_MaxLimit);
 
         if (Input.GetAxis("Mouse ScrollWheel") < -deadZone || Input.GetAxis("Mouse ScrollWheel") > deadZone)
         {
             desiredDistance = Mathf.Clamp(Distance - Input.GetAxis("Mouse ScrollWheel") * MouseWheelSensitivity, DistanceMin, DistanceMax);
             preOccludedDistance = desiredDistance;
             distanceSmooth = DistanceSmooth;
         }
     }
 
     void CalculateDesiredPosition()
     {
         // Evaluate distance
         ResetDesiredDistance();
         Distance = Mathf.SmoothDamp(Distance, desiredDistance, ref velDistance, distanceSmooth);
 
         // Calculate desired position
         desiredPosition = CalculatePosition(mouseY, mouseX, Distance);
     }
 
     Vector3 CalculatePosition(float rotationX, float rotationY, float distance)
     {
         Vector3 direction = new Vector3(0, 0, -distance);
         Quaternion rotation = Quaternion.Euler(rotationX, rotationY, 0);
         return TargetLookAt.position + rotation * direction;
     }
 
     bool CheckIfOccluded(int count)
     {
         var isOccluded = false;
 
         var nearestDistance = CheckCameraPoints(TargetLookAt.position, desiredPosition);
 
         if (nearestDistance != -1)
         {
             if (count < MaxOcclusionChecks)
             {
                 isOccluded = true;
                 Distance -= OcclusionDistanceStep;
 
                 if (Distance < 0.25f)
                     Distance = 0.25f;
             }
             else
                 Distance = nearestDistance - Camera.main.nearClipPlane;
 
             desiredDistance = Distance;
             distanceSmooth = DistanceResumeSmooth;
         }
 
         return isOccluded;
     }
 
     float CheckCameraPoints(Vector3 from, Vector3 to)
     {
         var nearestDistance = -1f;
 
         RaycastHit hitInfo;
 
         Helper.ClipPlanePoints clipPlanePoints = Helper.ClipPlaneAtNear(to);
 
         // Draw lines in the editor to make it easier to visualise
         Debug.DrawLine(from, to + transform.forward * -camera.nearClipPlane, Color.red);
         Debug.DrawLine(from, clipPlanePoints.UpperLeft);
         Debug.DrawLine(from, clipPlanePoints.LowerLeft);
         Debug.DrawLine(from, clipPlanePoints.UpperRight);
         Debug.DrawLine(from, clipPlanePoints.LowerRight);
 
         Debug.DrawLine(clipPlanePoints.UpperLeft, clipPlanePoints.UpperRight);
         Debug.DrawLine(clipPlanePoints.UpperRight, clipPlanePoints.LowerRight);
         Debug.DrawLine(clipPlanePoints.LowerRight, clipPlanePoints.LowerLeft);
         Debug.DrawLine(clipPlanePoints.LowerLeft, clipPlanePoints.UpperLeft);
 
         if (Physics.Linecast(from, clipPlanePoints.UpperLeft, out hitInfo) && hitInfo.collider.tag != "Player")
             nearestDistance = hitInfo.distance;
 
         if (Physics.Linecast(from, clipPlanePoints.LowerLeft, out hitInfo) && hitInfo.collider.tag != "Player")
             if (hitInfo.distance < nearestDistance || nearestDistance == -1)
                 nearestDistance = hitInfo.distance;
 
         if (Physics.Linecast(from, clipPlanePoints.UpperRight, out hitInfo) && hitInfo.collider.tag != "Player")
             if (hitInfo.distance < nearestDistance || nearestDistance == -1)
                 nearestDistance = hitInfo.distance;
 
         if (Physics.Linecast(from, clipPlanePoints.LowerRight, out hitInfo) && hitInfo.collider.tag != "Player")
             if (hitInfo.distance < nearestDistance || nearestDistance == -1)
                 nearestDistance = hitInfo.distance;
 
         if (Physics.Linecast(from, to + transform.forward * -camera.nearClipPlane, out hitInfo) && hitInfo.collider.tag != "Player")
             if (hitInfo.distance < nearestDistance || nearestDistance == -1)
                 nearestDistance = hitInfo.distance;
 
         return nearestDistance;
     }
 
     void ResetDesiredDistance()
     {
         if (desiredDistance < preOccludedDistance)
         {
             var pos = CalculatePosition(mouseY, mouseX, preOccludedDistance);
 
             var nearestDistance = CheckCameraPoints(TargetLookAt.position, pos);
 
             if (nearestDistance == -1 || nearestDistance > preOccludedDistance)
             {
                 desiredDistance = preOccludedDistance;
             }
         }
     }
 
     void UpdatePosition()
     {
         float posX = Mathf.SmoothDamp(position.x, desiredPosition.x, ref velX, X_Smooth);
         float posY = Mathf.SmoothDamp(position.y, desiredPosition.y, ref velY, Y_Smooth);
         float posZ = Mathf.SmoothDamp(position.z, desiredPosition.z, ref velZ, X_Smooth);
         position = new Vector3(posX, posY, posZ);
 
         transform.position = position;
 
         transform.LookAt(TargetLookAt);
     }
 
     public void Reset()
     {
         mouseX = 0.0f;
         mouseY = 10.0f;
         Distance = startDistance;
         desiredDistance = Distance;
         preOccludedDistance = Distance;
     }
 
     public static void UseExistingOrCreateNewMainCamera()
     {
         GameObject tempCamera;
         GameObject targetLookat;
         TP_Camera myCamera;
 
         if (Camera.main != null)
         {
             tempCamera = Camera.main.gameObject;
         }
         else
         {
             tempCamera = new GameObject("Main Camera");
             tempCamera.AddComponent<Camera>();
             tempCamera.tag = "MainCamera";
         }
 
         tempCamera.AddComponent<TP_Camera>();
         myCamera = tempCamera.GetComponent<TP_Camera>() as TP_Camera;
 
         targetLookat = GameObject.Find("targetLookAt") as GameObject;
 
         if (targetLookat == null)
         {
             targetLookat = new GameObject("targetLookAt");
             targetLookat.transform.position = Vector3.zero;
         }
 
         myCamera.TargetLookAt = targetLookat.transform;
     }
 }

TP_Controller:

 using UnityEngine;
 using System.Collections;
 
 public class TP_Controller : MonoBehaviour 
 {
     public static CharacterController CharacterController;
     public static TP_Controller Instance;
 
     void Awake() 
     {
         CharacterController = GetComponent<CharacterController>() as CharacterController;
         Instance = this;
         TP_Camera.UseExistingOrCreateNewMainCamera();
     }
 
     void Update() 
     {
         if(Camera.main == null)
             return;
 
         GetLocomotionInput();
         HandleActionInput();
 
         TP_Motor.Instance.UpdateMotor();
     }
 
     void GetLocomotionInput()
     {
         float deadzone = 0.1f;
 
         TP_Motor.Instance.VerticalVelocity = TP_Motor.Instance.MoveVector.y;
         TP_Motor.Instance.MoveVector = Vector3.zero;
 
         if(Input.GetAxis("Vertical") > deadzone || Input.GetAxis("Vertical") < -deadzone)
             TP_Motor.Instance.MoveVector += new Vector3(0, 0, Input.GetAxis("Vertical"));
 
         if(Input.GetAxis("Horizontal") > deadzone || Input.GetAxis("Horizontal") < -deadzone)
             TP_Motor.Instance.MoveVector += new Vector3(Input.GetAxis("Horizontal"), 0, 0);
 
         TP_Animator.Instance.DetermineCurrentMoveDirection();
     }
 
     void HandleActionInput()
     {
         if (Input.GetButton("Jump"))
         {
             Jump();
         }
     }
 
     void Jump()
     {
         TP_Motor.Instance.Jump();
     }
 }
 

TP_Motor:

 using UnityEngine;
 using System.Collections;
 
 public class TP_Motor : MonoBehaviour 
 {
     public static TP_Motor Instance;
 
     public float ForwardSpeed = 10.0f;
     public float BackwardSpeed = 2.0f;
     public float StrafingSpeed = 5.0f;
     public float SlideSpeed = 10f;
     public float JumpSpeed = 6.0f;
     public float Gravity = 21.0f;
     public float TerminalVelocity = 20.0f;
     public float SlideThreshold = 0.6f;
     public float MaxControllableSlideMagnitude = 0.4f;
 
     private Vector3 slideDirection;
 
     public Vector3 MoveVector { get; set; }
     public float VerticalVelocity { get; set; }
 
     void Awake() 
     {
         Instance = this;
     }
 
     public void UpdateMotor() 
     {
         SnapAlignCharacterWithCamera();
         ProcessMotion();
     }
 
     void ProcessMotion()
     {
         // Transform moveVector to world space
         MoveVector = transform.TransformDirection(MoveVector);
 
         // Normalize MoveVector if magnitude > 1
         if(MoveVector.magnitude > 1)
             MoveVector = Vector3.Normalize(MoveVector);
 
         // Apply sliding if applicable
         ApplySlide();
 
         // Multiply MoveVector by moveSpeed
         MoveVector *= MoveSpeed();
 
         // Reapply Vertical velocity to MoveVector.y
         MoveVector = new Vector3(MoveVector.x, VerticalVelocity, MoveVector.z);
 
         // Apply gravity
         ApplyGravity();
 
         // Move the character in world space
         TP_Controller.CharacterController.Move(MoveVector * Time.deltaTime);
     }
 
     void ApplyGravity()
     {
         if (MoveVector.y > -TerminalVelocity)
             MoveVector = new Vector3(MoveVector.x, MoveVector.y - Gravity * Time.deltaTime, MoveVector.z);
 
         if (TP_Controller.CharacterController.isGrounded && MoveVector.y < -1)
             MoveVector = new Vector3(MoveVector.x, -1, MoveVector.z);
     }
 
     void ApplySlide()
     {
         if (!TP_Controller.CharacterController.isGrounded)
             return;
 
         slideDirection = Vector3.zero;
 
         RaycastHit hitInfo;
         if (Physics.Raycast(transform.position + Vector3.up, Vector3.down, out hitInfo))
         {
             if (hitInfo.normal.y < SlideThreshold)
                 slideDirection = new Vector3(hitInfo.normal.x, -hitInfo.normal.y, hitInfo.normal.z);
         }
 
         if (slideDirection.magnitude < MaxControllableSlideMagnitude)
             MoveVector += slideDirection;
         else
         {
             MoveVector = slideDirection;
         }
     }
 
     public void Jump()
     {
         if (TP_Controller.CharacterController.isGrounded)
             VerticalVelocity = JumpSpeed;
     }
 
     void SnapAlignCharacterWithCamera()
     {
         if(MoveVector.x != 0 || MoveVector.z != 0)
         {
             transform.rotation = Quaternion.Euler(transform.eulerAngles.x, Camera.main.transform.eulerAngles.y, transform.eulerAngles.z);
         }
     }
 
     float MoveSpeed()
     {
         float moveSpeed = 0.0f;
 
         switch (TP_Animator.Instance.MoveDirection)
         {
             case TP_Animator.Direction.Stationary:
                 moveSpeed = 0.0f;
                 break;
             case TP_Animator.Direction.Forward:
                 moveSpeed = ForwardSpeed;
                 break;
             case TP_Animator.Direction.Backward:
                 moveSpeed = BackwardSpeed;
                 break;
             case TP_Animator.Direction.Left:
                 moveSpeed = StrafingSpeed;
                 break;
             case TP_Animator.Direction.Right:
                 moveSpeed = StrafingSpeed;
                 break;
             case TP_Animator.Direction.LeftForward:
                 moveSpeed = ForwardSpeed;
                 break;
             case TP_Animator.Direction.RightForward:
                 moveSpeed = ForwardSpeed;
                 break;
             case TP_Animator.Direction.LeftBackward:
                 moveSpeed = BackwardSpeed;
                 break;
             case TP_Animator.Direction.RightBackward:
                 moveSpeed = BackwardSpeed;
                 break;
         }
 
         if (slideDirection.magnitude > 0)
             moveSpeed = SlideSpeed;
 
         return moveSpeed;
     }
 }
 

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

20 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Help with a simple 3rd person camera? 1 Answer

3rd person camera doesn't rotate as intended 0 Answers

Camera Help (WoW-like) 1 Answer

3rd Person Camera Problem 1 Answer

Camera collision 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges