Skip to main content
C# for Games – Complete Beginner to Advanced Guide
CHAPTER 09 Beginner

Physics Programming Basics

Updated: May 16, 2026
30 min read

# CHAPTER 9

Physics Programming Basics

1. Introduction

If you want a wooden crate to tumble down a hill, you *could* write complex C# math to calculate gravity, mass, friction, and angular rotation. Or, you could simply let the engine's built-in Physics Engine do it for you. A physics engine is a massive background simulation that calculates physical reality so you don't have to. However, you still need to know how to interact with this simulation using code. In this chapter, we will master Physics Programming. We will learn how to apply forces to Rigidbodies, detect when two objects collide, and understand the critical rules of the FixedUpdate loop.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand the role of a Rigidbody component.
  • Apply physical forces via code (e.g., AddForce).
  • Use the FixedUpdate loop for stable physics calculations.
  • Detect solid collisions using OnCollisionEnter.
  • Detect overlapping ghost collisions using OnTriggerEnter.

3. The Rigidbody (Giving Objects Mass)

In a game engine, adding a 3D model to a scene just makes a ghost. To make the engine calculate gravity and physical bouncing for that object, you must attach a Rigidbody component to it.
  • Once an object has a Rigidbody, you should *never* move it using transform.Translate() (teleporting).
  • Instead, you must push it using physics forces.

4. Applying Forces (AddForce)

To push a Rigidbody, we grab a reference to it in C# and call the AddForce method.
csharp
123456789101112131415
class PhysicsPlayer
{
    // Reference to the engine's physics component
    public Rigidbody rb; 
    public float jumpForce = 500f;

    void Update()
    {
        if (Input.GetKeyDown("space"))
        {
            // Push the object upwards (Y-axis) with an Impulse force
            rb.AddForce(new Vector3(0, jumpForce, 0), ForceMode.Impulse);
        }
    }
}

5. The FixedUpdate Loop (The Physics Tick)

Physics engines hate fluctuating framerates. If gravity is calculated 144 times a second, and then suddenly 30 times a second, objects will glitch through solid walls.
  • Engines solve this with FixedUpdate.
  • FixedUpdate() runs at a locked, steady tick rate (usually exactly 50 times a second), regardless of your monitor's framerate.
  • *Golden Rule:* If you are constantly applying physics forces (like pushing a car forward), that code MUST go in FixedUpdate().

6. Collision Detection

When two Rigidbodies hit each other, the engine handles the bounce automatically. But how do you know it happened so you can subtract health?
  • Game engines provide built-in event methods.
  • OnCollisionEnter: Fires the exact frame two solid objects smash into each other.
csharp
12345678910
// This is automatically called by the engine upon impact
void OnCollisionEnter(Collision hitData)
{
    // Check the "Tag" of the object we just hit
    if (hitData.gameObject.tag == "Enemy")
    {
        Console.WriteLine("Ouch! Hit an enemy!");
        TakeDamage(10);
    }
}

7. Triggers (Ghost Collisions)

Sometimes you don't want objects to act like brick walls. If a player walks through a toxic gas cloud, they shouldn't bounce off it; they should walk through it, but the game still needs to know they entered it.
  • By checking the "Is Trigger" box on a collider, it becomes a ghost.
  • To detect it in code, use OnTriggerEnter.
csharp
12345678
void OnTriggerEnter(Collider other)
{
    if (other.tag == "Coin")
    {
        gold += 1;
        Destroy(other.gameObject); // Delete the coin
    }
}

8. Visual Learning: Collision vs. Trigger

txt
1234567
[ COLLISION ] (Solid impact, physics engine bounces them away)
Player [======] -> SMAASH! <- [======] Brick Wall
Action: OnCollisionEnter() fires.

[ TRIGGER ] (Ghost overlap, no physical bounce)
Player [======] -> walks into -> (::::) Gas Cloud
Action: OnTriggerEnter() fires.

9. Best Practices

  • Never Use DeltaTime in FixedUpdate: Because FixedUpdate runs at a locked interval, the time between ticks is already perfectly constant. Multiplying by Time.deltaTime inside FixedUpdate is not only unnecessary, it will actually break your math.

10. Common Mistakes

  • Teleporting Rigidbodies: A beginner attaches a Rigidbody to a car, but writes transform.position.z += 5; in the Update loop. The car moves, but ignores gravity, flies through walls, and jitters uncontrollably. *Rule:* If an object has a Rigidbody, you must move it via rb.AddForce() or rb.velocity, NOT by changing its transform coordinates directly.

11. Mini Project: Build a Physics Bouncer

Objective: Use Rigidbody forces and detect a collision to play a sound.
csharp
1234567891011121314151617181920212223242526272829
class BouncyBall
{
    Rigidbody rb;

    void Start()
    {
        // Get the Rigidbody attached to this object
        rb = GetComponent<Rigidbody>(); 
    }

    void Update()
    {
        // Push the ball Right
        if (Input.GetKeyDown("d"))
        {
            rb.AddForce(new Vector3(300, 0, 0));
        }
    }

    // Detect when the ball hits the floor or a wall
    void OnCollisionEnter(Collision hit)
    {
        if (hit.gameObject.tag == "Wall")
        {
            Console.WriteLine("Boing! Hit the wall.");
            PlayBounceSound();
        }
    }
}

12. Practice Exercises

  1. 1. What is the fundamental difference between OnCollisionEnter and OnTriggerEnter?
  1. 2. Why is the FixedUpdate loop used instead of the Update loop when applying continuous physics forces?

13. MCQs with Answers

Question 1

You are coding a spaceship that constantly fires its thrusters to move forward. The spaceship has a Rigidbody attached. In which C# method should you place the rb.AddForce() code to ensure the physics engine remains stable?

Question 2

You create an Area in your level that acts as a "Finish Line". It should not physically block the player from moving, but you need to run code when the player crosses it. What type of collider and C# method should you use?

14. Interview Questions

  • Q: Explain the mathematical dangers of mixing Transform movement (teleporting) with a Rigidbody component. How does the physics engine react?
  • Q: A junior programmer writes rb.AddForce(Vector3.up * speed * Time.deltaTime); inside the FixedUpdate() method. Identify the mathematical flaw in this code.
  • Q: Walk me through the execution order of Update() vs FixedUpdate(). How many times might FixedUpdate() be called during a single frame if the game drops to 10 FPS?

15. FAQs

Q: Can I turn physics off temporarily? A: Yes! You can set rb.isKinematic = true (in Unity). This tells the engine, "Stop simulating gravity and collisions for this object, I want to control it via animations or script for a few seconds."

16. Summary

In Chapter 9, we handed control over to the physics simulation. We learned that we should not teleport physical objects; we must push them using a Rigidbody and AddForce(). We protected our simulation from framerate glitches by moving all physics logic into the locked FixedUpdate() loop. Finally, we learned how to react to the world, using OnCollisionEnter for solid impacts (like hitting a wall) and OnTriggerEnter for ghost interactions (like collecting coins).

17. Next Chapter Recommendation

Our game functions perfectly in the physics world, but the player has no idea what their health is. Proceed to Chapter 10: Building UI Systems for Games.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·