• 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
2
Question by amirabiri · Sep 03, 2011 at 01:17 PM · physicsouterspace

AddForce and Maximum Speed

I'm trying to build an asteroids clone so the player ship can turn regardless of its moving direction. When the player moves forward I want to apply force to the ship, so the perceived effect is like flying in space.

My code right now is:

 rigidbody.AddRelativeForce(Input.GetAxis("Vertical") *  Vector3.forward * Time.deltaTime);

Generally it works correctly except for one thing, I'd like the ship to have some top speed. If a ship is moving in a given direction, beyond a certain point the force from its afterburner can't move it any faster, right?

At the moment the code above means that the ship can accelerate infinitely. I can't use drag because this is movement in space. If the player doesn't press any key the ship should continue drifting at its current velocity.

Am I misunderstanding the physics involved? Should I be using a different method? Or is the only solution coding myself the mitigation of the applied force?

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

6 Replies

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

Answer by amirabiri · Oct 11, 2012 at 06:16 AM

So far there isn't a really good solution to this issue. My particular solution is:

 if (Input.GetButton("Vertical"))
     rigidbody.AddRelativeForce(Vector3.forward * acceleration * Time.deltaTime);
 
 if (rigidbody.velocity.magnitude > topSpeed)
     rigidbody.velocity = rigidbody.velocity.normalized * topSpeed;

However there are shortcomings to this approach so if anyone has a better solution please post it (remember the context is a ship in outer space).

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
2

Answer by Judgeking · Nov 20, 2017 at 04:02 AM

Best solution I found gave me this, works perfectly:

     public float moveSpeed, maxSpeed;
     private Rigidbody rb;
     private Vector3 input;
 
     void Start () {
         rb = GetComponent<Rigidbody>();
     }
 
     void FixedUpdate () {
         input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
         rb.drag = (moveSpeed / maxSpeed);
         rb.AddForce(input * moveSpeed);
     }
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 DayyanSisson · Sep 03, 2011 at 05:04 PM

I was given this script for my question somewhat like this:

     var Speed : float = 50.0;
     var maxSpeed : float = 100.0; 
     var minSpeed : float = 10.0; 
     var maxAcceleration : float = 30.0;
     var currentSpeed : float = 50.0;
      
     function Update() 
     {
    transform.Translate(Vector3.forward * Time.deltaTime * currentSpeed);
     
  if(Input.GetKey("up"))
      currentSpeed += maxAcceleration * Time.deltaTime;
  else if(Input.GetKey("down"))
      currentSpeed-=maxAcceleration * Time.deltaTime;
  else if (currentSpeed > Speed){
     currentSpeed = currentSpeed;
         }
  else if (currentSpeed < Speed){
     currentSpeed = currentSpeed;
         }
   else {
      currentSpeed += maxAcceleration * Time.deltaTime;
      currentSpeed = Mathf.Clamp(currentSpeed, minSpeed, Speed);
         }
      currentSpeed = Mathf.Clamp(currentSpeed, minSpeed, maxSpeed);
 }


There you go. I hope this helps.

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 amirabiri · Sep 04, 2011 at 03:29 PM 1
Share

Thanks for the answer. Unfortunately this isn't based on AddForce. I'm trying to move a ship in space using the physics engine, and the ship could be facing a different direction than it is travelling at.

avatar image gevarre · Dec 02, 2011 at 03:51 AM 0
Share

Hmm, I think your code has become a bit jumbled. It seems to mostly work, but I get this in the console:

Assets/Scripts/JavaScripts/Rig_Control.js(60,18): BCW0020: WARNING: Assignment made to same expression. Did you mean to assign to something else?

Looking at the code, you have things like "currentSpeed = currentSpeed", which is what it is complaining about, but you also have the if statements set up so that if currentSpeed is either less than or greater than Speed then it equals itself. doesn't that negate itself?

Perhaps it's just some of the variables that are mixed up?

avatar image DayyanSisson · Dec 03, 2011 at 06:38 AM 0
Share

They aren't mixed up, I just wrote it inproperly. I forget the exact method, but what you can do is put a variable called currentSpeedD in update and then write :

 currentSpeedD = currentSpeed;

Then, on that line of code, write :

 else if (currentSpeed < Speed){
     currentSpeed = currentSpeedD;
         }

It would work the same, and there would be no error. There's a more efficient way, but I switched to C# since then, so I forget. But this way works too.

avatar image
1

Answer by Jonatan Crafoord · Oct 11, 2012 at 09:01 AM

Hi again,

I see the problem with using drag in space... :-p But if that is the case, maybe you can just limit the amount of acceleration you add until it is zero at top speed? For example:

 var accelerationMultiplier = 1 - (rigidbody.velocity.magnitude / topSpeed);
 
 if (Input.GetButton("Vertical"))
     rigidbody.AddRelativeForce(Vector3.forward * acceleration * accelerationMultiplier * Time.deltaTime);

The multiplier goes from 1 (no speed, 100% acceleration) to 0 (top speed, 0% acceleration) If you want the multiplier to be less pronounced, you can use its square root. That way will still go from 1 to 0, but will make a curve instead of a line.

EDIT: So, this leads to severe issues if we change the directional Vector. We also need the multiplier to take into account if you're trying to go in a different direction from your velocity vector.

 // Your normalized thrust vector (the direction you want to go)
 var direction : Vector3; 
 
 // Sum up your normalized direction with the normalized velocity vector and
 // divide by 2 to get a new vector with magnitude 0-1
 var sumVector : Vector3 = 0.5 * (direction + rigidbody.velocity.normalized);
 
 // Make a multiplier that goes from 0 (aligned vectors) to 1 (inversed vectors)
 var directionMultiplier = 1 - sumVector.magnitude;
 
 // Include it in the accelerationMultiplier
 var accelerationMultiplier = (1 - (rigidbody.velocity.magnitude / topSpeed)) * directionMultiplier;
 
 // Apply the force
 if (Input.GetButton("Vertical"))
    rigidbody.AddRelativeForce(direction * acceleration * accelerationMultiplier * Time.deltaTime);
Comment
Add comment · Show 6 · 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 amirabiri · Oct 11, 2012 at 09:27 AM 0
Share

Try your code the following way: accelerate to top speed in one direction, then turn 90 degrees right and press the thrust key...

avatar image Jonatan Crafoord · Oct 11, 2012 at 09:40 AM 0
Share

Oh, yes... :-p So, we need to keep track of the Vector too then. I'll try to modify my answer in a bit.

avatar image amirabiri · Oct 11, 2012 at 09:48 AM 0
Share

I was thinking of a solution with a dot product (game world is 2D). There is also a question of how the solution reacts when the ship is already at a speed higher than its top speed (from impact for example or under a temporary slow effect).

avatar image Jonatan Crafoord · Oct 11, 2012 at 10:02 AM 0
Share

Added a new code attempt. Haven't tried it, and I usually code C#, but hopefully you get the idea behind.

avatar image Jonatan Crafoord · Oct 11, 2012 at 10:06 AM 0
Share

There is probably a cleaner way of doing it. But this solution should actually brake your speed if you're above max. Any speed bonuses or slow effects should probably change the topSpeed value to make it work correctly.

Show more comments
avatar image
0

Answer by Jonatan Crafoord · Oct 10, 2012 at 10:10 PM

I was looking for this for a long time as well. Finally found the answer in this forum post: http://forum.unity3d.com/threads/34667-Terminal-Velocity

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 Sisso · Oct 11, 2012 at 02:24 AM 0
Share

If your question was answered, please accept, even if was answered by yourself.

avatar image amirabiri · Oct 11, 2012 at 06:19 AM 0
Share

$$anonymous$$y particular context is a ship in outer space, where the object preserves it's momentum, therefore I can't use drag.

avatar image Jonatan Crafoord · Oct 11, 2012 at 09:24 AM 0
Share

I see. New answer attempt added then. :)

  • 1
  • 2
  • ›

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

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

9 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

2D 360 degress platformer example needed 0 Answers

What is the best way to check is object intersecting? 1 Answer

how to stop mesh entering another mesh, both with colliders 3 Answers

Does AddForce use Time.deltaTime or TIme.fixedDeltaTime or it depends on whether it is being used in Update() or fixedUpdate()? 2 Answers

Rotating a Rigidbody with Physics 1 Answer


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