07: Rude Gold Bug (Part 5)
Learning Target
- Detect physics events in code
- Control Rigidbodies through scripts
- Change the state of objects in response to physics events
Resources
- Rigidbody.AddForce:
Unity Doc: https://docs.unity3d.com/ScriptReference/Rigidbody.AddForce.html
Unity Video: - Rigidbody.AddTorque:
Unity Doc: https://docs.unity3d.com/ScriptReference/Rigidbody.AddTorque.html
Unity Video: - OnTriggerEnter:
Unity Doc: https://docs.unity3d.com/ScriptReference/Collider.OnTriggerEnter.html
Unity Video: - OnCollisionEnter:
Unity Doc: https://docs.unity3d.com/ScriptReference/Collision.html
Unity Video: - Rigidbody.isKinematic:
Unity Doc: https://docs.unity3d.com/ScriptReference/Rigidbody-isKinematic.html
Instructions
Step 1: Scripting Basics — Triggers and Collisions
So far your machine has used physics components set up entirely in the Inspector. In this part, you'll write C# scripts that react to physics events and change what objects do at runtime.
There are two main ways a script can detect physical contact:
-
- Trigger Colliders — A collider with "Is Trigger" checked. Objects pass through it, but the script is notified. Good for invisible zones.
- Collision Events — Two solid colliders that actually bounce off each other. The script is notified when they first touch.
The relevant Unity event methods are:
void OnTriggerEnter(Collider other) { } // something
entered a trigger zone
void OnCollisionEnter(Collision col) { } // two solid
objects collidedThere are quite a few ways you can use collisions and triggers to alter the behavior of a physics simulation in Unity.
Here are 4 different examples:
Example 1: Trigger Applies Force or Torque
When the ball (or any object) enters a trigger zone, the script can push or spin another object by calling AddForce() or AddTorque() on its Rigidbody.
Store the target object as a public variable so you can assign it in the Inspector without hard-coding names:
using UnityEngine;
public class TriggerForce : MonoBehaviour
{
public Rigidbody target; // drag the object here in Inspector
public Vector3 force = new Vector3(0, 500, 0);
public Vector3 torque = new Vector3(0, 0, 200);
void OnTriggerEnter(Collider other)
{
if (target != null)
{
target.AddForce(force, ForceMode.Impulse);
target.AddTorque(torque, ForceMode.Impulse);
}
}
}
ForceMode.Impulse applies the force all at once (like a kick). ForceMode.Force applies it continuously per physics frame — useful inside OnTriggerStay().Example 2: Trigger Releases a Kinematic Object
A kinematic Rigidbody is frozen in place — gravity and forces have no effect on it. Setting isKinematic =
false at runtime "releases" it so it falls or flies away normally.
using UnityEngine;
public class ReleaseKinematic : MonoBehaviour
{
public Rigidbody target; // the frozen object to release
void OnTriggerEnter(Collider other)
{
if (target != null)
{
target.isKinematic = false; // let gravity take over
}
}
}
isKinematic = true to freeze a moving object, like catching a ball in a cup or slamming a gate shut.Example 3: Collision Between Two Objects Changes Movement
OnCollisionEnter fires when two non-trigger colliders physically hit each other. You can react to that impact — add extra force, change kinematic state, or anything else.
using UnityEngine;
public class CollisionBumper : MonoBehaviour
{
public float bounceForce = 800f;
void OnCollisionEnter(Collision col)
{
// Push the incoming object away from this object's center
Rigidbody rb = col.rigidbody;
if (rb != null)
{
Vector3 direction = col.transform.position - transform.position;
direction.Normalize();
rb.AddForce(direction * bounceForce, ForceMode.Impulse);
}
}
}
col.rigidbody gives you the Rigidbody of whichever object hit you. col.relativeVelocity.magnitude tells you how fast the collision was — useful for only reacting to hard hits.Example 4: Trigger Changes Other Object's State
Not every trigger needs to use forces or kinematic. You can change almost anything in your scene from a script — a light's color, a Hinge Joint's motor speed, a spring's strength, an object's material, whether an object is active at all.
using UnityEngine;
public class TriggerStateChange : MonoBehaviour
{
public HingeJoint motorJoint; // drag the hinge here
public float targetMotorSpeed = 200f;
void OnTriggerEnter(Collider other)
{
if (motorJoint != null)
{
JointMotor motor = motorJoint.motor;
motor.targetVelocity = targetMotorSpeed;
motor.force = 100f;
motorJoint.motor = motor;
motorJoint.useMotor = true;
}
}
}
gameObject.SetActive(false) to make an obstacle disappear entirely, or GetComponent<Renderer>().material.color =
Color.green to change a color.Step 2: Add Scripts to Your Scene
Now it's your turn!
Your scripts must include at least two of the four interaction types described above. Each script must actually affect the Rude Gold Bug's journey — it should contribute directly or indirectly to the ball's motion through the machine.
- Create your scripts in a Scripts subfolder inside your Assets folder
- Attach each script to the appropriate object in your scene
- Assign any public variables (like
target) by dragging objects into the Inspector - Use trigger colliders (
Is Trigger = true) where your zone should not block movement - Test carefully — make sure each script fires at the right moment
Step 3: Testing and Debugging
Scripts introduce new ways things can go wrong. Follow this process:
-
- Check the Console window for errors — a red error usually means something is null or misnamed
- Use
Debug.Log("trigger fired!")inside your event method to confirm it is being called - Check that Is Trigger is checked on your trigger collider (and that the other object has a Rigidbody)
- If
AddForceseems to do nothing, make sureisKinematicis false on the target - Iterate — adjust force values until the motion feels right
Grading
| Criteria | Letter Grade |
|---|---|
|
Indie Developer
|
A++ |
|
Extended
|
A+ |
|
Exceptional
|
A |
|
Good
|
B |
|
Reasonable
|
C |
|
Needs Improvement
|
D |
|
Insufficient
|
F |
| Scores may be rounded to the nearest whole number. | |
Tips for Success
- Start Simple: Create one script at a time and get it working first!
- Null Checks Matter: Check if (target != null) before using a public variable — unassigned references crash your game.
- Debug.Log is Your Friend: Add a log message inside event methods while testing so you know exactly when it fires.
- Force Modes: ForceMode.Impulse for instant kicks, ForceMode.Force for steady pushes, ForceMode.Acceleration to ignore mass.
- Triggers Need Rigidbodies: OnTriggerEnter only fires if at least one of the two objects has a Rigidbody component.
- Keep Scripts Focused: One script should do one thing — it is easier to debug and reuse. However, it is okay to use a script with multiple objects if the behavior is exactly the same.