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 TRON-dll · Jul 16, 2013 at 04:55 AM · c#movementjumpingcharacter.move

Midair movement with the character controller?

I'm working on a 3D platformer where the character needs to be able to move around and be capable of performing single and double jumps. I'm using the character controller and the example code on the CharacterController.Move page of the scripting reference. The problem inherent in this script is that the character cannot be controlled in midair. First, my current script, which is a modified version of the script shown on the CharacterController.Move page, changed to allow for double jumping, in its entirety:

 using UnityEngine;
 using System.Collections;
 
 public class PlayerMove : MonoBehaviour {
 
     public float speed = 6.0F;
     public float jumpSpeed = 8.0F;
     public float gravity = 20.0F;
     
     private Vector3 moveDirection = Vector3.zero;
     
     int maxJumps = 2;
     int currentJumps;
     
     void Start()
     {
         currentJumps = 0;
     }
     
     void Update()
     {
         CharacterController controller = GetComponent<CharacterController>();
         
         if (controller.isGrounded)
         {
             currentJumps = 0;
             
             moveDirection = new Vector3(Input.GetAxis("Horizontal"), moveDirection.y, Input.GetAxis("Vertical"));
             moveDirection = transform.TransformDirection(moveDirection);
             moveDirection *= speed;
             
             if (Input.GetButtonDown("Jump"))
             {
                 moveDirection.y = jumpSpeed;
                 currentJumps++;
             }
         }
         
         if (!controller.isGrounded)
         {    
             if (Input.GetButtonDown("Jump") && currentJumps < maxJumps)
             {
                 moveDirection.y = jumpSpeed;
                 currentJumps++;
             }
         }
         
         moveDirection.y -= gravity * Time.deltaTime;
         controller.Move(moveDirection * Time.deltaTime);
     }
 }

Now I want to be able to move the character around in midair, so I would think that taking these three lines:

 moveDirection = new Vector3(Input.GetAxis("Horizontal"), moveDirection.y, Input.GetAxis("Vertical"));
             moveDirection = transform.TransformDirection(moveDirection);
             moveDirection *= speed;

And moving them before the first if statement starts would work, but this causes jumping to behave incorrectly and causes the object to fall much slower. I get the same effect if those three lines are copied/pasted into the if (!controller.isGrounded) statement before the nested if statement for detecting the jump input.

Any help is appreciated. Javascript and C# are fine for answers.

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

5 Replies

· Add your reply
  • Sort: 
avatar image
3

Answer by scott95 · Oct 11, 2017 at 07:00 PM

I think i found a solution sorry if my code is a bit messy.

CharacterController controller = GetComponent(); if (controller.isGrounded) {

         moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
         moveDirection = transform.TransformDirection(moveDirection);
         moveDirection *= speed;

         //moveDirection.y = 0;

         //if (Input.GetButton("Jump"))

         if (Input.GetButtonDown("XboxA") || Input.GetKey(KeyCode.Space))
             moveDirection.y = jumpSpeed;
         //

 


     }else if (controller.isGrounded == false) // Here I independently allow for both X and Z movement. 
       
     {
         moveDirection.x = Input.GetAxis("Horizontal") * speed;
         moveDirection.z = Input.GetAxis("Vertical") * speed;

         moveDirection = transform.TransformDirection(moveDirection);// Then reassign the current transform to the Vector 3.
     }



Comment
Add comment · Show 1 · 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
avatar image Akselmo · Dec 28, 2017 at 12:22 AM 0
Share

This worked for me, many thanks!

avatar image
1

Answer by amphoterik · Jul 16, 2013 at 12:01 PM

I did something similar like this last night. Simply take the part that moves you along the x and z axis out of the grounding conditional:

 moveDirection = new Vector3(Input.GetAxis("Horizontal"), moveDirection.y, Input.GetAxis("Vertical"));
 moveDirection = transform.TransformDirection(moveDirection);
 moveDirection *= speed;
 if (controller.isGrounded)
 {
     currentJumps = 0;
  
     if (Input.GetButtonDown("Jump"))
     {
         moveDirection.y = jumpSpeed;
         currentJumps++;
     }
 }

That will do what you want. You may want to dampen the control while in the air so that they cannot move perfectly while on the ground.

Comment
Add comment · Show 7 · 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
avatar image TRON-dll · Jul 18, 2013 at 08:41 PM 0
Share

Yeah, I tried that. It causes some strange issue where gravity has a significantly lower effect on the character as it falls. Jumping also doesn't work correctly, the character just moves up however many units the jump height is set to, and then falls slowly. Any idea why this is happening?

In case it matters, here is my code:

 using UnityEngine;
 using System.Collections;
 
 public class Player$$anonymous$$ove : $$anonymous$$onoBehaviour
 {
     public float speed = 6.0F;
     public float jumpSpeed = 8.0F;
     public float gravity = 20.0F;
     public int maxJumps = 2;
     
     private Vector3 moveDirection = Vector3.zero;
     private float usedSpeed;
     private int jumps;
     
     void Start()
     {
         usedSpeed = speed;
         jumps = 0;
     }
     
     void Update()
     {
         CharacterController controller = GetComponent<CharacterController>();
         
         moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
         moveDirection = transform.TransformDirection(moveDirection);
         moveDirection *= usedSpeed;
         
         if (controller.isGrounded)
         {
             jumps = 0;
             
             usedSpeed = speed;
             
             if (Input.GetButtonDown("Jump"))
             {
                 moveDirection.y = jumpSpeed;
                 jumps++;
             }
         }
         
         if (!controller.isGrounded)
         {
             usedSpeed = speed * 0.5f;
             
             if (Input.GetButtonDown("Jump") && jumps < maxJumps)
             {
                 moveDirection.y = jumpSpeed;
                 jumps++;
             }
         }
         
         moveDirection.y -= gravity * Time.deltaTime;
         controller.$$anonymous$$ove(moveDirection * Time.deltaTime);
     }
 }
avatar image amphoterik · Jul 19, 2013 at 11:34 AM 0
Share

Here's your problem:

 moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));

Compare yours to $$anonymous$$e.

avatar image TRON-dll · Jul 19, 2013 at 05:34 PM 0
Share

Tried that. The capsule seems to fall properly, but freaks out whenever it hits something. Tried both a flat terrain and a cube mesh and got the following error in both cases:

transform.position assign attempt for 'Capsule' is not valid. Input position is { NaN, -Infinity, NaN }.

I'm starting my player object in midair, as well.

avatar image amphoterik · Jul 19, 2013 at 05:45 PM 0
Share

can I see your code now?

avatar image TRON-dll · Jul 19, 2013 at 05:51 PM 0
Share

Yeah, here's the section I changed. If you want I can post the whole thing, but the rest of it is the same:

 void Update()
     {
         CharacterController controller = GetComponent<CharacterController>();
         
         moveDirection = new Vector3(Input.GetAxis("Horizontal"), moveDirection.y, Input.GetAxis("Vertical"));
         moveDirection = transform.TransformDirection(moveDirection);
         moveDirection *= usedSpeed;
         
         if (controller.isGrounded)
Show more comments
avatar image
0

Answer by SmileyMerx · Jan 28, 2015 at 11:41 AM

I had some problems and none of your solutions worked, so here is my solution. It is really easy and allows mid-air movement left/right. If you also want to turn around, or forward, backward. Just add it in the suitable location:

using UnityEngine; using System.Collections;

public class MovementWorm3 : MonoBehaviour {

 float speed     = 6.0f;
 float jumpSpeed = 8.0f;
 float gravity   = 20.0f;

 private Vector3 moveDirection = Vector3.zero;
 private CharacterController controller;

 // Use this for initialization
 void Start () {
     controller = GetComponent<CharacterController>();    
 }
 
 // Update is called once per frame
 void Update () {
         
     if (controller.isGrounded) {
         // We are grounded, so recalculate
         // move direction directly from axes        
         moveDirection = new Vector3(Input.GetAxis ("Horizontal"), 0, 0);
         moveDirection = transform.TransformDirection(moveDirection);
         moveDirection = moveDirection * speed;

         if (Input.GetButton ("Jump")) {
             moveDirection.y = jumpSpeed;
         }
     }
     else {
         // Apply right/left, if we are NOT grounded
         // --> Left/Right movement in mid air allowed
         moveDirection.x = Input.GetAxis ("Horizontal") * speed;
     }

     // Apply gravity
     moveDirection.y -= gravity * Time.deltaTime;
     
     // Move the controller
     controller.Move(moveDirection * Time.deltaTime);
 }

}

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

Answer by GameDev_Chuck · Jul 30, 2016 at 04:46 PM

     if(grounded)
     {
     //grounded controls
     }
     else  //in air controls
     {
                     /* this works but doesnt clamp horizontal velocity:
                     Vector3 inputVector = new Vector3(Input.GetAxis("Horizontal"), 0, verticalInput);
                     inputVector = transform.TransformDirection(inputVector);
                     moveDirection = controller.velocity + (inputVector * Time.deltaTime * airSpeed);
                     */
     
                 Vector3 inputVector = new Vector3(horizontalInput, 0, verticalInput);
                 inputVector = transform.TransformDirection(inputVector);
                 Vector2 clampedHorizontalVelocity = Vector2.ClampMagnitude(new Vector2(controller.velocity.x, controller.velocity.z), runSpeed);
                 moveDirection = new Vector3(clampedHorizontalVelocity.x, controller.velocity.y, clampedHorizontalVelocity.y)  + (inputVector * Time.deltaTime * airSpeed);
 }



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

Answer by iuripujol · Jun 20, 2018 at 05:38 PM

Guys take it easy...

         float v = Input.GetAxis ("Vertical");
         float h = Input.GetAxis ("Horizontal");
         float Angle = Mathf.Atan2 (h,v) * Mathf.Rad2Deg;
         Vector3 m = transform.forward * new Vector3 (h, 0, v).magnitude;

         transform.eulerAngles = new Vector3 (0, cam.eulerAngles.y + Angle, 0);

         if (cc.isGrounded) {
             move = m ;
             move *= Input.GetKey (KeyCode.LeftShift) ? 1 : .5f;

             if (Input.GetKey (KeyCode.Space))
                 move.y = JumpSpeed;
         } else {
             move = new Vector3(m.x, move.y, m.z);
         }

         move.y -= 3 * Time.deltaTime;
         
         cc.Move (move * MoveSpeed * Time.deltaTime);
Comment
Add comment · Show 1 · 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
avatar image iuripujol · Jun 20, 2018 at 06:18 PM 0
Share

Final solution:

float v = Input.GetAxis ("Vertical"); float h = Input.GetAxis ("Horizontal");

Vector3 m = Quaternion.Euler(0, cam.eulerAngles.y, 0) * new Vector3 (h, 0, v);//move direction

Vector3 dir = transform.InverseTransformDirection (m); float Turn = $$anonymous$$athf.Atan2 (dir.x, dir.z); transform.Rotate (0, Turn * 20, 0);//handle rotation

if (cc.isGrounded) { move = m.normalized; move *= Input.Get$$anonymous$$ey ($$anonymous$$eyCode.LeftShift) ? 1 : .5f;

if (Input.Get$$anonymous$$ey ($$anonymous$$eyCode.Space)) move.y = JumpSpeed; } else { move = new Vector3(m.x, move.y, m.z); }

move.y -= 3 * Time.deltaTime;//gravity

cc.$$anonymous$$ove (move $$anonymous$$oveSpeed Time.deltaTime);

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

22 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

Related Questions

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

Cant Jump ?c# please 2 Answers

MidAir Strafing 0 Answers

Player Jumps instead of moving forward 0 Answers

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