Preventing Player Vehicles From Passing Through Walls In Unity

Colliding with Walls

Making vehicles collide properly with walls in a Unity scene starts with configuring the collision layers and rigidbody physics. By correctly defining which game objects can collide with each other, we can lay the groundwork for realistic vehicle-wall interactions.

Defining Collision Layers

Unity uses layers to dictate which objects should collide in a scene. We need to properly configure the layer collision matrix to enable collisions between vehicles and walls. Here are the key steps:

  1. Create a “Vehicle” layer under Edit > Project Settings > Tags and Layers
  2. Create a “Wall” layer
  3. Under the Layer Collision Matrix, check the box to enable “Vehicle” vs “Wall” collisions

Now walls and vehicles can collide with each other by default. Any GameObjects assigned to those layers will intersect properly during physics simulation.

Assigning Collision Layers

After defining collision layers, we need to add vehicles and walls to them:

  1. Select each vehicle GameObject
  2. In the Inspector, assign the “Vehicle” layer
  3. Repeat for each wall GameObject, assigning the “Wall” layer

The scene layers are now configured correctly. Vehicles belong to the Vehicle layer, walls belong to the Wall layer, and collisions between those layers are enabled.

Configuring Rigidbody Physics

The final step is ensuring vehicles and walls use rigidbody physics:

  1. Add a Rigidbody component to each vehicle
  2. Check “Is Kinematic” on each wall Rigidbody

This allows the vehicles to move dynamically while walls remain static colliders. The physics simulation will now detect and resolve collisions between them.

Blocking Vehicle Movement

With collision layers and physics defined, vehicles will collide with walls. However, by default they will still pass through. We need custom logic to block vehicles from passing through colliders.

Using OnCollisionEnter Function

The key is using the OnCollisionEnter function to detect when a vehicle first contacts a wall collider:


void OnCollisionEnter(Collision collision) 
{
  // Detect collision  
}

This gets called automatically by physics when a collision occurs. We can access information about the collision to check if it was with a wall.

Checking Collision Normal

To test if the collision was head-on with a wall, we need to check the collision normal:

  
void OnCollisionEnter(Collision collision)
{
  if (Vector3.Dot(collision.contacts[0].normal, transform.forward) < -0.5) 
  {
    // Head-on wall collision  
  }
}

If the angle between the vehicle's forward and the collision normal is less than 90 degrees, it was primarily a front-end impact. This indicates a wall blockage rather than just scraping alongside it.

Negating Vehicle Velocity

Once we detect a head-on wall collision inside OnCollisionEnter, we can block the vehicle from passing through by negating its velocity:


void OnCollisionEnter(Collision collision) 
{
  if (HeadOnWallCollision(collision))
  {     
    GetComponent().velocity = Vector3.zero;
    GetComponent().angularVelocity = Vector3.zero;
  }
}  

This instantly cancels out the vehicle's movement, blocking it in place against the wall. The physics simulation will then separate them on the next frame.

Example Vehicle Controller

For a real working example, here is a basic vehicle controller script that handles wall collisions:

Creating Vehicle Script

First we make a VehicleController script and attach it to the vehicle:


public class VehicleController : MonoBehaviour {

  public float speed = 10f;
  public float turnSpeed = 45f;
  
  private Rigidbody rb;

  void Start()
  {
    rb = GetComponent();
  }

  void FixedUpdate() 
  {
    // Move vehicle
  }
  
  void OnCollisionEnter(Collision collision)
  {
    // Handle collisions 
  }

}

This will drive the vehicle forward based on input and resolve wall collisions.

Getting Input and Move Direction

Inside FixedUpdate we handle input and calculate a move direction:


  void FixedUpdate()
  {
    // Forward input
    float vInput = Input.GetAxis("Vertical") * speed;

    // Turn input 
    float hInput = Input.GetAxis("Horizontal");
        
    // Calculate move direction
    Vector3 dir = transform.forward * vInput;
    dir += transform.right * hInput * turnSpeed;

    // Apply to rigidbody
    rb.MovePosition(rb.position + dir * Time.fixedDeltaTime);
  }

This uses the Vertical axis for acceleration and Horizontal axis for steering. The end result is applied to the rigidbody movement.

Applying Movement Rules

For more control over movement mechanics, we can modify the direction before applying forces:


  void FixedUpdate() 
  {
    // Gather inputs
      
    // Calculate desired direction
    Vector3 desiredDir = transform.forward * vInput; 
    desiredDir += transform.right * hInput * turnSpeed;

    // Limit direction based on angle
    desiredDir = Vector3.ClampMagnitude(desiredDir, speed);

    // Apply friction slant direction  
    Vector3 slantDir = Vector3.Lerp(desiredDir, rb.velocity, slick);

    // Final direction  
    Vector3 dir = slantDir;
    dir.y = rb.velocity.y;

    // Apply to rigidbody
    rb.velocity = dir; 
  }  

This clamps max speed, slants movement on turns, and keeps upright orientation. The exact rules can be customized as needed.

Handling Collisions

Finally we use OnCollisionEnter to check for wall impacts:


  void OnCollisionEnter(Collision collision) 
  {
    // Head-on wall collision test
    if (Vector3.Dot(collision.contacts[0].normal, transform.forward) < -0.5)
    {
      // Halt velocity to block sliding through
      rb.velocity = Vector3.zero;
      rb.angularVelocity = Vector3.zero;
    }
  }

If a front-end collision is detected, we zero out velocity to block the vehicle from passing through the wall.

Improving Collision Response

To make collisions look and feel more realistic, we can improve the physical reaction using physics materials.

Using Physics Materials

Adding a physics material overrides the default collision response with custom values. Here are the main benefits:

  • Configure exact friction and bounciness reactions
  • Tune the audio clips triggered by impacts
  • Eliminate surface sticking and tight physics gaps

This helps make vehicles behave realistically when hitting walls and other objects.

Configuring Bounciness and Friction

Inside a physics material, the two main tuning values are:

  • Bounciness - Controls how much energy is retained after impact
  • Friction - Determines how slippery the surface contact is

High bounciness with low friction makes surfaces very "bouncy". Low bounciness with high friction creates very "sticky" collisions.

Preventing Sticking

One issue is vehicles sticking to wall collisions too much. Symptoms include:

  • Getting caught on minor surface cracks
  • Being anchored to steep slopes
  • Feeling glued down around tight turns

This is often from too much friction influence after an impact. Some tips to reduce sticking:

  1. Lower the Friction Combine setting closer to "Minimum"
  2. Raise default collision Bounciness higher
  3. Increase Rigidbody drag settings

Tuning values appropriately reduces sticky forces so vehicles can glance off surfaces more readily after collisions.

Summary

Preventing vehicles from passing through walls takes careful configuration between layers, physics, and scripts in Unity:

Key Points for Solid Collisions

  • Define collision layers for vehicles vs walls
  • Use physics rigidbodies and triggers appropriately
  • Detect collisions entering OnCollisionEnter
  • Halt velocity on front-end wall impacts
  • Tune physics materials for best reactions

Additional Tips for Tuning

Here are some other tips for realistic vehicle-wall collisions:

  • Use smaller, tapered trigger colliders on vehicles to avoid surface snagging
  • Add physics distortion effects using shader animations
  • Use audio clips triggered by collision enter/exit events
  • Animate vehicle parts reacting to impacts

With the fundamentals handled in code, there is a lot of room for building on realism via special effects and sound design.

Leave a Reply

Your email address will not be published. Required fields are marked *