I keep coming across conflicting information regarding moving a simple 3D rigidbody object - left, right, forward, backwards. As I wish to do things the ‘correct’ way from now on, and not make silly mistakes that may affect my games in the future, what is the correct way?
I hear that the Input should go in the Update method.
That the Rigidbody movement should go in the FixedUpdate method.
I know that Delta Time is important too, but not sure if it always required with physics processes in Unity.
For moving diagonally you require Normalized so that the speed is consistant in those directions too.
I’m more familiar with Transform and Vectors, but realise there are other ways such as Add Force.
I’ve followed many tutorials for Unity over the last few months and read the Unity manual. I’ve looked at loads of examples on YouTube about this topic, but each focuses on different aspects and often the viewers complain in the comments that things haven’t been done right.
I can’t find a single tutorial or script that has all of these correct implementations. I’m here as a last resort
I totally get that it’s probably really obvious to some, but could somone show me a simple short script that encompases all of the above please? Or perhaps even a link to such script if you know where? It might be useful to others looking for this exact thing too.
Here’s what I have so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveCube : MonoBehaviour
{
public float speed = 10.0f;
public Rigidbody rb;
public Vector3 movement;
// Use this for initialization
void Start()
{
rb = this.GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
movement = new Vector3(Input.GetAxis("Horizontal"), 0,Input.GetAxis("Vertical"));
}
void FixedUpdate()
{
moveCharacter(movement);
}
void moveCharacter(Vector3 direction)
{
rb.velocity = direction * speed;
}
}
I have done a change to the above script, but for some reason I can’t edit the post. Anyway, here’s the change I added with Normalized.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveCube : MonoBehaviour
{
public float speed = 1f;
public Rigidbody rb;
public Vector3 movement;
// Use this for initialization
void Start()
{
rb = this.GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
movement = new Vector3(Input.GetAxis("Horizontal"), 0 ,Input.GetAxis("Vertical")).normalized;
}
void FixedUpdate()
{
moveCharacter(movement);
}
void moveCharacter(Vector3 direction)
{
rb.velocity = direction * speed;
}
}
Is this correct? Do I require Delta Time?
For example:
rb.velocity = direction * speed * Time.deltaTime;
I obviously have to increase the speed variable to 100f approx etc.
Thanks hms0589 for the info on Time.fixedDeltaTime, I didn’t know it existed - the Unity manual leaves a little to be desired on this topic!
I’ve added the above to the script, and also commented out how it all works (to the best of my knowledge at this time). I thought i’d include it here for other’s that come across the post in the future.
// This script moves a game object left, right, forwards, backwards...
// using input from keyboard/gamepad (set in the Input Manager)
// 'Update' Method is used for the Input (keyboard/Gamepad)
// 'Fixed' Method is used for physics movement
// The Input is 'Normalized' to prevent faster diagonal movement
// 'Time.fixedDeltaTime' is used to keep the physics framrate consistant on all devices
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveCube : MonoBehaviour
{
// Add the variables
public float speed = 100f; // Speed variable
public Rigidbody rb; // Set the variable 'rb' as Rigibody
public Vector3 movement; // Set the variable 'movement' as a Vector3 (x,y,z)
// 'Start' Method run once at start for initialisation purposes
void Start()
{
// find the Rigidbody of this game object and add it to the variable 'rb'
rb = this.GetComponent<Rigidbody>();
}
// 'Update' Method is called once per frame
void Update()
{
// In Update we get the Input for left, right, up and down and put it in the variable 'movement'...
// We only get the input of x and z, y is left at 0 as it's not required
// 'Normalized' diagonals to prevent faster movement when two inputs are used together
movement = new Vector3(Input.GetAxis("Horizontal"), 0 ,Input.GetAxis("Vertical")).normalized;
}
// 'FixedUpdate' Method is used for Physics movements
void FixedUpdate()
{
moveCharacter(movement); // We call the function 'moveCharacter' in FixedUpdate for Physics movement
}
// 'moveCharacter' Function for moving the game object
void moveCharacter(Vector3 direction)
{
// We multiply the 'speed' variable to the Rigidbody's velocity...
// and also multiply 'Time.fixedDeltaTime' to keep the movement consistant on all devices
rb.velocity = direction * speed * Time.fixedDeltaTime;
}
}
This isn’t valid C# code so I’m not sure why you’re posting this? Also, note that you should never modify the Transform, that’s the whole point of a Rigidbody(2D) to write to the Transform.
Modifying the Transform is just instantly moving to a new position (teleporting) and causes all sorts of physics problems.
You cause physics movement by going through the API of the Rigidbody(2D).
I have arrived to this same problem… but I have some questions about this is THE CORRECT way to do… because some collisions do not work well with it.
I am making a simple exercise, one open box over a carpet, a few balls falling from time to time and you have to collect those balls with the box. Simple!
I am using this code to controll movement, works to move… but some balls get out of the box when I change my direction or even balls that has drop over the carpet get into de box (through the walls…) if I go fast enough and suddenly change my direction.
protected Rigidbody rb;
Vector3 movement;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
private void Update()
{
movement= new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")) * speed;
}
private void FixedUpdate()
{
rb.velocity = movement;
}
I found that the code works really well for character movement but I got a bit of an issue when making a game that has gravity involved, the character falls much slower than other rigidbody objects. I am thinking that the cause might be the part were you set the “Y” on the velocity to zero and since the script runs a lot of times, it probably effects the speed of falling
This is a serious issue that should be adressed in a post marked as solved. Indeed, the Y value of the velocity is being stablished by the Y value of the Vector3 variable named movement and will have a visible effect in gravity. This is the way I solved the gravity issue (please note this is a 2D controller that only moves an object RB horizontally so theres no diagonal movement thus theres no need to normalize):
Try changing “Collision Detection” from “Discrete” to “Continuous Dynamic” in your rigidbodies.
Update: Oh, and there’s no point in using “rb.velocity = movement;” in “private void FixedUpdate()”. It is enough to use in “private void Update()” - it will be the same, but without constant input
information in “rb.velocity” in “FixedUpdate()”, which is called more often than “Update()”. That is, it is even more economical.
Bit of an older thread, but seems like people are still visiting nowadays, so I wanted to add some extra info about this:
As of Unity 2020.3 and per the Time.deltaTime documentation, “When this is called from inside MonoBehaviour.FixedUpdate, it returns Time.fixedDeltaTime.”
So it’s actually fine to use Time.deltaTime within FixedUpdate() in Unity 2020.3 or later!
First link in websearch for “how to move rigidbody unity” so necro.
You do not.
A velocity in Unity is represented as world units per second.
When you set that inside FixedUpdate Unity will multiply that velocity by 0.02, and you multiply that by 0.02. If your intended velocity is 10 (game units/sec) you will have 10*0.02 = 0.2 (game units/sec) - 50x slower. It’s gonna work (you compensate with speed value), but you will have no benefits. More calculations and harder to manage.
You can use (fixed) delta time when you use MovePosition or when you move body by yourself outside of Unity FixedUpdate.
your update part is entirely wrong, update is called constantly while fixed update is only called 50 times a second by default, designed to be slower and more reliable for physics interactions