• 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 Poytis · Mar 01, 2017 at 07:25 AM · c#unity 5monodevelopplayer movement

How do I stop jumping mid air?

I know I need to do something with "isGrounded" but i just don't know what to do Here is my code

 using UnityEngine;
 using System.Collections;
 
 public class Playermovement : MonoBehaviour
 {
 
     public Rigidbody rb;
 
     public float forwardForce = 200f;
 
     public float sidewaysForce = 250f;
 
     public float jumpHeight = 250f;
 
     public float rotationForce = 50f;

     void FixedUpdate()
     {
 
         rb.AddForce(0, 0, forwardForce * Time.deltaTime);
 
         if (Input.GetKey("d"))
         {
             rb.AddForce(sidewaysForce * Time.deltaTime, 0, 0);
 
             transform.Rotate(-Vector3.forward * rotationForce * Time.deltaTime);
         }
 
         if (Input.GetKey("a"))
         {
             rb.AddForce(-sidewaysForce * Time.deltaTime, 0, 0);
 
             transform.Rotate(-Vector3.back * rotationForce * Time.deltaTime);
         }
 
         if (Input.GetKeyDown("w"))
         {
             rb.AddForce(0, jumpHeight, 0);
         }
 
     }
    
 }
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 N1warhead · Mar 01, 2017 at 08:48 AM

I've encountered this before, so far the best way I've found to getting around it is to do this.

     // Not tested - but it's roughly if not exactly what I did in the past.
     // Use a timer inside Update, when the timer tops - the force stops and you drop down.
     // Only problem with doing it this way is each jump will ALWAYS be the same height.
     // But it should be easy to modify this to work any way you desire.
     float jumpTime = 2.5f;
     bool isGrounded;
     public Rigidbody rb;
     public float jumpHeight = 250f;
 
     void Update(){
         
         if (Input.GetKeyDown (KeyCode.W)) {
             isGrounded = false;    
         }
 
         if (!isGrounded) {
             jumpTime -= Time.deltaTime;
         }
 
     }
 
     void FixedUpdate(){
         if (!isGrounded && jumpTime > 0) {
             rb.AddForce (0, jumpHeight, 0);
         }
     }
 
     void OnCollisionEnter(Collision col){
         if (col.gameObject.tag == "Map") {
             jumpTime = 2.5f;
             isGrounded = true;
         }
     }

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
1

Answer by DragonGamingYT · Nov 05, 2017 at 10:17 PM

The easiest way i found was to set isGrounded false when jumping and set it true when touching the ground`using UnityEngine;

public class Jump : MonoBehaviour {

 [Range(1, 10)]
 public float jumpVelocity;

 private bool isGrounded;

 void Update()
 {
     if (Input.GetButtonDown("Jump") && isGrounded == true)
     {
         GetComponent<Rigidbody>().velocity = Vector3.up * jumpVelocity;
         isGrounded = false;
     }

 }

 void OnCollisionEnter()
 {
     isGrounded = true;
 }

} `

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 AidanHorton · Nov 06, 2017 at 11:45 AM 0
Share

This is the method that I would personally go with - this is the most lightweight implementation and it always works great for me. Here is a version with a few amendments:

 public float jumpVelocity;
 
 private bool isGrounded;
 private Rigidbody rb;
 
 void Start()
 {
     rb = GetComponent<Rigidbody>();
 }
 
  void Update()
  {
      if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.W) && isGrounded)
      {
          rb.velocity = Vector3.up * jumpVelocity;
          isGrounded = false;
      }
  }
  void OnCollisionEnter()
  {
      isGrounded = true;
  }
avatar image
0

Answer by BhargavChauhan · Mar 01, 2017 at 08:46 AM

First set your ground tag as a Ground Tag and make changes on your code below. This will prevent your player to mid air jump.

 using UnityEngine;
 using System.Collections;
 
 public class Playermovement : MonoBehaviour
 {
 
     public Rigidbody rb;
 
     public float forwardForce = 200f;
 
     public float sidewaysForce = 250f;
 
     public float jumpHeight = 250f;
 
     public float rotationForce = 50f;
 
     bool isGrounded;
 
     void FixedUpdate()
     {
 
         rb.AddForce(0, 0, forwardForce * Time.deltaTime);
 
         if (Input.GetKey("d"))
         {
             rb.AddForce(sidewaysForce * Time.deltaTime, 0, 0);
 
             transform.Rotate(-Vector3.forward * rotationForce * Time.deltaTime);
         }
 
         if (Input.GetKey("a"))
         {
             rb.AddForce(-sidewaysForce * Time.deltaTime, 0, 0);
 
             transform.Rotate(-Vector3.back * rotationForce * Time.deltaTime);
         }
 
         if (Input.GetKeyDown("w"))
         {
             if (isGrounded) {
                 rb.AddForce (0, jumpHeight, 0);
                 isGrounded = false;
             }
         }
 
     }
 
     void OnCollisionEnter(Collision other){
         if (other.gameObject.tag == "Ground") {
             isGrounded = true;
         }
     }
 }
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 N1warhead · Mar 01, 2017 at 09:05 AM 0
Share

But wouldn't making isGrounded false stop the force from working? Add Force is meant to gradually add force over a period of time, so you might get 0.005 meters off the ground before it's then false, which I would think would kill the force before ever getting high enough.

avatar image
0

Answer by Smart_Guy12 · Mar 01, 2017 at 02:01 PM

Create a bool:

bool isGrounded;
Then you will need to create a raycast hit,
RaycastHit hitInfo;
Then call a raycast inside of an if loop,
if (Physics.Raycast (transform.position, Vector3.down, out hitInfo, 0.2f)) {
     isGrounded = true;
} else {
     isGrounded = false;
} 
If the object is more than 0.2 units off the ground, then isGrounded will be set to false.

Comment
Add comment · Show 4 · 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 jp8173 · Mar 01, 2017 at 05:13 PM 0
Share

how may i use this in my code

using UnityEngine; using System.Collections;

public class Jump : $$anonymous$$onoBehaviour {

 public float jump;
  
   
 // Use this for initialization
 void Start()
 {
     
 }




 // Update is called once per frame
 void update()
 
   
         {
         if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space))
         {
             GetComponent<Rigidbody>().AddForce(new Vector3(0, jump, 0));
         }
     }
 

}

avatar image Smart_Guy12 jp8173 · Mar 05, 2017 at 06:06 PM 0
Share

You can use isGrounded as a condition for being able to jump,

if (isGrounded == true) {
     if (Input.Get$$anonymous$$eyDown ($$anonymous$$eycode.Space)) {
          GetComponent().AddForce(new Vector3(0, jump, 0)
          }
     }

avatar image jp8173 Smart_Guy12 · Mar 06, 2017 at 07:19 AM 0
Share

so id put the raycast call code in void update?

Show more comments
avatar image
0

Answer by jjcrawley · Mar 02, 2017 at 01:18 PM

There are several ways to handle this ability, and the path you take will ultimately come down to how your jump is designed.

First things first: be wary of OnCollisionEnter. The solution will work if your tags are setup properly, but would require additional tag filters if you had platforms tagged as the floor. If the tags weren't setup correctly you would hit your head on the platform, tagged as floor, and your jump would reset. Not what you're after.

One way to fix this problem is to use a physics raycast that aims downwards. If necessary, you could use an Overlap box instead, this may be better as you can then still jump if you're right on the edge of a platform. Have a peak at the API, https://docs.unity3d.com/ScriptReference/Physics.BoxCast.html There are a ton of detection functions to choose from.

These casts would be done in the downwards direction, Vector3.down and you can use a collision mask to filter the cast. Using a mask allows you to cull out certain physics layers using the casting function, rather than constantly checking for tags in OnCollisionEnter, although the messages would be filtered by the collision matrix anyway.

In terms of code, it would be something along the lines of:

     using UnityEngine;
     using System.Collections;
      
      public class Playermovement : MonoBehaviour
      {     
          public Rigidbody rb;
      
          public float forwardForce = 200f;
      
          public float sidewaysForce = 250f;
      
          public float jumpHeight = 250f;
      
          public float rotationForce = 50f;
     
     //private so you can't change it externally by accident, use a getter to see it.
          private bool isGrounded;
          void FixedUpdate()
          {
     //do checks first, so if you need it later, it's all done       
            Vector3 feetPos = transform.position + offset;                                               //offset is defined by you, this is just a safety check to ensure that the ray doesn't hit the player. You could avoid offset completely by using a layer mask, with the player being on its own layer.
 
             Ray myRay = new Ray(feetPos, Vector3.down);                                               //the origin and direction will differ depending on needs
 
     float maxDistance = 2;                             //just a guess, tweak as needs dictate
 
     int layerMask =  LayerMask.GetMask("Floor", "Any other jumpable things"); //The mask used will     depend on your project, also may want to cache on Awake so you're not constantly remaking it.              
     isGrounded = Physics.RayCast(myRay, maxDistance, layerMask);  //true if the raycast hits something, should be only 'ground' objects if the mask is setup correctly
     
     //check boxcast info if you'd rather use a box cast, similar principle just a few additional params
      
              rb.AddForce(0, 0, forwardForce * Time.deltaTime);
      
              if (Input.GetKey("d"))
              {
                  rb.AddForce(sidewaysForce * Time.deltaTime, 0, 0);
      
                  transform.Rotate(-Vector3.forward * rotationForce * Time.deltaTime);
              }
      
              if (Input.GetKey("a"))
              {
                  rb.AddForce(-sidewaysForce * Time.deltaTime, 0, 0);
      
                  transform.Rotate(-Vector3.back * rotationForce * Time.deltaTime);
              }                                                                                        
              
 bool movingUpwards = rb.velocity.y > 0; 
 
 //moving upwards can be used to prevent the player from hitting the jump button again if they just pressed it, as a force is applied the moment you press the button so if the velocity is > 0, then you're moving upwards.  This solution may not work with moving platforms, going up. You could use a timer coroutine instead, start the coroutine the moment you press the button and don't let it be pressed again until it finishes, have a 'finished jumping' flag, false when just pressed, true when finished and 'time till next press' variable, defines how long until next press. 
 
              if (Input.GetKeyDown("w") && isGrounded && !movingUpwards)
              {
                  rb.AddForce(0, jumpHeight, 0);
              }          
          }    
      }

One final thing before concluding, may may want to use the input checks in Update. Fixed update is called consistently, however, you want to detect the press immediately and, unless I'm mistaken, Unity updates the input stuff, in the Update loop. As a consequence you may miss the press in Fixed update.

Hopefully this will lead you in the right direction.

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.

Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.



Follow this Question

Answers Answers and Comments

13 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

Related Questions

How to let other object know i have enter a collider of a different object 1 Answer

C# script parse error 1 Answer

Cant get Monodevolop to work 0 Answers

Unity3d and monodevelop c# scripting on ubuntu 16.04 IntelliSense problems 0 Answers

Not able to make fps character controller player movement.,Not able to make Fps character controller player movement properly. 0 Answers

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges