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 ToeBeanGames · Apr 25, 2017 at 05:08 PM · rigidbodycharacter movement

Help with fixing character's physics

So I have this custom rigidbody-based character controller I'm making, and I need a bit of help tweaking the physics. Pretty much what's wring with it is A) player can stop and turn on a dime, B) walking uphill is slower than the regular walking speed, C) walking downhill is very jittery, D) for some reason my character moves faster diagonally than horizontally or vertically, and E) jumping is entirely momentum-based which is not very good for a platformer.

Here's the script:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 [AddComponentMenu("Controllers/Player Controller")]
 public class PlayerController : MonoBehaviour {
 
     public Animator playerAnimator;
     Transform cameraPos;
     CapsuleCollider col; //Collider
     Rigidbody phys; //Rigidbody
     float BaseHeight;//The default height of the character controller
     public float CrouchingHeight; //The height of the character controller while crouching
 
     public float CrawlSpeed = 1.0f;
     public float RunSpeed = 5.0f;
     public float SprintSpeed = 10.0f;
     float CurrentSpeed = 0.0f;
     bool Crouching  = false;
     bool Sprinting = false;
     bool CanSprint = true;
     bool Climbing = false;
     bool CanClimb = false;
     public float MaxStamina = 8.0f;
     public float CurrentStamina = 8.0f; //How long the player can sprint or climb
     public LayerMask ClimbingMask;
 
 
     //Jump variables
     public float MaxJumpHeight = 1.5f;
 
     //State variables
 
     public float GroundCheckDistance = 0.1f; //How close to the ground is the player to be considered grounded?
     public float WallCheckDistance = 0.3f; //How close to a wall can the player be to start climbing?
     bool Grounded ()
     {
         return Physics.Raycast (transform.position, -Vector3.up, GroundCheckDistance);
     }
     bool WallDetected ()
     {
         return Physics.Raycast (transform.position, transform.forward, WallCheckDistance, ClimbingMask);
     }
 
     //Stealth Elements
     public Transform SunLight, FeetAnchor, HeadAnchor;
     bool IsHidden;
 
 
     // Use this for initialization
     void Start () {
 
         cameraPos = Camera.main.transform;
         col = GetComponent<CapsuleCollider> ();
         phys = GetComponent<Rigidbody> ();
         BaseHeight = col.height;
         
     }
     
     // Update is called once per frame
     void Update () {
 
 
         //Set IsHidden
         if (Physics.Raycast (FeetAnchor.position, SunLight.forward * -1f, 100) && Physics.Raycast (HeadAnchor.position, SunLight.forward * -1f, 100)) {
             IsHidden = true;
             print ("Hidden");
         } else {
             IsHidden = false;
             print ("Visible");
         }
 
         //Movement
 
         ///Set Crouching
         if (Input.GetButtonDown ("Crouch")) {
             Crouching = !Crouching;
             playerAnimator.SetBool ("IsCrouching", Crouching);
         }
         if (Crouching) {
             col.height = CrouchingHeight;
         } else {
             col.height = BaseHeight;
         }
 
         ////////Set Sprinting
             if (Input.GetButton ("Sprint") && !Crouching) {
             if (CanSprint && phys.velocity != Vector3.zero) {
                 Sprinting = true;
                 CurrentStamina -= Time.deltaTime;
             }
             } else {
                 Sprinting = false;
             }
         if (CurrentStamina <= 0) {
             CanSprint = false;
             Sprinting = false;
         }
         if (CurrentStamina > 4) {
             CanSprint = true;
         }
         if (CurrentStamina >= MaxStamina) {
             CurrentStamina = MaxStamina;
         }
 
         if (!Sprinting) {
             CurrentStamina += Time.deltaTime * 0.7f;
         }
 
         float h = Input.GetAxis ("Horizontal");
         float v = Input.GetAxis ("Vertical");
         Vector3 movementDir = new Vector3 (h, 0f, v);
 
         movementDir = cameraPos.TransformDirection (movementDir);
 
         if (movementDir != Vector3.zero)
             transform.forward = new Vector3 (movementDir.x, 0f, movementDir.z);
 
         if (Grounded()) {
             //Movement
             if (!Crouching) {
                 if (!Sprinting)
                     CurrentSpeed = RunSpeed * movementDir.magnitude;
                 else
                     CurrentSpeed = SprintSpeed * movementDir.magnitude;
             } else {
                 CurrentSpeed = CrawlSpeed * movementDir.magnitude;
             }
             phys.velocity = new Vector3 (movementDir.x * CurrentSpeed, 0f, movementDir.z * CurrentSpeed);
 
             //Jumping
             if (Input.GetButtonDown ("Jump") && !Crouching) {
                 phys.AddForce (Vector3.up * MaxJumpHeight, ForceMode.Impulse);
             }
         }
 
         //Wall Detection (Grounded)
         if (Grounded ()) {
             if (Physics.Raycast (transform.position, transform.forward, WallCheckDistance)) {
                 CurrentSpeed = 0;
             }
         }
 
         //Climbing
         if (!Grounded () && WallDetected () && Input.GetButtonDown ("Sprint")) {
             Climbing = true;
             if (Input.GetButtonDown ("Jump") && Climbing) {
                 Climbing = false;
             }
         }
             
         playerAnimator.SetFloat ("GroundSpeed", CurrentSpeed);
         playerAnimator.SetBool ("Grounded", Grounded());
         playerAnimator.SetFloat ("AirSpeed", phys.velocity.y);
     }
         
 }
 


Any help is appreciated. Thanks in advance.

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

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by Eno-Khaon · Apr 25, 2017 at 07:56 PM

To address all major points (roughly) in order:

A) (player can stop and turn on a dime) Your movement is defined by forcibly defining your velocity every frame rather than by adding a force, and that movement is defined based on the current input. There's nothing to accelerate and decelerate aside from Input.GetAxis() easing in and out for the controls. If you want strict control over the character's movement, you'll probably want to directly control acceleration and maximum speed yourself by monitoring a 2D movement axis.

Incidentally, this also means you're winding up somewhat lucky right now -- If you weren't restricting controls to when Grounded only, you would be cancelling out vertical movement every frame.

B, C, and D) (walking uphill is slower than the regular walking speed) -- (walking downhill is very jittery) -- (player can stop and turn on a dime) This also fits in with the means of directing character input. As long as you know that your character is Grounded, you can observe the traits of the ground to know how to walk along it.

Problem D can also be covered here -- By using both axis inputs in full, you reach a maximum of √2 (square root of 2) speed, or approximately 1.4x your intended speed.

 Vector3 movementDir = new Vector3 (h, 0f, v);
 
 // Solve problem D by normalizing when necessary
 if(movementDir.sqrMagnitude > 1.0f)
 {
     movementDir = movementDir.normalized;
 }
 
 movementDir = cameraPos.TransformDirection (movementDir);
 
 // Locate the ground
 // distanceToFeet should be slightly longer distance (10% at most) than from the center of your character to the bottom of its collider
 if(grounded)
 {
     RaycastHit hit;
     if(Physics.Raycast(transform.position, Vector3.down, out hit, distanceToFeet))
     {
         // If the raycast hits, you now know the angle of the ground.
         Quaternion rotateToGround = Quaternion.FromToRotation(transform.up, hit.normal);
         // rotate your movement direction relative to the ground
         movementDir = rotateToGround * movementDir;
     }
 }

Why not normalize the initial movement vector all the time? If you're using analog control (e.g. a gamepad), for example, you'll still have the granularity such controls should offer.

E) (jumping is entirely momentum-based which is not very good for a platformer) Contrary to your current basis for jumping, If you want an absolute jumping force applied, without influence from current momentum, you actually WANT to apply this manually.

 movementDir.y = maxJumpHeight;
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

82 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 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 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 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 avatar image avatar image

Related Questions

Having trouble turning a Transform movement into a Rigidbody force. Code included 1 Answer

Rigidbody Controller Jittery 1 Answer

My Rigidbody FPS controller is falling very slow, please help! 2 Answers

Help with rigidbody character controller 0 Answers

Rigidbody character controller issues 0 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