Hello people, I am relatively new to Unity so this might be a stupid question, but I will still try it.
I tried to make something that has resemblance to collision detection. The set up is described in the picture.
I have a cube that has basic Rigidbody and collider. I want it to go to the right by setting Rigidbody.velocity, and when it reaches a point (e.g. transform.position.x =0), it stops. The script applies to both sides so if it is on the right it will go left.
The problem here is that the position of the cube is updated each frame, and it will never go to exact 0. For example, current frame x = -0.004f, next frame x = 0.01f. So instead of the behaviour I want, I get a pendulum like behaviour where the object springs back and forth around the X line.
I can use lerp, but it makes the object slow down at the middle (maybe that’s the point). But I still want to have a more constant movement.
I noticed the collision system never gets this problem. Even if I move at the speed of 5000 velocity, objects would still stop right at the colliding point.
How did they do it? How do I replicate something like that or am I missing something.
Thank you in advance.
Hello @ducthangdang1502
I’m going to reply to your 2 question..
If you want to continue with this technique, you need to use a check based on the position.. That’s because, as you said, the position will be “never” exact 0…
this is an example code that can fix the problem:
private Vector3 targetPosition;
void Update(){
float distance = Vector3.Distance(this.transform.position, this.targetPosition);
if(distance < 0.01f){
rigidBody.velocity = Vector3.zero;
this.transform.position = this.targetPosition;
}
}
This is a very basic code to resolve the issue.. The problem remains if you speed up the movement..
To resolve this, you need to implement collisions..
First of all, add a collider on your cube (I know that you already have a RigidBody attached).
Create a gameObject in the scene and add it a BoxCollider.
Enable the isTrigger on this collider and add a TAG to the gameObject like “StopPoint”.
Make the collider of the blocking object much smaller than your cube.. for a test, try making it 10 times smaller.
Now add this function on you cube script:
private void OnTriggerEnter(Collider collider) {
rigidbody.velocity = Vector3.zero;
this.transform.position = collider.gameObject.transform.position;
}
This code will solve your problem, but I must warn you that it is not the best method to implement what you want to do.
The best solution would be to calculate where the cube has to stop, and perform a distance check .. obviously, you shouldn’t use extreme speeds, or you would encounter the first problem.
Hope this can help you.
Instead of just looking at the current frame, look at the last two frames and test if the object crossed the line between the two frames. For example, if you want to stop your object at x = 0 then you check if x > 0 in one frame and x < 0 in the other. If that condition is true then you can get a good estimate for it’s actual position at the time of crossing the line by solving a linear equation. Let’s not concern ourselves with the exact math here, in Unity you would probably do it with Lerp and InverseLerp:
public Vector3 velocity;
Vector3 previousPosition;
void Update() {
transform.position = transform.position + velocity * Time.deltaTime;
// Did the object cross the line?
if (transform.position.x > 0 != previousPosition.x > 0) {
// When did the object cross the line?
var t = Mathf.InverseLerp(previousPosition.x, transform.position.x, 0);
// Where did the object cross the line?
transform.position = Vector3.Lerp(previousPosition, transform.position, t);
// Stop moving the object
velocity = Vector3.zero;
}
// Store current position for next frame
previousPosition = transform.position;
}