Claude-Code-Game-Studios/docs/engine-reference/unity/modules/physics.md
Donchitos ad540fe75d Game Studio Agent Architecture — complete setup (Phases 1-7)
48 coordinated Claude Code subagents for indie game development:
- 3 leadership agents (creative-director, technical-director, producer)
- 10 department leads (game-designer, lead-programmer, art-director, etc.)
- 23 specialist agents (gameplay, engine, AI, networking, UI, tools, etc.)
- 12 engine-specific agents (Godot, Unity, Unreal with sub-specialists)

Infrastructure:
- 34 skills (slash commands) for workflows, reviews, and team orchestration
- 8 hooks for commit validation, asset checks, session management
- 11 path-scoped rules enforcing domain-specific standards
- 28 templates for design docs, reports, and collaborative protocols

Key features:
- User-driven collaboration protocol (Question → Options → Decision → Draft → Approval)
- Engine version awareness with knowledge-gap detection (Godot 4.6 pinned)
- Phase gate system for development milestone validation
- CLAUDE.md kept under 80 lines with extracted doc imports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 21:04:24 +11:00

268 lines
6 KiB
Markdown

# Unity 6.3 — Physics Module Reference
**Last verified:** 2026-02-13
**Knowledge Gap:** Unity 6 physics improvements, solver changes
---
## Overview
Unity 6.3 uses **PhysX 5.1** (improved from PhysX 4.x in 2022 LTS):
- Better solver stability
- Improved performance
- Enhanced collision detection
---
## Key Changes from 2022 LTS
### Default Solver Iterations Increased
Unity 6 increased default solver iterations for better stability:
```csharp
// Default changed from 6 to 8 iterations
Physics.defaultSolverIterations = 8; // Check if relying on old behavior
```
### Enhanced Collision Detection
```csharp
// ✅ Unity 6: Improved Continuous Collision Detection (CCD)
rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
// Better handling of fast-moving objects
```
---
## Core Physics Components
### Rigidbody
```csharp
// ✅ Best practice: Use AddForce, not direct velocity writes
Rigidbody rb = GetComponent<Rigidbody>();
rb.AddForce(Vector3.forward * 10f, ForceMode.Impulse);
// ❌ Avoid: Direct velocity assignment (can cause instability)
rb.velocity = new Vector3(0, 10, 0); // Only use when necessary
```
### Colliders
```csharp
// Primitive colliders: Box, Sphere, Capsule (cheapest)
// Mesh colliders: Expensive, use only for static geometry
// ✅ Compound colliders (multiple primitives) > single mesh collider
```
---
## Raycasting
### Efficient Raycasting (Avoid Allocations)
```csharp
// ✅ Non-allocating raycast
if (Physics.Raycast(origin, direction, out RaycastHit hit, maxDistance)) {
Debug.Log($"Hit: {hit.collider.name}");
}
// ✅ Multiple hits (non-allocating)
RaycastHit[] results = new RaycastHit[10];
int hitCount = Physics.RaycastNonAlloc(origin, direction, results, maxDistance);
for (int i = 0; i < hitCount; i++) {
Debug.Log($"Hit {i}: {results[i].collider.name}");
}
// ❌ Avoid: RaycastAll (allocates array every call)
RaycastHit[] hits = Physics.RaycastAll(origin, direction); // GC allocation!
```
### LayerMask for Selective Raycasting
```csharp
// ✅ Use LayerMask to filter collisions
int layerMask = 1 << LayerMask.NameToLayer("Enemy");
Physics.Raycast(origin, direction, out RaycastHit hit, maxDistance, layerMask);
```
---
## Physics Queries
### OverlapSphere (Check for nearby objects)
```csharp
// ✅ Non-allocating version
Collider[] results = new Collider[10];
int count = Physics.OverlapSphereNonAlloc(center, radius, results);
for (int i = 0; i < count; i++) {
// Process results[i]
}
```
### SphereCast (Thick raycast)
```csharp
// Useful for character controllers
if (Physics.SphereCast(origin, radius, direction, out RaycastHit hit, maxDistance)) {
// Hit something with a sphere-shaped ray
}
```
---
## Collision Events
### OnCollisionEnter / Stay / Exit
```csharp
void OnCollisionEnter(Collision collision) {
// Triggered when collision starts
Debug.Log($"Collided with {collision.gameObject.name}");
// Access contact points
foreach (ContactPoint contact in collision.contacts) {
Debug.DrawRay(contact.point, contact.normal, Color.red, 2f);
}
}
```
### OnTriggerEnter / Stay / Exit
```csharp
void OnTriggerEnter(Collider other) {
// Trigger collider (Is Trigger = true)
if (other.CompareTag("Pickup")) {
Destroy(other.gameObject);
}
}
```
---
## Character Controllers
### CharacterController Component
```csharp
CharacterController controller = GetComponent<CharacterController>();
// ✅ Move with collision detection
Vector3 move = transform.forward * speed * Time.deltaTime;
controller.Move(move);
// Apply gravity manually
if (!controller.isGrounded) {
velocity.y += Physics.gravity.y * Time.deltaTime;
}
controller.Move(velocity * Time.deltaTime);
```
---
## Physics Materials
### Friction & Bounciness
```csharp
// Create: Assets > Create > Physic Material
// Assign to collider: Collider > Material
// PhysicMaterial settings:
// - Dynamic Friction: 0.6 (sliding friction)
// - Static Friction: 0.6 (starting friction)
// - Bounciness: 0.0 - 1.0
// - Friction Combine: Average, Minimum, Maximum, Multiply
// - Bounce Combine: Average, Minimum, Maximum, Multiply
```
---
## Joints
### Fixed Joint (Attach two rigidbodies)
```csharp
FixedJoint joint = gameObject.AddComponent<FixedJoint>();
joint.connectedBody = otherRigidbody;
```
### Hinge Joint (Door, wheel)
```csharp
HingeJoint hinge = gameObject.AddComponent<HingeJoint>();
hinge.axis = Vector3.up; // Rotation axis
hinge.useLimits = true;
hinge.limits = new JointLimits { min = -90, max = 90 };
```
---
## Performance Optimization
### Physics Layer Collision Matrix
`Edit > Project Settings > Physics > Layer Collision Matrix`
- Disable unnecessary collision checks between layers
- Massive performance gain
### Fixed Timestep
`Edit > Project Settings > Time > Fixed Timestep`
- Default: 0.02 (50 FPS physics)
- Lower = more accurate, higher CPU cost
- Match game's target framerate if possible
### Simplified Collision Geometry
- Use primitive colliders (box, sphere, capsule) over mesh colliders
- Bake mesh colliders at build time, not runtime
---
## Common Patterns
### Ground Check (Character Controller)
```csharp
bool IsGrounded() {
float rayLength = 0.1f;
return Physics.Raycast(transform.position, Vector3.down, rayLength);
}
```
### Apply Explosion Force
```csharp
void ApplyExplosion(Vector3 explosionPos, float radius, float force) {
Collider[] colliders = Physics.OverlapSphere(explosionPos, radius);
foreach (Collider hit in colliders) {
Rigidbody rb = hit.GetComponent<Rigidbody>();
if (rb != null) {
rb.AddExplosionForce(force, explosionPos, radius);
}
}
}
```
---
## Debugging
### Physics Debugger (Unity 6+)
- `Window > Analysis > Physics Debugger`
- Visualize colliders, contacts, queries
### Gizmos
```csharp
void OnDrawGizmos() {
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, detectionRadius);
}
```
---
## Sources
- https://docs.unity3d.com/6000.0/Documentation/Manual/PhysicsOverview.html
- https://docs.unity3d.com/ScriptReference/Physics.html