File size: 4,119 Bytes
40c0886
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# Unity Physics

Unity ships two physics engines: **3D (NVIDIA PhysX)** and **2D (Box2D)**.
This document covers 3D physics, which is what the open-world city example
uses.

## Rigidbody

A `Rigidbody` puts a GameObject under physics control. There are two ways to
move a rigidbody:

1. **Force-based** (preferred for realistic motion):
   ```csharp
   _rb.AddForce(Vector3.up * jumpForce, ForceMode.VelocityChange);
   _rb.AddForceAtPosition(force, wheel.position, ForceMode.Force);
   ```

2. **Direct velocity set** (preferred for arcade controllers):
   ```csharp
   Vector3 v = _rb.velocity;
   v.x = desired.x;
   v.z = desired.z;
   _rb.velocity = v;
   ```

| ForceMode       | Mass dependent? | Use case                           |
|-----------------|-----------------|------------------------------------|
| `Force`         | Yes             | Continuous pushes (default)        |
| `Acceleration`  | No              | Continuous push ignoring mass      |
| `Impulse`       | Yes             | Instantaneous burst (explosion)    |
| `VelocityChange`| No              | Instantaneous burst (jump)         |

* Set `rb.freezeRotation = true` when you want to control rotation manually
  (most third-person controllers).
* Use `rb.interpolation = RigidbodyInterpolation.Interpolate` to smooth out
  stutter when the physics timestep (50 Hz) is slower than the render rate
  (60+ Hz).
* Set `rb.collisionDetectionMode = CollisionDetectionMode.Continuous` for
  fast-moving objects to prevent tunnelling.

## Colliders

* `BoxCollider`, `SphereCollider`, `CapsuleCollider`, `MeshCollider` are the
  built-in shapes.
* `MeshCollider` should be **convex** unless the mesh is static (mark
  `Convex` in the inspector) -- rigidbodies require convex colliders.
* Set `isTrigger = true` to receive `OnTriggerEnter/Stay/Exit` without
  physically blocking movement. Use triggers for pickups, zones, audio
  volumes.

```csharp
private void OnTriggerEnter(Collider other)
{
    if (other.CompareTag("Player"))
        Debug.Log("Player entered the zone");
}
```

## Raycasting

```csharp
// Single hit
if (Physics.Raycast(origin, direction, out RaycastHit hit, maxDistance, layerMask))
{
    Debug.Log(hit.collider.name);
}

// Sphere cast -- great for ground checks on characters
if (Physics.SphereCast(origin, radius, Vector3.down, out RaycastHit hit, distance, mask))
{
    _isGrounded = true;
}

// Overlap sphere -- explosions, area damage
Collider[] hits = Physics.OverlapSphere(center, radius);
foreach (var h in hits)
{
    var hp = h.GetComponentInParent<HealthSystem>();
    if (hp != null) hp.TakeDamage(damage);
}
```

> Use `QueryTriggerInteraction.Ignore` to skip trigger colliders in physics
> queries unless you explicitly want them.

## Layer masks

Layer masks let you filter physics queries and collisions:

```csharp
public LayerMask groundMask = ~0; // everything by default

if (Physics.Raycast(origin, dir, out _, distance, groundMask)) { ... }
```

You can also use `LayerMask.GetMask("Ground", "Default")` to convert names
at runtime, but exposing the mask as a serialised field is cleaner.

## Physics step vs frame step

| Step          | Method        | Frequency                 | Use it for                |
|---------------|---------------|---------------------------|---------------------------|
| Physics       | `FixedUpdate` | Fixed (50 Hz by default)  | `rb.AddForce`, wheel torque |
| Frame         | `Update`      | Variable (frame rate)     | `Input.GetAxis`, gameplay |
| Post-frame    | `LateUpdate`  | After all Updates         | Camera follow             |

Never read `Input` in `FixedUpdate` -- the input system only updates once
per frame, so `FixedUpdate` may run zero or multiple times per frame.

## Collision matrix gotchas

* Two trigger colliders do not fire `OnTriggerEnter` unless **at least one**
  of their GameObjects has a Rigidbody.
* A Rigidbody marked `IsKinematic` will not respond to forces but **will**
  push other rigidbodies.
* Adjust the collision matrix in `Project Settings > Physics` to skip
  collision between layers (e.g. Player vs. PlayerBullet).