Beginner question, but i have seen multiple ways of moving an object in a 3d scene (im particuarly thinking about player movement but generally any object that needs to move) and am not sure the best way to do a pretty simple task, eg. Using .AddForce() to a physics object, transform.Translate(), Vector3.Lerp() (last one not so much) and some other ways i cant remember off top of my head but was curious when the best place would be to use each way, how it works and performance. Any help is appreciated! (Mostly for player objects as ive seen alot of different ways to move them but anything really)
Usually if an object needs to move it is best to have a Rigidbody on it. so using Rigidbody.AddForce();
or Rigidbody.linearVelocity = Speed;
is probably the best way to go around it.
Ah ok, would this mean the object has some ‘left over’ movement, eg. Player stops pressing button but obj gradually slows to a halt instead of stopping instantly?
the rigidbody.addforce option would do that, whereas the rigidbody.linearVelocity option instantly changes the velocity so it would be instant.
AddForce is the best way to move a rigidbody. Changing the velocity directly can be problematic as it means it’ll override other forces like gravity and prevent friction and bouncing from occurring.
While it is less applicable to Player-controlled objects, just using a bog-standard plain vanilla tweener (like LeanTween, DOTWeen, iTween, whatever-tween) can save you a TON of time and a ton of fiddly buggy coding.
Otherwise, here’s some more notes:
Smoothing movement between any two particular values:
You have currentQuantity and desiredQuantity.
- only set desiredQuantity
- the code always moves currentQuantity towards desiredQuantity
- read currentQuantity for the smoothed value
Works for floats, Vectors, Colors, Quaternions, anything continuous or lerp-able.
The code: SmoothMovement.cs · GitHub
Hello,
Great questions and it’s definitely a plethora of subjects that can go on forever. I’ve spent a lot of time on these, and there’s always more to learn and consider. The way you want to move anything can always change depending on what your game object is and what you want to do with it. I’ve spent a lot of time working on first person physics controllers, so that’s what I’m drawing on here. Maybe not everything will be clear, but, the below will cover various subjects you can look up, etc.:
I’m going to put performance aside for this discussion as I don’t think I can help with it given the broad context. Let’s just assume for these movement examples, that it’s something we’re going to do every single frame, whether in Update() or FixedUpdate().
For you to get comfortable with this, I recommend starting with manipulating a game object’s transform.position directly, or the same- using the method transform.Translate(). There is nothing wrong with transform.Translate() and it is probably the easiest and most basic way of moving any object. To move it forward, you just need, ideally, a Vector3 for direction (preferably normalized), a speed to multiply it by, and a call to Time to make it framerate independent and per-second.
// This will move your game object at 5 units/second forward in its +Z local axis.
transform.Translate(transform.forward * 5f * Time.deltaTime);
You will use this same basic idea in the similar move methods for Rigidbody. So, I advise practicing and getting comfortable making things move with transform.Translate and get good at describing Vectors in 3D space, both globally and locally, etc.
Now because you are asking about player game objects, of course you will eventually want to move on to physics. Which is truly the subject that never ends. When working with physics, you will use FixedUpdate(), instead of Update() which you will use when manipulating the transform directly, as above. Here you can use Time.fixedDeltaTime instead of regular old delta time.
Some people will tell you to only use [Method X] when using physics, but every method that exists is… there to be done. You can go to the Rigidbody page on the scripting API and see all the properties and methods you can mess with on a rigidbody. You can actually even set the Transform directly, and it does work- it’s just not advisable.
When you are working with physics, I think it’s most useful to think of what you can do with the rigidbody in terms of least deterministic to most deterministic. The more aggressively we enforce the rigidbody’s position or speed by code, the more we undermine the “purity” of the physics simulation. You will have to feel out what this means in each case over long practice, experience and reading. Some people will tell you to only ever (emphasis on only and ever) use AddForce()… but they will rarely tell you afterward, how to then use integral calculus, or principles of industrial design, to make that object slow down and brake and move in a way that’s appropriate and snappy for a video game… So, consider that. If the other methods were entirely bad ideas, they probably wouldn’t exist.
Note- I am assuming a dynamic rigidbody in this discussion, not a kinematic one.
Anyway, a simple hierarchy from most aggressive to most permissive would probably be
- set transform.position or do transform.Translate() (generally don’t do this with a rigidbody)
- set rigidbody.position
- use Rigidbody.MovePosition()
- set the Rigidbody.linearVelocity (I use this for player controllers)
- use Rigidbody.AddForce()
MovePosition() will work essentially the same way as transform.Translate in the example above, only it will live more correctly in the physics simulation- just use Time.fixedDeltaTime. Once you are competent at those very enforced methods, try moving on to setting the linear velocity directly. That’s what I use for my player controllers, and I’ve spent a very long time making them, and using the physics engine. It will present you, of course, with a few new challenges, which you will work out how to solve.
For example, what’s happening with the y velocity component (Helpful Hint: when you compose your Vector3, just set the y component to the current velocity’s y component)? Can things still push you around if you’re enforcing your velocity every fixed frame? Do you keep moving when you let go of W (Yes, you probably will, but you can solve that in your own way, like setting XZ velocity to 0 when you let go of W… of course, that too will introduce other challenges )
I prefer setting velocity in this way for player movement because it feels much more appropriate to the type of snappy and precise controllers I create for first person experiences. And for their jumping, I use AddForce().
Briefly, as stated by someone above, Tweens (from Tweening engines) are also good ways to move objects. It can be especially good for effects, or machines. But be sure you understand what method the Tween is using to move the object, and how that tweening engine handles its life cycle, etc.
Lastly, using Vector3.Lerp() along with setting a transform.position is also a great way to move things- remember, what’s important here is the method we are using- we are enforcing transform.position, and determining what that position should be with a Vector3 lerp.
A small bone to pick- many accepted examples use lerping in ways that I do not think are good and are not the original purpose of a lerp (linear interpolation, between two poles). An arbitrary lerping “speed” will get used as some kind of “smoothing effect.” If you like or need precision, just try and not do that (my advice). I use lerping more for deterministic effects- if we are lerping on a range from 0 meters (here) to 10 meters forward from here, and we do so on a range from 0f to 1f, a lerp value of .2 puts us 2 meters forward. A lerp value (t) of .5 puts us 5 meters forward, .8 is 8 meters forward, and so on. It can be a great way to move things deterministically, and you can even send that lerp value (t) through an easing function of your choosing, to get cooler effects as opposed to just a linear motion.
Anyway, essay concluded, best of luck to you! Keep learning!