Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 nordaj123 · Jun 14, 2017 at 08:01 AM · physicscharactercontrollercharacter movementlookjittering

Physics Based Character Controller Problems With Jitter

I wrote a Physics Based Character controller, everything is working well except I get a jitter that is noticeable when I look while moving. I must be doing both to notice it. The physics updates every 0.02(I think) seconds which is all fine and dandy until I use a camera look script which updates in the update method. With the almost too slow update for the character movement, using the camera at a different interval emphasizes this giving the jitter(that's my guess). I don't want to make physics update more often as that would be unnecessary to have the whole scene be more demanding. I have put the look script in fixed update and no longer noticed a jitter but I know other people could as i may not notice frame rate drops as much. Perhaps the scaling of everything is bad as I understand physics will act differently depending on sizes. I am using the default capsule with a scale of (1, 1, 1) for the temporary player. What i'm looking to do is figure out if I can update the player's physics more often than the rest but I doubt it. So is there any other way to help the situation? Or should I just slap the camera look script in a timer to update as physics do(don't want it directly in fixed update as it executes more than once).

Character Crontroller (Very unfinished):

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.UI;
 
 public class NewController : MonoBehaviour
 {
     //Public Variables
     [Range(0, 10)]
     public float acceleration = 3.75f;
     [Range(0, 10)]
     public float deceleration = 1.5f;
     [Tooltip("Anybody who can tell me why this is on a different scale than decel gets a cookie cuz im fucken confused...")]
     [Range(0, 10)]
     public float inAirDrag = 0.15f;
     public float minSlope = 0.4f;
     public float walkSpeed = 0.7f;
     public float runSpeed = 3.9f;
     public float jumpForce = 3.75f;
     public bool dblJump;
     public bool moveInAir;
     public bool toggleRun;
     public string horizontal = "Horizontal";
     public string vertical = "Vertical";
     public string jump = "Jump";
     public string run = "Run";
     public bool debugMode;
     [HideInInspector]
     public enum MoveState { Run, Walk, Idle, Jump, DiagLeftWalk, DiagRightWalk, DiagLeftRun, DiagRightRun, TurnLeft, TurnRight }
     public MoveState moveState { get; private set; }
 
     //Private Variables
     private bool isRunning;
     private Vector3 localVel;
     private Rigidbody rb;
     private float decel;
     private float accel;
     private bool isOnGround;
     private float iad;
     private bool hasUsedDoubleJump;
 
     void Start()
     {
         rb = GetComponent<Rigidbody>();
         decel = Map(0, 10, 1, 0, deceleration);
         accel = Map(0, 10, 0, 50, acceleration);
         iad = Map(0, 10, 1, 0, inAirDrag);
     }
 
     void Update()
     {
         #region DeterminRun
         if (isOnGround)
         {
             if (toggleRun)
             {
                 if (Input.GetButtonDown(run))
                     isRunning = !isRunning;
             }
             else
             {
                 isRunning = Input.GetButton(run);
             }
         }
         #endregion
 
         #region Movement
 
         //Move
         if (moveInAir)
         {
             rb.AddForce(transform.forward * (Input.GetAxisRaw(vertical) * accel * Time.deltaTime * 200), ForceMode.Acceleration);
             rb.AddForce(transform.right * (Input.GetAxisRaw(horizontal) * accel) * Time.deltaTime * 200, ForceMode.Acceleration);
         }
         else
         {
             if (isOnGround)
             {
                 rb.AddForce(transform.forward * (Input.GetAxisRaw(vertical) * accel * Time.deltaTime * 200), ForceMode.Acceleration);
                 rb.AddForce(transform.right * (Input.GetAxisRaw(horizontal) * accel * Time.deltaTime * 200), ForceMode.Acceleration);
             }
         }
 
         #endregion
 
         #region Control
         //Take Local Vel
         localVel = transform.InverseTransformDirection(rb.velocity);
 
         if (isOnGround)
         {
             //Apply Drag X
             if (Input.GetAxisRaw(horizontal) == 0)
                 localVel.x *= decel;
             //Apply Drag Z
             if (Input.GetAxisRaw(vertical) == 0)
                 localVel.z *= decel;
         }
         else
         {
             //Apply Drag X
             localVel.x *= iad;
             //Apply Drag Z
             localVel.z *= iad;
         }
 
         if (isOnGround || moveInAir)
         {
             //Clamp Z
             if (localVel.z > walkSpeed && !isRunning) localVel.z = walkSpeed;
             if (localVel.z > runSpeed && isRunning) localVel.z = runSpeed;
             if (localVel.z < -walkSpeed && !isRunning) localVel.z = -walkSpeed;
             if (localVel.z < -runSpeed && isRunning) localVel.z = -runSpeed;
             //Clamp X
             if (localVel.x > walkSpeed && !isRunning) localVel.x = walkSpeed;
             if (localVel.x > runSpeed && isRunning) localVel.x = runSpeed;
             if (localVel.x < -walkSpeed && !isRunning) localVel.x = -walkSpeed;
             if (localVel.x < -runSpeed && isRunning) localVel.x = -runSpeed;
         }
 
         //Apply Local Vel
         rb.velocity = transform.TransformDirection(localVel);
         #endregion
 
         #region Jumping
         if (Input.GetButtonDown(jump))
         {
             if (isOnGround)
             {
                 hasUsedDoubleJump = false;
                 rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
             }
             else if (!hasUsedDoubleJump && dblJump)
             {
                 rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
                 hasUsedDoubleJump = true;
             }
         }
         #endregion
     }
 
     void OnCollisionExit()
     {
         isOnGround = false;
     }
 
     void OnCollisionStay(Collision collision)
     {
         foreach (ContactPoint cp in collision.contacts)
         {
             if (cp.normal.y > minSlope)
             {
                 isOnGround = true;
             }
         }
     }
 
     float Map(float min1, float max1, float min2, float max2, float num)
     {
         return (num - min1) / (max1 - min1) * (max2 - min2) + min2;
     }
 }
 

Look Script:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class NewLook : MonoBehaviour
 {
     //Public Variables
     [Header("Looking")]
     [Range(0, 30)]
     public float sensitivity = 1;
     [Range(0, 30)]
     public float smoothing = 12;
     [Tooltip("Dont touch unless you know this script.")]
     [Range(0, 30)]
     public float distanceMultiplier = 1;
     [Tooltip("The limit of looking Up(U).")]
     public float ULimit = -95;
     [Tooltip("The limit of looking Down(D).")]
     public float DLimit = 95;
     public bool cheap = false;
     public bool useSmoothing = true;
 
     [Header("Input")]
     public string horizontalInput = "MouseX";
     public string verticalInput = "MouseX";
 
     [Header("References")]
     public Transform player;
 
     //Private Variables
     private float smoothingDist;
     float smoothFact;
     private Vector2 normal;
     private Vector2 smooth;
 
     void Start()
     {
         //Setting Current Values
         normal.x = player.localEulerAngles.y;
         smooth.x = player.localEulerAngles.y;
         normal.y = transform.localEulerAngles.x;
         smooth.y = transform.localEulerAngles.x;
     }
 
     void Update()
     {
         //Looking Logic
         if (!cheap && useSmoothing)
         {
             normal.x += Input.GetAxis(horizontalInput) * sensitivity;
             normal.y += Input.GetAxis(verticalInput) * sensitivity;
             smoothingDist = Vector2.Distance(normal, smooth);
             smoothFact = (smoothing * (smoothingDist * distanceMultiplier)) * Time.deltaTime;
             smooth = Vector2.MoveTowards(smooth, normal, smoothFact);
         }
         else if (cheap && useSmoothing)
         {
             normal.x += Input.GetAxis(horizontalInput) * sensitivity;
             normal.y += Input.GetAxis(verticalInput) * sensitivity;
             smooth = Vector2.MoveTowards(smooth, normal, smoothing);
         }
         else
         {
             smooth.x += Input.GetAxis(horizontalInput) * sensitivity;
             smooth.y += Input.GetAxis(verticalInput) * sensitivity;
         }
 
         //Look Limits
         if (smooth.y < ULimit)
             smooth.y = ULimit;
         if (smooth.y > DLimit)
             smooth.y = DLimit;
 
         //Gotta Do Look Limits For Normal Vector Too, FML
         if (normal.y < ULimit)
             normal.y = ULimit;
         if (normal.y > DLimit)
             normal.y = DLimit;
 
         //Applying Stuff
         transform.localEulerAngles = new Vector2(smooth.y, 0);
         player.localEulerAngles = new Vector2(player.localEulerAngles.x, smooth.x);
     }
 }
 

Feel free to try them for yourself and tell me if you can see it.

(Please do not use my code in your games)

Comment
Add comment · Show 1
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
avatar image TreyH · Jun 14, 2017 at 02:04 PM 0
Share

"Physics Based" and Update() do not always have a great relationship. Specifically, you are using AddForce() within an Update call. As FixedUpdate() is timed with the Physics engine, Physics operations are typically done there.

It's common to collect user input within the Update() cycle, but those inputs are typically delayed and implemented on the soonest FixedUpdate() call available.

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by Lili-Shi · Jun 14, 2017 at 07:01 PM

I have not entirely looked through you scripts, but let me paste in something I wrote in my look-script:

 /*
                    * NOTE: Making a camera LookAt an object, that _IS_ moved using phyics/rigidbodies,
                    * one should try any and any combinations of these steps to get rid of the weird jitter:
                    * 1) put the cam LookAt into LateUpdate
                    * 2) put the cam LookAt into FixedUpdate
                    * 3) set the rigidbody Interpolate to Interpolation / Extrapolation or even back to None
                   */


Basically, if you do anything via the physics system, you better put it into the FixedUpdate/LateUpdate method (not sure which it was), and also fiddle around with the Rigidbody interpolation.

Comment
Add comment · Share
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

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

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

Decrease character controller velocity by percent each frame 0 Answers

Low fps issues for character movement 0 Answers

Calculating linear speed at a point on a rotating platform 0 Answers

Gravity not working 1 Answer

Character Controller meets Rigidbody 1 Answer


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