ryzerrr's picture
Upload folder using huggingface_hub
40c0886 verified
|
Raw
History Blame Contribute Delete
4.12 kB
# 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).