0
\$\begingroup\$

I need help with a script for a very simple car that uses transform.Translate:

public class car1 : MonoBehaviour {

    public PauseMenu pause;
    [Space]
    public Car_Script car_s;
    public float speed;
    public GameObject car;

    void FixedUpdate()
    {

        if (car_s.InCar == true)
        {
            if(pause.isPaused == false)
            {
                if (Input.GetKey(KeyCode.W))
                {
                    car.transform.Translate(Vector3.forward * Time.deltaTime * speed);

                    if (Input.GetKey(KeyCode.A))
                    {
                        if (speed <= 0)
                        {
                        }
                        else
                        {
                            if (speed > 0F && speed <= 50F)
                            {
                                car.transform.Rotate(Vector3.down, 2F);
                            }
                            else if (speed > 50F && speed < 90F)
                            {
                                car.transform.Rotate(Vector3.down, 1.3F);
                            }
                            else if (speed > 90F)
                            {
                                car.transform.Rotate(Vector3.down, 0.9F);
                            }

                        }
                    }
                    if (Input.GetKey(KeyCode.D))
                    {
                        if (speed <= 0)
                        {
                        }
                        else
                        {
                            if (speed > 0F && speed <= 50F)
                            {
                                car.transform.Rotate(Vector3.up, 2F);
                            }
                            else if (speed > 50F && speed < 90F)
                            {
                                car.transform.Rotate(Vector3.up, 1.3F);
                            }
                            else if (speed > 90F)
                            {
                                car.transform.Rotate(Vector3.up, 0.9F);
                            }

                        }
                    }
                }
            }
        }
    }
}

Whenever I drive the car it immediately goes through walls.

I have colliders on everything. The car has mesh colliders set to convex.

I've searched around quite a bit for answers and it seems that a common one is using rigid bodies. But whenever I even put a rigid body on the car, it flies out into the sky.

\$\endgroup\$
3
  • 2
    \$\begingroup\$ One coding style tip: what you have here is called "arrow-shaped code" or the "arrowhead anti-pattern" - it happens when you have a lot of nested ifs or loops so your code indents further and further in, making it harder to keep track of what all the layers are doing and if they're closed in the right places. Here, it looks like you could flatten a lot of this with guard clauses. Instead of wrapping the whole method in if (car_s.InCar == true) {...everything...}, try an early-out: if(car_s.InCar == false) return; same effect, without an end brace to keep track of all the way at the end. \$\endgroup\$
    – DMGregory
    Feb 17, 2018 at 13:42
  • \$\begingroup\$ ok i did that i hope it helpd \$\endgroup\$ Feb 17, 2018 at 19:38
  • \$\begingroup\$ In addition to what @DMGregory said, reemerge also that you can combine statements and drop things like == true, eg if (car_s.InCar && !pause.isPaused) \$\endgroup\$ May 13, 2018 at 15:58

1 Answer 1

8
\$\begingroup\$

When you move an object with its transform, you're telling Unity "I don't care about colliders or physics or whatever, just put the object exactly HERE" and it will obey, wedging the object right through solid colliders if you tell it to.

If it has a Rigidbody, then on the next physics step the physics engine will try to do its best to clean up the mess, finding some impulse that will take this object (which is ostensibly stationary - it didn't have any forward velocity carrying it into the wall, it just teleported itself there with its transform) and move it outside of the colliders it's penetrating.

If it's really wedged in there, then that impulse can be quite large, resulting in objects launching out out from each other. Or it could get wedged so deep that the smallest impulse that resolves the collision is to push it out the other side, so the object tunnels right through a solid barrier (the physics engine doesn't know this shouldn't be possible, because there's no velocity information telling it which direction the object impacted from, so pushing it out either side seem like equally plausible ways to resolve this teleport)

If the object has no rigidbody, then its movement is not influenced by the physics engine, and no collision police will enforce that colliders should mean anything to it. You're on your own to use the transform responsibly to put the object where you actually want it. If you pass it right through a collider, well, that's what you told Unity you wanted it to do. Who is it to argue?

So, solutions:

  1. Add a rigidbody and do not touch its transform. Move it solely via rigidbody methods like AddForce, velocity, AddTorque, MoveRotation, etc.

    This way the motion remains under the control of the physics engine and it can stop the object when it begins to hit something and process the collision correctly, rather than doing its best to clean up after a teleportation accident.

  2. Keep your transform-based movement, and take on responsibility for avoiding interpenetration in your own script. That may mean casting rays, boxes, or other shapes to determine how far into its motion the object can go before penetrating another collider, and positioning it at the nearest non-intersecting point.

    This gives you complete control of its physics if you want it to behave in ways the normal physics sim does not out of the box (eg. if you want something exaggerated & cartoony), but it can increase the complexity of your code if you need to model more complicated physical interactions yourself, like the torque from striking a wall corner-on, or the push imparted to a pile of debris objects as you try to drive through them.

\$\endgroup\$
3
  • \$\begingroup\$ i had already thought that when using transform.translate it would move the object threw walls. i messed around a little bit more and found that i could disabled the mesh collider on the car and add a box collider around it. i changed the mass of the car to 1000. and it seemed to work. \$\endgroup\$ Feb 17, 2018 at 19:39
  • \$\begingroup\$ thanks for all the help and some cool new information for me to remember. however i dont really know how to use AddForce, velocity, AddTorque, moveRotation and etc. my game is an fps game and this is the first time im making a car script ever. \$\endgroup\$ Feb 17, 2018 at 19:40
  • \$\begingroup\$ If you don't know how to use them, that's a great opportunity to ask. :) Just make sure you include lots of detail about the situation and the intended behaviour you want to achieve. \$\endgroup\$
    – DMGregory
    Feb 17, 2018 at 20:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .