Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 11 Next capture
2021 2022 2023
1 capture
11 Jun 22 - 11 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 Joewater · Jul 13, 2015 at 01:19 AM · c#movementraycastcharactercharactercontroller

Changing the landing and switch directions of standard assets TPC controller

I can't seem to figure out how to change the landing and switching directions behavior of standard assets third person character script.

At the moment when you land after jumping the controller stops moving briefly as if you have fallen a great distance. When using free look cam, you strafe to the right then switch directions to the left it is too slow of a change as it briefly slows right down.

I want to change it to when you land you continue moving without stopping. Also speed up the time it takes to switch directions.

I'm sure there's something simple to change that I am missing, any help would be great. :)

(I'm using the 4.6 version as it has a head look function, but they both behave the same way when landing.)

 using UnityEngine;
 using System.Collections;
 
 public class ThirdPersonCharacter : MonoBehaviour {
     
     [SerializeField] public PhysicMaterial theZFMat;
     [SerializeField] public PhysicMaterial theHFMat;
     
     [SerializeField] public float jumpPower = 8;                        // determines the jump force applied when jumping (and therefore the jump height)
     [SerializeField] float airSpeed = 6;                                // determines the max speed of the character while airborne
     [SerializeField] float airControl = 2;                                // determines the response speed of controlling the character while airborne
     [Range(1,4)] [SerializeField] public float gravityMultiplier = 2;    // gravity modifier - often higher than natural gravity feels right for game characters
     [SerializeField][Range(0.1f,3f)] float moveSpeedMultiplier = 1;        // how much the move speed of the character will be multiplied by
     [SerializeField][Range(0.1f,3f)] float animSpeedMultiplier = 1;        // how much the animation of the character will be multiplied by
     [SerializeField] AdvancedSettings advancedSettings;                 // Container for the advanced settings class , thiss allows the advanced settings to be in a foldout in the inspector
 
 
     [System.Serializable]
     public class AdvancedSettings
     {
         public float stationaryTurnSpeed = 500;                // additional turn speed added when the player is stationary (added to animation root rotation)
         public float movingTurnSpeed = 1200;                    // additional turn speed added when the player is moving (added to animation root rotation)
         public float headLookResponseSpeed = 2;                // speed at which head look follows its target
         public float crouchHeightFactor = 0.5f;             // collider height is multiplied by this when crouching
         public float crouchChangeSpeed = 4;                    // speed at which capsule changes height when crouching/standing
         public float autoTurnThresholdAngle = 100;            // character auto turns towards camera direction if facing away by more than this angle
         public float autoTurnSpeed = 4;                        // speed at which character auto-turns towards cam direction
         public PhysicMaterial zeroFrictionMaterial;            // used when in motion to enable smooth movement
         public PhysicMaterial highFrictionMaterial;            // used when stationary to avoid sliding down slopes
         public float jumpRepeatDelayTime = 0.25f;            // amount of time that must elapse between landing and being able to jump again
         public float runCycleLegOffset = 0.2f;                // animation cycle offset (0-1) used for determining correct leg to jump off
         public float groundStickyEffect = 5f;                // power of 'stick to ground' effect - prevents bumping down slopes.
     }
 
     public Transform lookTarget { get; set; }               // The point where the character will be looking at
 
     bool onGround;                                          // Is the character on the ground
     Vector3 currentLookPos;                                 // The current position where the character is looking
     float originalHeight;                                   // Used for tracking the original height of the characters capsule collider
     Animator animator;                                      // The animator for the character
     float lastAirTime;                                      // USed for checking when the character was last in the air for controlling jumps
     CapsuleCollider capsule;                                // The collider for the character
     const float half = 0.5f;                                // whats it says, it's a constant for a half
     Vector3 moveInput;
     bool crouchInput;
     bool jumpInput;
     float turnAmount;
     float forwardAmount;
     Vector3 velocity;
     IComparer rayHitComparer;
 
     // Use this for initialization
     void Start () {
         advancedSettings.highFrictionMaterial = theHFMat;
         advancedSettings.zeroFrictionMaterial = theZFMat;
         animator = GetComponentInChildren<Animator>();
         capsule = GetComponent<Collider>() as CapsuleCollider;
 
         // as can return null so we need to make sure thats its not before assigning to it
         if (capsule != null) {
             originalHeight = capsule.height;
             capsule.center = Vector3.up * originalHeight * half;
         } else {
             Debug.LogError(" collider cannot be cast to CapsuleCollider");
         }
 
         rayHitComparer = new RayHitComparer ();
 
         SetUpAnimator();
     }
     
     
     // The Move function is designed to be called from a separate component
     // based on User input, or an AI control script
     public void Move (Vector3 move, bool crouch, bool jump, Vector3 lookPos) {
 
         if (move.magnitude > 1) move.Normalize();
 
         // transfer input parameters to member variables.
         this.moveInput = move;
         this.crouchInput = crouch;
         this.jumpInput = jump;
         this.currentLookPos = lookPos;
 
         // grab current velocity, we will be changing it.
         velocity = GetComponent<Rigidbody>().velocity;
 
         ConvertMoveInput (); // converts the relative move vector into local turn & fwd values
         
         TurnTowardsCameraForward (); // makes the character face the way the camera is looking
 
         PreventStandingInLowHeadroom (); // so the character's head doesn't penetrate a low ceiling
 
         ScaleCapsuleForCrouching (); // so you can fit under low areas when crouching
 
         ApplyExtraTurnRotation(); // this is in addition to root rotation in the animations
         
         GroundCheck (); // detect and stick to ground
 
         SetFriction (); // use low or high friction values depending on the current state
 
         // control and velocity handling is different when grounded and airborne:
         if (onGround) {
             HandleGroundedVelocities();
         } else {
             HandleAirborneVelocities();
         }
     
         UpdateAnimator (); // send input and other state parameters to the animator
 
         // reassign velocity, since it will have been modified by the above functions.
         GetComponent<Rigidbody>().velocity = velocity;    
 
 
     }
 
     void ConvertMoveInput ()
     {
         // convert the world relative moveInput vector into a local-relative
         // turn amount and forward amount required to head in the desired
         // direction. 
         Vector3 localMove = transform.InverseTransformDirection (moveInput);
         turnAmount = Mathf.Atan2 (localMove.x, localMove.z);
         forwardAmount = localMove.z;
     }
 
     void TurnTowardsCameraForward ()
     {
         // automatically turn to face camera direction,
         // when not moving, and beyond the specified angle threshold
         if (Mathf.Abs (forwardAmount) < .01f) {
             Vector3 lookDelta = transform.InverseTransformDirection (currentLookPos - transform.position);
             float lookAngle = Mathf.Atan2 (lookDelta.x, lookDelta.z) * Mathf.Rad2Deg;
 
             // are we beyond the threshold of where need to turn to face the camera?
             if (Mathf.Abs (lookAngle) > advancedSettings.autoTurnThresholdAngle) {
                 turnAmount += lookAngle * advancedSettings.autoTurnSpeed * .001f;
             }
         }
     }
 
     void PreventStandingInLowHeadroom ()
     {
         // prevent standing up in crouch-only zones
         if (!crouchInput) {
             Ray crouchRay = new Ray (GetComponent<Rigidbody>().position + Vector3.up * capsule.radius * half, Vector3.up);
             float crouchRayLength = originalHeight - capsule.radius * half;
             if (Physics.SphereCast (crouchRay, capsule.radius * half, crouchRayLength)) {
                 crouchInput = true;
             }
         }
     }    
 
     void ScaleCapsuleForCrouching ()
     {
         // scale the capsule collider according to
         // if crouching ...
         if (onGround && crouchInput && (capsule.height != originalHeight * advancedSettings.crouchHeightFactor)) {
             capsule.height = Mathf.MoveTowards (capsule.height, originalHeight * advancedSettings.crouchHeightFactor, Time.deltaTime * 4);
             capsule.center = Vector3.MoveTowards (capsule.center, Vector3.up * originalHeight * advancedSettings.crouchHeightFactor * half, Time.deltaTime * 2);
         }
         // ... everything else 
         else
             if (capsule.height != originalHeight && capsule.center != Vector3.up * originalHeight * half) {
                 capsule.height = Mathf.MoveTowards (capsule.height, originalHeight, Time.deltaTime * 4);
                 capsule.center = Vector3.MoveTowards (capsule.center, Vector3.up * originalHeight * half, Time.deltaTime * 2);
             }
     }
 
     void ApplyExtraTurnRotation ()
     {
         // help the character turn faster (this is in addition to root rotation in the animation)
         float turnSpeed = Mathf.Lerp (advancedSettings.stationaryTurnSpeed, advancedSettings.movingTurnSpeed, forwardAmount);
         transform.Rotate (0, turnAmount * turnSpeed * Time.deltaTime, 0);
     }
 
     void GroundCheck ()
     {
         Ray ray = new Ray (transform.position + Vector3.up * .1f, -Vector3.up);
         RaycastHit[] hits = Physics.RaycastAll (ray, .5f); //5
         System.Array.Sort (hits, rayHitComparer);
         
         if (velocity.y < jumpPower * .5f) { //5
             onGround = false;
             GetComponent<Rigidbody>().useGravity = true;
             foreach (var hit in hits) {
                 // check whether we hit a non-trigger collider (and not the character itself)
                 if (!hit.collider.isTrigger) {
                     // this counts as being on ground.
 
                     // stick to surface - helps character stick to ground - specially when running down slopes
                     if (velocity.y <= 0) {
                         GetComponent<Rigidbody>().position = Vector3.MoveTowards (GetComponent<Rigidbody>().position, hit.point, Time.deltaTime * advancedSettings.groundStickyEffect);
                     }
 
                     onGround = true;
                     GetComponent<Rigidbody>().useGravity = false;
                     break;
                 }
             }
         }
 
         // remember when we were last in air, for jump delay
         if (!onGround) lastAirTime = Time.time;
 
     }
 
     void SetFriction()
     {
 
         if (onGround) {
 
             // set friction to low or high, depending on if we're moving
             if (moveInput.magnitude == 0) {
                 // when not moving this helps prevent sliding on slopes:
                 GetComponent<Collider>().material = advancedSettings.highFrictionMaterial;
             } else {
                 // but when moving, we want no friction:
                 GetComponent<Collider>().material = advancedSettings.zeroFrictionMaterial; //advancedSettings.
             }
         } else {
             // while in air, we want no friction against surfaces (walls, ceilings, etc)
             GetComponent<Collider>().material = advancedSettings.zeroFrictionMaterial;
         }
     }
 
     void HandleGroundedVelocities()
     {
 
         velocity.y = 0;
 
         if (moveInput.magnitude == 0) {
             // when not moving this prevents sliding on slopes:
             velocity.x = 0;
             velocity.z = 0;
         }
         // check whether conditions are right to allow a jump:
         bool animationGrounded = animator.GetCurrentAnimatorStateInfo (0).IsName ("Grounded");
         bool okToRepeatJump = Time.time > lastAirTime + advancedSettings.jumpRepeatDelayTime;
         
         if (jumpInput && !crouchInput && okToRepeatJump && animationGrounded) {
             // jump!
             onGround = false;
             velocity = moveInput * airSpeed;
             velocity.y = jumpPower;
         }
     }
 
     void HandleAirborneVelocities ()
     {
         // we allow some movement in air, but it's very different to when on ground
         // (typically allowing a small change in trajectory)
         Vector3 airMove = new Vector3 (moveInput.x * airSpeed, velocity.y, moveInput.z * airSpeed);
         velocity = Vector3.Lerp (velocity, airMove, Time.deltaTime * airControl);
         GetComponent<Rigidbody>().useGravity = true;
 
         // apply extra gravity from multiplier:
         Vector3 extraGravityForce = (Physics.gravity * gravityMultiplier) - Physics.gravity;
         GetComponent<Rigidbody>().AddForce(extraGravityForce);
 
     }
 
     void UpdateAnimator ()
     {
         // Here we tell the animator what to do based on the current states and inputs.
 
         // only use root motion when on ground:
         animator.applyRootMotion = onGround;
 
         // update the animator parameters
         animator.SetFloat ("Forward", forwardAmount, 0.1f, Time.deltaTime);
         animator.SetFloat ("Turn", turnAmount, 0.1f, Time.deltaTime);
         animator.SetBool ("Crouch", crouchInput);
         animator.SetBool ("OnGround", onGround);
         if (!onGround) {
             animator.SetFloat ("Jump", velocity.y);
         }
 
         // calculate which leg is behind, so as to leave that leg trailing in the jump animation
         // (This code is reliant on the specific run cycle offset in our animations,
         // and assumes one leg passes the other at the normalized clip times of 0.0 and 0.5)
         float runCycle = Mathf.Repeat (animator.GetCurrentAnimatorStateInfo (0).normalizedTime + advancedSettings.runCycleLegOffset, 1);
         float jumpLeg = (runCycle < half ? 1 : -1) * forwardAmount;
         if (onGround) {
             animator.SetFloat ("JumpLeg", jumpLeg);
         }
 
         // the anim speed multiplier allows the overall speed of walking/running to be tweaked in the inspector,
         // which affects the movement speed because of the root motion.
         if (onGround && moveInput.magnitude > 0) {
             animator.speed = animSpeedMultiplier;
         } else {
             // but we don't want to use that while airborne
             animator.speed = 1;
         }
     }
 
     
 
     void OnAnimatorIK(int layerIndex)
     {
         // we set the weight so most of the look-turn is done with the head, not the body.
         animator.SetLookAtWeight(1, 0.2f, 2.5f);
         
         // if a transform is assigned as a look target, it overrides the vector lookPos value
         if (lookTarget != null) {
             currentLookPos = lookTarget.position;
         }
 
         // Used for the head look feature.
         animator.SetLookAtPosition( currentLookPos );
     }
     
     
     
     void SetUpAnimator()
     {
         // this is a ref to the animator component on the root.
         animator = GetComponent<Animator>();
         
         // we use avatar from a child animator component if present
         // (this is to enable easy swapping of the character model as a child node)
         foreach (var childAnimator in GetComponentsInChildren<Animator>()) {
             if (childAnimator != animator) {
                 animator.avatar = childAnimator.avatar;
                 Destroy (childAnimator);
                 break;
             }
         }
     }
     
     public void OnAnimatorMove()
     {
         // we implement this function to override the default root motion.
         // this allows us to modify the positional speed before it's applied.
         GetComponent<Rigidbody>().rotation = animator.rootRotation;
         if (onGround && Time.deltaTime > 0) {
             Vector3 v = (animator.deltaPosition * moveSpeedMultiplier) / Time.deltaTime;
 
             // we preserve the existing y part of the current velocity.
             v.y = GetComponent<Rigidbody>().velocity.y;
             GetComponent<Rigidbody>().velocity = v;
         }
     }
     
 
     //used for comparing distances
     class RayHitComparer: IComparer
     {
         public int Compare(object x, object y)
         {
             return ((RaycastHit)x).distance.CompareTo(((RaycastHit)y).distance);
         }    
     }
 }
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

2 People are following this question.

avatar image avatar image

Related Questions

[C#]CharacterController Turning 2 Answers

[C#] Movement Direction Change 2 Answers

Making a bubble level (not a game but work tool) 1 Answer

[C#] Jump on slopes 1 Answer

The controller.move does not work correctly 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