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 artimusp · May 19, 2013 at 03:07 PM · velocitygravityjumping

Trying to limit air velocity

I've been having a lot of trouble figuring out how to limit horizontal air velocity. For example, when I'm grounded I can do.

 if(IsGrounded() && !_isJumping)
 {        
     _velocity = _rigidBody.velocity;
             
     _velocity += _groundVelocity;

     // Limit velocity to my run speed
     if(_velocity.magnitude > runSpeed)
     {
         _velocity.Normalize();
         _velocity *= runSpeed;
     }
             
     _rigidBody.velocity = _velocity;
 }

But when I'm jumping I have gravity to worry about. so I can't limit my horizontal velocity without messing with my vertical velocity. I'm not great at math and really don't know too much about vector math. My gravity is attracting towards a sphere like planet gravity so my up and forward vectors always change which makes it even harder for me to visualize what I need to do.

I'm using the standard jump velocity formula

 Mathf.Sqrt(-gravity * targetJumpHeight * 2);

So this is what I have so far (this is in FixedUpdate() ):

 // Apply velocity changes
 if(IsGrounded() && !_isJumping)
 {        
     // Not sure if this should be here
     // but everything seems to work.
     _velocity = _rigidBody.velocity;
             
     _velocity += _groundVelocity;
             
     // Limit velocity to run speed
     if(_velocity.magnitude > runSpeed)
     {
         _velocity.Normalize();
         _velocity *= runSpeed;
     }

     // I know people say don't change this directly, but I'm looking for
     // pretty instant move speed and this does what I need.  I am open to
     // suggestions :)
     _rigidBody.velocity = _velocity;
 }
 else // Air control
 {        

     // If I add _velocity = _rigidbody.velocity here
     // and then do _velocity += _airVelocity then when I try to limit
     // my velocity to the run speed it slows down the gravity
     // since I'm normalizing it and multiplying by the run speed.  Gravity needs
     // to be faster than the run speed over time.
     _velocity = _airVelocity;
             
     if(_velocity.magnitude > airSpeed)
     {
         _velocity.Normalize();
         _velocity *= airSpeed;
     }

    // this just keeps adding velocity (obviously :) ) 
    // which makes the player go extremely fast
    // How do I make the horizontal movement velocity be limited
    // by the run speed but allow gravity to keep it's previous
    // values and continue to work as needed.
     _velocity += _rigidBody.velocity;
             
     _rigidBody.velocity = _velocity;
 }
 
 // Add Jump velocity after movement velocity
 if(_isJumping && !_hasJumped)
 {
     // This gets me the right jump velocity but then I 
     // screw it up next frame when I try and limit
     // the horizontal air velocity
     _rigidBody.velocity = _velocity + _jumpVelocity;
     _hasJumped = true;
 }
 
 // Call Attractor update
 gravityAttractor.Attract(_transform, _rigidBody);
 
 // Clear our velocities so we can recalculate next frame
 _velocity = _groundVelocity = _airVelocity = Vector3.zero;

I'm more of a hobbyist programmer and don't really have all the concepts down so any help is greatly appreciated :)

Thanks,

Artie

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

2 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by robertbu · May 19, 2013 at 03:31 PM

Just take the 'Y' out and put it back. Conceptually:

 var v3 = rigidbody.velocity;
 v3.y = 0;
 
 if (v3.magnitude > airSpeed)
   v3 = v3.normalized * airSpeed;
 
 v3.y = rigidbody.velocity.y;
 rigidbody.velocity = v3;

I'm assuming you are using a rigidbody somewhere, but if not, the concept is the same. Zero out the 'Y' component, do you limiting calculation, put 'Y' back.

Comment
Add comment · Show 3 · 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 artimusp · May 19, 2013 at 04:11 PM 0
Share

Wouldn't that only work if the up direction was always the world Vector3.up?

I'm using Faux Gravity so gravity is based on the normal of my sphere or surface normal of whichever surface I want.

Is there a way do do this same concept but account for the current gravity direction?

Thanks,

avatar image robertbu · May 19, 2013 at 11:18 PM 0
Share

Interesting. I misses the sphere/gravtiy, and it was the whole point of your question. $$anonymous$$y vector math is self taught and I don't have the grounding it I like. So I think you can do it this way. Project the velocity onto the normal to the surface of the sphere at the current point. Subtract that from the velocity. Limit the resulting vector and then add the up velocity back in. Something like:

 // v3WorldUp - sphere normal at the current position
 // velocity - current velocity
 
     var v3UpVelocity = Vector3.Project(velocity, v3WorldUp);
     var v3T = velocity - v3UpVelocity;
     if (v3T.magnitude > airSpeed)
       v3T = v3T.normalized * airSpeed;
     velocity = v3T + v3UpVelocity;
avatar image artimusp · May 20, 2013 at 12:12 AM 0
Share

This seems to be working great. Thank you so much! Someday I'll start catching on to these cool little tricks. (starting today :) )

avatar image
0

Answer by Owen-Reynolds · May 19, 2013 at 05:56 PM

The standard math trick is to convert to local coords, do the work, then convert back. Visually local coords are a spaceman standing with the fake gravity planet below her feet, at -Y, and whichever way she happens to be looking is +Z. Aim one finger away from the grav source, and the other in your speed. Then spin so your "away" finger is pointing up. That spin is toUpSpin below. After, the "speed" finger is your local velocity for how the spaceman is standing.

Something like (this type of math works, but exact math here untested):

 Vector3 upFromGravSource = (trans.pos - grav.pos).normalized;
 Quaternion toUpSpin = Quaternion.rotateTowards(upFromGravSource, Vector3.up);
 Vector3 localVel = toUpSpin * rigidbody.velocity;

 // test toUpSpin is correct. Should put cube "up" from fake grav source:
 someCube.position = trans.pos + toUpSpin*Vector3.up*5;

If that works, localVel.y is now away from the fake gravity source. x and z will be correct, but on sort of a "random" x and z axis flat to y (but not a problem.)

After the math, turn that back into the real (world) velocity with:

 worldVel = Quaternion.Inverse(upFromGravSrc)*localVel;
Comment
Add comment · Show 5 · 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 artimusp · May 19, 2013 at 06:17 PM 0
Share

Looks like it might work. However Quaternion.Inverse doesn't take a vector it takes a Quaternion. I'm guessing that upFromGravSrc is supposed to be the Vector3 from above?

Thanks

avatar image Owen-Reynolds · May 19, 2013 at 08:09 PM 0
Share

Ah...should be toUpSpin. Velocity gets rotated by toUpSpin, then rotated back by the opposite, which is Inverse(toUpSpin).

avatar image artimusp · May 20, 2013 at 12:14 AM 0
Share

This seemed to be close, the inverse was was flipping the left and right and I didn't quite get how to switch that back. $$anonymous$$aybe I was doing something wrong. Robertbu's solution seems to be working as I am intending. Thanks for your help. Also, It's good to think about things in local coordinates and convert them back, I never thought of that before. Thanks!

-Artie

avatar image Owen-Reynolds · May 20, 2013 at 02:16 AM 0
Share

$$anonymous$$athematically, Robertu's code does the same thing -- decomposes into a Y and a left-over X/Z.

Local coordinates are easier when you have a target transform aimed the correct way. But then most problems like this are mostly a matter of visualizing them.

avatar image artimusp · May 20, 2013 at 04:39 AM 0
Share

Yeah, they seemed very similar.

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

14 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

Related Questions

Anti-Gravity isn't working 1 Answer

Jumping a specific height using Velocity & Gravity 1 Answer

Gravity trouble: Falling slow, jumping fast 1 Answer

Why does Gravity (Physics2D) produce different results for AddForce() versus velocity in player sprite? 2 Answers

In-Air Movement for Custom Controller? 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