How can i get my car to redirect/rocochet/bounce off a wall and continue driving?

Hello,
It seems all my code attempts have failed,
I have tried to reflect, transform.rotate, use physics materials. No success.

I have this super simple car, like a baby could make it
, left and right input cause it to move.

    private void GetInput()
    {
        horizontalInput = Input.GetAxis(HORIZONTAL);
        transform.Translate(0, 0, 1.0f * Time.deltaTime, Space.Self);
        transform.Rotate(0,1*horizontalInput,0,Space.Self);
    }

I simply want to have an OnCollisionEnter()
That redirects my car, so it carries on driving when it hits a wall, based on the angle it collides.

E.g If i drive straight into the wall, I will do a 180
Same way a pool ball bouncess off a pool table, but with a car…

Dying of frustration here.

Cheers.

Probably don’t use non-trigger colliders for this issue at all. There will be a force the physics engine applies to rectify that collision automatically that will ruin your bounce.

I would use trigger colliders for the wall. In FixedUpdate, keep track of one previous physics frame worth of position. Then in OnTriggerEnter, do a raycast (or box cast) from your previous position to your new position. That should give you a hit on the collider you’re currently inside. You can use the hit point and normal to calculate the reflected position and direction of the car.

Thanks for your reply PraetorBlue,
I think you have me on the right track!

So i am having a ray appear when I am 2 units from the wall, and then trying to redirect the car based on the direction of the ray.

As you can see in the picture, its not entirely working, in fact 3/4 times it works well, and then it randomly seems to point somewhere completely wrong.

The laser is very accurate, but the redirect is innacurate

I think its something to do with how i redirect the car.
Any ideas?

This is inside my fixedupdate…

        velocityBeforeCollision = gameObject.GetComponent<Rigidbody>().velocity;
        transBeforeCollision = gameObject.GetComponent<Rigidbody>().transform;

        Ray ray;
        RaycastHit hit;
        ray = new Ray(transBeforeCollision.position,transBeforeCollision.transform.forward);
                if(Physics.Raycast(transBeforeCollision.position,transBeforeCollision.transform.forward, out hit, 1))//cast the ray 100 units at the specified direction
                {
                    if(hit.collider.name == "Wall"){
                    print("Raycast hits wall");
                    //find new ray direction
                    Vector3 inDirection = Vector3.Reflect(ray.direction,hit.normal);
                    Debug.DrawRay(hit.point, inDirection*8, Color.magenta);

                    transform.LookAt(inDirection);
                    transform.Translate(0, 0, 2, Space.Self);


                    //hitpoint and indirection now face the correct way
                    }

                }

So since you’re doing rigidbody motion, you should never ever move your object like this:

                    transform.LookAt(inDirection);
                    transform.Translate(0, 0, 2, Space.Self);

Instead, use the rigidbody functions. Also, instead of acutally moving the object, just set a new velocity! This won’t be perfect but it might be close:

        var rb = GetComponent<Rigidbody>();

        if(Physics.Raycast(rb.position,rb.velocity, out RaycastHit hit, rb.velocity.magnitude))//cast the ray 100 units at the specified direction
                {
                    if(hit.collider.name == "Wall"){
                    print("Raycast hits wall");
                    //find new ray direction
                    Vector3 newVelocity = Vector3.Reflect(rb.velocity, hit.normal);
                    Debug.DrawRay(hit.point, newVelocity.normalized*8, Color.magenta);

                    // Set new rotation and velocity.
                    rb.MoveRotation(Quaternion.LookRotation(newVelocity, transform.up));
                    rb.velocity = newVelocity;
                    //hitpoint and indirection now face the correct way
                    }
                }

One thing we might want to add is also moving the object to the reflected version of its current position before setting the new velocity. That will probably result in a bit more convincing of a reflection.

Thanks again :slight_smile:

I think my driving code stops the velocity from working properly though?

    private void GetInput()
    {
        horizontalInput = Input.GetAxis(HORIZONTAL);
        transform.Translate(0, 0, 1.0f * Time.deltaTime, Space.Self);
        transform.Rotate(0,1*horizontalInput,0,Space.Self);
    }

Yeah if that’s your driving code you need to work some stuff out. You either use Rigidbody physics in which case you should only use things like RigidBody.AddForce, RigidBody.MovePosition(), Rigidbody.MoveRotation(), Rigidbody.velocity, OR you don’t use physics at all and you directly modify the transform position and rotation like how you have your driving code. Basically, pick one or the other and go with it. If you use a mix of the two you’re going to get all kinds of crazy behaviors like things going through walls and unsightly jittering.

Amazing, it’s working really well :slight_smile:

Thank you for explaining all of this to me, i appreciate you taking the time.

Awesome, looks like the reflection angle is perfect!