添加 claude code game studios 到项目
This commit is contained in:
250
docs/engine-reference/unity/PLUGINS.md
Normal file
250
docs/engine-reference/unity/PLUGINS.md
Normal file
@@ -0,0 +1,250 @@
|
||||
# Unity 6.3 LTS — Optional Packages & Systems
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
|
||||
This document indexes **optional packages and systems** available in Unity 6.3 LTS.
|
||||
These are NOT part of the core engine but are commonly used for specific game types.
|
||||
|
||||
---
|
||||
|
||||
## How to Use This Guide
|
||||
|
||||
**✅ Detailed Documentation Available** - See `plugins/` directory for comprehensive guides
|
||||
**🟡 Brief Overview Only** - Links to official docs, use WebSearch for details
|
||||
**⚠️ Preview** - May have breaking changes in future versions
|
||||
**📦 Package Required** - Install via Package Manager
|
||||
|
||||
---
|
||||
|
||||
## Production-Ready Packages (Detailed Docs Available)
|
||||
|
||||
### ✅ Cinemachine
|
||||
- **Purpose:** Virtual camera system (dynamic cameras, cutscenes, camera blending)
|
||||
- **When to use:** 3rd person games, cinematics, complex camera behavior
|
||||
- **Knowledge Gap:** Cinemachine 3.0+ (Unity 6) has major API changes vs 2.x
|
||||
- **Status:** Production-Ready
|
||||
- **Package:** `com.unity.cinemachine` (Package Manager)
|
||||
- **Detailed Docs:** [plugins/cinemachine.md](plugins/cinemachine.md)
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.cinemachine@3.0/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
### ✅ Addressables
|
||||
- **Purpose:** Advanced asset management (async loading, remote content, memory control)
|
||||
- **When to use:** Large projects, DLC, remote content delivery
|
||||
- **Knowledge Gap:** Unity 6 improvements, better performance
|
||||
- **Status:** Production-Ready
|
||||
- **Package:** `com.unity.addressables` (Package Manager)
|
||||
- **Detailed Docs:** [plugins/addressables.md](plugins/addressables.md)
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.addressables@2.0/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
### ✅ DOTS / Entities (ECS)
|
||||
- **Purpose:** Data-Oriented Technology Stack (high-performance ECS for massive scale)
|
||||
- **When to use:** Games with 1000s of entities, RTS, simulations
|
||||
- **Knowledge Gap:** Entities 1.3+ (Unity 6) is production-ready, major rewrite from 0.x
|
||||
- **Status:** Production-Ready (as of Unity 6.3 LTS)
|
||||
- **Package:** `com.unity.entities` (Package Manager)
|
||||
- **Detailed Docs:** [plugins/dots-entities.md](plugins/dots-entities.md)
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
## Other Production-Ready Packages (Brief Overview)
|
||||
|
||||
### 🟡 Input System (Already Covered)
|
||||
- **Purpose:** Modern input handling (rebindable, cross-platform)
|
||||
- **Status:** Production-Ready (default in Unity 6)
|
||||
- **Package:** `com.unity.inputsystem`
|
||||
- **Docs:** See [modules/input.md](../modules/input.md)
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.inputsystem@1.11/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
### 🟡 UI Toolkit (Already Covered)
|
||||
- **Purpose:** Modern runtime UI (HTML/CSS-like, performant)
|
||||
- **Status:** Production-Ready (Unity 6)
|
||||
- **Package:** Built-in
|
||||
- **Docs:** See [modules/ui.md](../modules/ui.md)
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.ui@2.0/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Visual Effect Graph (VFX Graph)
|
||||
- **Purpose:** GPU-accelerated particle system (millions of particles)
|
||||
- **When to use:** Large-scale VFX, fire, smoke, magic, explosions
|
||||
- **Status:** Production-Ready
|
||||
- **Package:** `com.unity.visualeffectgraph` (URP/HDRP only)
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.visualeffectgraph@17.0/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Shader Graph
|
||||
- **Purpose:** Visual shader editor (node-based shader creation)
|
||||
- **When to use:** Custom shaders without HLSL coding
|
||||
- **Status:** Production-Ready
|
||||
- **Package:** `com.unity.shadergraph` (URP/HDRP)
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.shadergraph@17.0/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Timeline
|
||||
- **Purpose:** Cinematic sequencing (cutscenes, scripted events)
|
||||
- **When to use:** Story-driven games, cinematics, scripted sequences
|
||||
- **Status:** Production-Ready
|
||||
- **Package:** `com.unity.timeline` (built-in)
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.timeline@1.8/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Animation Rigging
|
||||
- **Purpose:** Runtime IK, procedural animation
|
||||
- **When to use:** Foot IK, aim offsets, procedural limb placement
|
||||
- **Status:** Production-Ready (Unity 6)
|
||||
- **Package:** `com.unity.animation.rigging`
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
### 🟡 ProBuilder
|
||||
- **Purpose:** In-editor 3D modeling (level prototyping, greyboxing)
|
||||
- **When to use:** Rapid prototyping, level blockout
|
||||
- **Status:** Production-Ready
|
||||
- **Package:** `com.unity.probuilder`
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.probuilder@6.0/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Netcode for GameObjects
|
||||
- **Purpose:** Official Unity multiplayer networking
|
||||
- **When to use:** Multiplayer games (client-server architecture)
|
||||
- **Status:** Production-Ready
|
||||
- **Package:** `com.unity.netcode.gameobjects`
|
||||
- **Official:** https://docs-multiplayer.unity3d.com/netcode/current/about/
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Burst Compiler
|
||||
- **Purpose:** LLVM-based compiler for C# Jobs (massive performance boost)
|
||||
- **When to use:** Performance-critical code, DOTS, Jobs System
|
||||
- **Status:** Production-Ready
|
||||
- **Package:** `com.unity.burst` (auto-installed with DOTS)
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.burst@1.8/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Jobs System
|
||||
- **Purpose:** Multi-threaded job scheduling (CPU parallelism)
|
||||
- **When to use:** Performance optimization, parallel processing
|
||||
- **Status:** Production-Ready
|
||||
- **Package:** Built-in
|
||||
- **Official:** https://docs.unity3d.com/Manual/JobSystem.html
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Mathematics
|
||||
- **Purpose:** SIMD math library (optimized for Burst)
|
||||
- **When to use:** DOTS, high-performance math
|
||||
- **Status:** Production-Ready
|
||||
- **Package:** `com.unity.mathematics`
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.mathematics@1.3/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
### 🟡 ML-Agents (Machine Learning)
|
||||
- **Purpose:** Train AI with reinforcement learning
|
||||
- **When to use:** Advanced AI training, procedural behavior
|
||||
- **Status:** Production-Ready
|
||||
- **Package:** `com.unity.ml-agents`
|
||||
- **Official:** https://github.com/Unity-Technologies/ml-agents
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Recorder
|
||||
- **Purpose:** Capture gameplay footage, screenshots, animation clips
|
||||
- **When to use:** Trailers, replays, debug recording
|
||||
- **Status:** Production-Ready
|
||||
- **Package:** `com.unity.recorder`
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.recorder@5.0/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
## Preview/Experimental Packages (Use with Caution)
|
||||
|
||||
### ⚠️ Splines
|
||||
- **Purpose:** Runtime spline creation and editing
|
||||
- **When to use:** Roads, paths, procedural content
|
||||
- **Status:** Production-Ready (Unity 6)
|
||||
- **Package:** `com.unity.splines`
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.splines@2.6/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ Muse (AI Assistant)
|
||||
- **Purpose:** AI-powered asset creation (textures, sprites, animations)
|
||||
- **Status:** Preview (Unity 6)
|
||||
- **Package:** `com.unity.muse.*`
|
||||
- **Official:** https://unity.com/products/muse
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ Sentis (Neural Network Inference)
|
||||
- **Purpose:** Run neural networks in Unity (AI inference)
|
||||
- **Status:** Preview
|
||||
- **Package:** `com.unity.sentis`
|
||||
- **Official:** https://docs.unity3d.com/Packages/com.unity.sentis@2.0/manual/index.html
|
||||
|
||||
---
|
||||
|
||||
## Deprecated Packages (Avoid for New Projects)
|
||||
|
||||
### ❌ UGUI (Canvas UI)
|
||||
- **Deprecated:** Still supported, but UI Toolkit recommended
|
||||
- **Use Instead:** UI Toolkit
|
||||
|
||||
---
|
||||
|
||||
### ❌ Legacy Particle System
|
||||
- **Deprecated:** Use Visual Effect Graph (VFX Graph)
|
||||
- **Use Instead:** VFX Graph
|
||||
|
||||
---
|
||||
|
||||
### ❌ Legacy Animation
|
||||
- **Deprecated:** Use Animator (Mecanim)
|
||||
- **Use Instead:** Animator Controller
|
||||
|
||||
---
|
||||
|
||||
## On-Demand WebSearch Strategy
|
||||
|
||||
For packages NOT listed above, use the following approach when users ask:
|
||||
|
||||
1. **WebSearch** for latest documentation: `"Unity 6.3 [package name]"`
|
||||
2. Verify if package is:
|
||||
- Post-cutoff (beyond May 2025 training data)
|
||||
- Preview vs Production-Ready
|
||||
- Still supported in Unity 6.3 LTS
|
||||
3. Optionally cache findings in `plugins/[package-name].md` for future reference
|
||||
|
||||
---
|
||||
|
||||
## Quick Decision Guide
|
||||
|
||||
**I need virtual cameras** → **Cinemachine**
|
||||
**I need async asset loading / DLC** → **Addressables**
|
||||
**I need 1000s of entities (RTS, sim)** → **DOTS/Entities**
|
||||
**I need modern input** → **Input System** (see modules/input.md)
|
||||
**I need GPU particles** → **Visual Effect Graph**
|
||||
**I need visual shaders** → **Shader Graph**
|
||||
**I need cinematics** → **Timeline**
|
||||
**I need runtime IK** → **Animation Rigging**
|
||||
**I need level prototyping** → **ProBuilder**
|
||||
**I need multiplayer** → **Netcode for GameObjects**
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-02-13
|
||||
**Engine Version:** Unity 6.3 LTS
|
||||
**LLM Knowledge Cutoff:** May 2025
|
||||
57
docs/engine-reference/unity/VERSION.md
Normal file
57
docs/engine-reference/unity/VERSION.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Unity Engine — Version Reference
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Engine Version** | Unity 6.3 LTS |
|
||||
| **Release Date** | December 2025 |
|
||||
| **Project Pinned** | 2026-02-13 |
|
||||
| **Last Docs Verified** | 2026-02-13 |
|
||||
| **LLM Knowledge Cutoff** | May 2025 |
|
||||
|
||||
## Knowledge Gap Warning
|
||||
|
||||
The LLM's training data likely covers Unity up to ~2022 LTS (2022.3). The entire
|
||||
Unity 6 release series (formerly Unity 2023 Tech Stream) introduced significant
|
||||
changes that the model does NOT know about. Always cross-reference this directory
|
||||
before suggesting Unity API calls.
|
||||
|
||||
## Post-Cutoff Version Timeline
|
||||
|
||||
| Version | Release | Risk Level | Key Theme |
|
||||
|---------|---------|------------|-----------|
|
||||
| 6.0 | Oct 2024 | HIGH | Unity 6 rebrand, new rendering features, Entities 1.3, DOTS improvements |
|
||||
| 6.1 | Nov 2024 | MEDIUM | Bug fixes, stability improvements |
|
||||
| 6.2 | Dec 2024 | MEDIUM | Performance optimizations, new input system improvements |
|
||||
| 6.3 LTS | Dec 2025 | HIGH | First LTS since 6.0, production-ready DOTS, enhanced graphics features |
|
||||
|
||||
## Major Changes from 2022 LTS to Unity 6.3 LTS
|
||||
|
||||
### Breaking Changes
|
||||
- **Entities/DOTS**: Major API overhaul in Entities 1.0+, complete redesign of ECS patterns
|
||||
- **Input System**: Legacy Input Manager deprecated, new Input System is default
|
||||
- **Rendering**: URP/HDRP significant upgrades, SRP Batcher improvements
|
||||
- **Addressables**: Asset management workflow changes
|
||||
- **Scripting**: C# 9 support, new API patterns
|
||||
|
||||
### New Features (Post-Cutoff)
|
||||
- **DOTS**: Production-ready Entity Component System (Entities 1.3+)
|
||||
- **Graphics**: Enhanced URP/HDRP pipelines, GPU Resident Drawer
|
||||
- **Multiplayer**: Netcode for GameObjects improvements
|
||||
- **UI Toolkit**: Production-ready for runtime UI (replaces UGUI for new projects)
|
||||
- **Async Asset Loading**: Improved Addressables performance
|
||||
- **Web**: WebGPU support
|
||||
|
||||
### Deprecated Systems
|
||||
- **Legacy Input Manager**: Use new Input System package
|
||||
- **Legacy Particle System**: Use Visual Effect Graph
|
||||
- **UGUI**: Still supported, but UI Toolkit recommended for new projects
|
||||
- **Old ECS (GameObjectEntity)**: Replaced by modern DOTS/Entities
|
||||
|
||||
## Verified Sources
|
||||
|
||||
- Official docs: https://docs.unity3d.com/6000.0/Documentation/Manual/index.html
|
||||
- Unity 6 release: https://unity.com/releases/unity-6
|
||||
- Unity 6.3 LTS announcement: https://unity.com/blog/unity-6-3-lts-is-now-available
|
||||
- Migration guide: https://docs.unity3d.com/6000.0/Documentation/Manual/upgrade-guides.html
|
||||
- Unity 6 support: https://unity.com/releases/unity-6/support
|
||||
- C# API reference: https://docs.unity3d.com/6000.0/Documentation/ScriptReference/index.html
|
||||
154
docs/engine-reference/unity/breaking-changes.md
Normal file
154
docs/engine-reference/unity/breaking-changes.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# Unity 6.3 LTS — Breaking Changes
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
|
||||
This document tracks breaking API changes and behavioral differences between Unity 2022 LTS
|
||||
(likely in model training) and Unity 6.3 LTS (current version). Organized by risk level.
|
||||
|
||||
## HIGH RISK — Will Break Existing Code
|
||||
|
||||
### Entities/DOTS API Complete Overhaul
|
||||
**Versions:** Entities 1.0+ (Unity 6.0+)
|
||||
|
||||
```csharp
|
||||
// ❌ OLD (pre-Unity 6, GameObjectEntity pattern)
|
||||
public class HealthComponent : ComponentData {
|
||||
public float Value;
|
||||
}
|
||||
|
||||
// ✅ NEW (Unity 6+, IComponentData)
|
||||
public struct HealthComponent : IComponentData {
|
||||
public float Value;
|
||||
}
|
||||
|
||||
// ❌ OLD: ComponentSystem
|
||||
public class DamageSystem : ComponentSystem { }
|
||||
|
||||
// ✅ NEW: ISystem (unmanaged, Burst-compatible)
|
||||
public partial struct DamageSystem : ISystem {
|
||||
public void OnCreate(ref SystemState state) { }
|
||||
public void OnUpdate(ref SystemState state) { }
|
||||
}
|
||||
```
|
||||
|
||||
**Migration:** Follow Unity's ECS migration guide. Major architectural changes required.
|
||||
|
||||
---
|
||||
|
||||
### Input System — Legacy Input Deprecated
|
||||
**Versions:** Unity 6.0+
|
||||
|
||||
```csharp
|
||||
// ❌ OLD: Input class (deprecated)
|
||||
if (Input.GetKeyDown(KeyCode.Space)) { }
|
||||
|
||||
// ✅ NEW: Input System package
|
||||
using UnityEngine.InputSystem;
|
||||
if (Keyboard.current.spaceKey.wasPressedThisFrame) { }
|
||||
```
|
||||
|
||||
**Migration:** Install Input System package, replace all `Input.*` calls with new API.
|
||||
|
||||
---
|
||||
|
||||
### URP/HDRP Renderer Feature API Changes
|
||||
**Versions:** Unity 6.0+
|
||||
|
||||
```csharp
|
||||
// ❌ OLD: ScriptableRenderPass.Execute signature
|
||||
public override void Execute(ScriptableRenderContext context, ref RenderingData data)
|
||||
|
||||
// ✅ NEW: Uses RenderGraph API
|
||||
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
|
||||
```
|
||||
|
||||
**Migration:** Update custom render passes to use RenderGraph API.
|
||||
|
||||
---
|
||||
|
||||
## MEDIUM RISK — Behavioral Changes
|
||||
|
||||
### Addressables — Asset Loading Returns
|
||||
**Versions:** Unity 6.2+
|
||||
|
||||
Asset loading failures now throw exceptions by default instead of returning null.
|
||||
Add proper exception handling or use `TryLoad` variants.
|
||||
|
||||
```csharp
|
||||
// ❌ OLD: Silent null on failure
|
||||
var handle = Addressables.LoadAssetAsync<Sprite>("key");
|
||||
var sprite = handle.Result; // null if failed
|
||||
|
||||
// ✅ NEW: Throws on failure, use try/catch or TryLoad
|
||||
try {
|
||||
var handle = Addressables.LoadAssetAsync<Sprite>("key");
|
||||
var sprite = await handle.Task;
|
||||
} catch (Exception e) {
|
||||
Debug.LogError($"Failed to load: {e}");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Physics — Default Solver Iterations Changed
|
||||
**Versions:** Unity 6.0+
|
||||
|
||||
Default solver iterations increased for better stability.
|
||||
Check `Physics.defaultSolverIterations` if you rely on old behavior.
|
||||
|
||||
---
|
||||
|
||||
## LOW RISK — Deprecations (Still Functional)
|
||||
|
||||
### UGUI (Legacy UI)
|
||||
**Status:** Deprecated but supported
|
||||
**Replacement:** UI Toolkit
|
||||
|
||||
UGUI still works but UI Toolkit is recommended for new projects.
|
||||
|
||||
---
|
||||
|
||||
### Legacy Particle System
|
||||
**Status:** Deprecated
|
||||
**Replacement:** Visual Effect Graph (VFX Graph)
|
||||
|
||||
---
|
||||
|
||||
### Old Animation System
|
||||
**Status:** Deprecated
|
||||
**Replacement:** Animator Controller (Mecanim)
|
||||
|
||||
---
|
||||
|
||||
## Platform-Specific Breaking Changes
|
||||
|
||||
### WebGL
|
||||
- **Unity 6.0+**: WebGPU is now the default (WebGL 2.0 fallback available)
|
||||
- Update shaders for WebGPU compatibility
|
||||
|
||||
### Android
|
||||
- **Unity 6.0+**: Minimum API level raised to 24 (Android 7.0)
|
||||
|
||||
### iOS
|
||||
- **Unity 6.0+**: Minimum deployment target raised to iOS 13
|
||||
|
||||
---
|
||||
|
||||
## Migration Checklist
|
||||
|
||||
When upgrading from 2022 LTS to Unity 6.3 LTS:
|
||||
|
||||
- [ ] Audit all DOTS/ECS code (complete rewrite likely needed)
|
||||
- [ ] Replace `Input` class with Input System package
|
||||
- [ ] Update custom render passes to RenderGraph API
|
||||
- [ ] Add exception handling to Addressables calls
|
||||
- [ ] Test physics behavior (solver iterations changed)
|
||||
- [ ] Consider migrating UGUI to UI Toolkit for new UI
|
||||
- [ ] Update WebGL shaders for WebGPU
|
||||
- [ ] Verify minimum platform versions (Android/iOS)
|
||||
|
||||
---
|
||||
|
||||
**Sources:**
|
||||
- https://docs.unity3d.com/6000.0/Documentation/Manual/upgrade-guides.html
|
||||
- https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/upgrade-guide.html
|
||||
334
docs/engine-reference/unity/current-best-practices.md
Normal file
334
docs/engine-reference/unity/current-best-practices.md
Normal file
@@ -0,0 +1,334 @@
|
||||
# Unity 6.3 LTS — Current Best Practices
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
|
||||
Modern Unity 6 patterns that may not be in the LLM's training data.
|
||||
These are production-ready recommendations as of Unity 6.3 LTS.
|
||||
|
||||
---
|
||||
|
||||
## Project Setup
|
||||
|
||||
### Use Unity 6.3 LTS for Production
|
||||
- **Tech Stream** (6.4+): Latest features, less stable
|
||||
- **LTS** (6.3): Production-ready, 2-year support (until Dec 2027)
|
||||
|
||||
### Choose the Right Render Pipeline
|
||||
- **URP (Universal)**: Mobile, cross-platform, good performance ✅ Recommended for most games
|
||||
- **HDRP (High Definition)**: High-end PC/console, photorealistic
|
||||
- **Built-in**: Deprecated, avoid for new projects
|
||||
|
||||
---
|
||||
|
||||
## Scripting
|
||||
|
||||
### Use C# 9+ Features (Unity 6 Supports C# 9)
|
||||
|
||||
```csharp
|
||||
// ✅ Record types for data
|
||||
public record PlayerData(string Name, int Level, float Health);
|
||||
|
||||
// ✅ Init-only properties
|
||||
public class Config {
|
||||
public string GameMode { get; init; }
|
||||
}
|
||||
|
||||
// ✅ Pattern matching
|
||||
var result = enemy switch {
|
||||
Boss boss => boss.Enrage(),
|
||||
Minion minion => minion.Flee(),
|
||||
_ => null
|
||||
};
|
||||
```
|
||||
|
||||
### Async/Await for Asset Loading
|
||||
|
||||
```csharp
|
||||
// ✅ Modern async pattern
|
||||
public async Task<GameObject> LoadEnemyAsync(string key) {
|
||||
var handle = Addressables.LoadAssetAsync<GameObject>(key);
|
||||
return await handle.Task;
|
||||
}
|
||||
```
|
||||
|
||||
### Use Source Generators for Serialization (Unity 6+)
|
||||
|
||||
```csharp
|
||||
// ✅ Source-generated serialization (faster, less reflection)
|
||||
[GenerateSerializer]
|
||||
public partial struct PlayerStats : IComponentData {
|
||||
public int Health;
|
||||
public int Mana;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DOTS/ECS (Production-Ready in Unity 6.3 LTS)
|
||||
|
||||
### Use ISystem (Not ComponentSystem)
|
||||
|
||||
```csharp
|
||||
// ✅ Modern unmanaged ISystem (Burst-compatible)
|
||||
public partial struct MovementSystem : ISystem {
|
||||
public void OnCreate(ref SystemState state) { }
|
||||
|
||||
public void OnUpdate(ref SystemState state) {
|
||||
foreach (var (transform, speed) in
|
||||
SystemAPI.Query<RefRW<LocalTransform>, RefRO<MoveSpeed>>()) {
|
||||
transform.ValueRW.Position += speed.ValueRO.Value * SystemAPI.Time.DeltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Use IJobEntity for Parallel Jobs
|
||||
|
||||
```csharp
|
||||
// ✅ IJobEntity (replaces IJobForEach)
|
||||
[BurstCompile]
|
||||
public partial struct DamageJob : IJobEntity {
|
||||
public float DeltaTime;
|
||||
|
||||
void Execute(ref Health health, in DamageOverTime dot) {
|
||||
health.Value -= dot.DamagePerSecond * DeltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule it
|
||||
var job = new DamageJob { DeltaTime = SystemAPI.Time.DeltaTime };
|
||||
job.ScheduleParallel();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input
|
||||
|
||||
### Use Input System Package (Not Legacy Input)
|
||||
|
||||
```csharp
|
||||
// ✅ Input Actions (rebindable, cross-platform)
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
public class PlayerInput : MonoBehaviour {
|
||||
private PlayerControls controls;
|
||||
|
||||
void Awake() {
|
||||
controls = new PlayerControls();
|
||||
controls.Gameplay.Jump.performed += ctx => Jump();
|
||||
}
|
||||
|
||||
void OnEnable() => controls.Enable();
|
||||
void OnDisable() => controls.Disable();
|
||||
}
|
||||
```
|
||||
|
||||
Create Input Actions asset in editor, generate C# class via inspector.
|
||||
|
||||
---
|
||||
|
||||
## UI
|
||||
|
||||
### Use UI Toolkit for Runtime UI (Production-Ready in Unity 6)
|
||||
|
||||
```csharp
|
||||
// ✅ UI Toolkit (replaces UGUI for new projects)
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
public class MainMenu : MonoBehaviour {
|
||||
void OnEnable() {
|
||||
var root = GetComponent<UIDocument>().rootVisualElement;
|
||||
|
||||
var playButton = root.Q<Button>("play-button");
|
||||
playButton.clicked += StartGame;
|
||||
|
||||
var scoreLabel = root.Q<Label>("score");
|
||||
scoreLabel.text = $"High Score: {PlayerPrefs.GetInt("HighScore")}";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**UXML** (UI structure) + **USS** (styling) = HTML/CSS-like workflow.
|
||||
|
||||
---
|
||||
|
||||
## Asset Management
|
||||
|
||||
### Use Addressables (Not Resources)
|
||||
|
||||
```csharp
|
||||
// ✅ Addressables (async, memory-efficient)
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
public async Task SpawnEnemyAsync(string enemyKey) {
|
||||
var handle = Addressables.InstantiateAsync(enemyKey);
|
||||
var enemy = await handle.Task;
|
||||
|
||||
// Cleanup: release when destroyed
|
||||
Addressables.ReleaseInstance(enemy);
|
||||
}
|
||||
```
|
||||
|
||||
**Benefits:** Async loading, remote content delivery, better memory control.
|
||||
|
||||
---
|
||||
|
||||
## Rendering
|
||||
|
||||
### Use RenderGraph API for Custom Passes (URP/HDRP)
|
||||
|
||||
```csharp
|
||||
// ✅ RenderGraph API (Unity 6+)
|
||||
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) {
|
||||
using (var builder = renderGraph.AddRasterRenderPass<PassData>("My Pass", out var passData)) {
|
||||
// Setup pass
|
||||
builder.SetRenderFunc((PassData data, RasterGraphContext context) => {
|
||||
// Execute commands
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Replaces:** Old `CommandBuffer.Execute()` pattern.
|
||||
|
||||
---
|
||||
|
||||
## Performance
|
||||
|
||||
### Use Burst Compiler + Jobs System
|
||||
|
||||
```csharp
|
||||
// ✅ Burst-compiled job (massive performance gain)
|
||||
[BurstCompile]
|
||||
struct ParticleUpdateJob : IJobParallelFor {
|
||||
public NativeArray<float3> Positions;
|
||||
public NativeArray<float3> Velocities;
|
||||
public float DeltaTime;
|
||||
|
||||
public void Execute(int index) {
|
||||
Positions[index] += Velocities[index] * DeltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule
|
||||
var job = new ParticleUpdateJob {
|
||||
Positions = positions,
|
||||
Velocities = velocities,
|
||||
DeltaTime = Time.deltaTime
|
||||
};
|
||||
job.Schedule(positions.Length, 64).Complete();
|
||||
```
|
||||
|
||||
**20-100x faster** than equivalent C# code.
|
||||
|
||||
---
|
||||
|
||||
### Use GPU Instancing for Repeated Objects
|
||||
|
||||
```csharp
|
||||
// ✅ GPU Instancing (thousands of objects, minimal draw calls)
|
||||
Graphics.RenderMeshInstanced(
|
||||
new RenderParams(material),
|
||||
mesh,
|
||||
0,
|
||||
matrices // NativeArray<Matrix4x4>
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Memory Management
|
||||
|
||||
### Use NativeContainers (Not Managed Arrays in Jobs)
|
||||
|
||||
```csharp
|
||||
// ✅ NativeArray (no GC, Burst-compatible)
|
||||
NativeArray<int> data = new NativeArray<int>(1000, Allocator.TempJob);
|
||||
// ... use in job
|
||||
data.Dispose(); // Manual cleanup required
|
||||
|
||||
// ✅ Or use using statement
|
||||
using var data = new NativeArray<int>(1000, Allocator.TempJob);
|
||||
// Auto-disposed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Multiplayer
|
||||
|
||||
### Use Netcode for GameObjects (Official)
|
||||
|
||||
```csharp
|
||||
// ✅ Unity's official netcode
|
||||
using Unity.Netcode;
|
||||
|
||||
public class Player : NetworkBehaviour {
|
||||
private NetworkVariable<int> health = new NetworkVariable<int>(100);
|
||||
|
||||
[ServerRpc]
|
||||
public void TakeDamageServerRpc(int damage) {
|
||||
health.Value -= damage;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Replaces:** UNet (deprecated), MLAPI (renamed to Netcode for GameObjects).
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
### Use Unity Test Framework (NUnit-based)
|
||||
|
||||
```csharp
|
||||
// ✅ Play Mode Test
|
||||
[UnityTest]
|
||||
public IEnumerator Player_TakesDamage_HealthDecreases() {
|
||||
var player = new GameObject().AddComponent<Player>();
|
||||
player.Health = 100;
|
||||
|
||||
player.TakeDamage(25);
|
||||
yield return null; // Wait one frame
|
||||
|
||||
Assert.AreEqual(75, player.Health);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Use Logging Best Practices
|
||||
|
||||
```csharp
|
||||
// ✅ Structured logging (Unity 6+)
|
||||
using UnityEngine;
|
||||
|
||||
Debug.Log($"Player {playerName} scored {score} points");
|
||||
|
||||
// ✅ Conditional compilation for debug code
|
||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||
Debug.DrawRay(transform.position, direction, Color.red);
|
||||
#endif
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary: Unity 6 Tech Stack
|
||||
|
||||
| Feature | Use This (2026) | Avoid This (Legacy) |
|
||||
|---------|------------------|----------------------|
|
||||
| **Input** | Input System package | `Input` class |
|
||||
| **UI** | UI Toolkit | UGUI (Canvas) |
|
||||
| **ECS** | ISystem + IJobEntity | ComponentSystem |
|
||||
| **Rendering** | URP + RenderGraph | Built-in pipeline |
|
||||
| **Assets** | Addressables | Resources |
|
||||
| **Jobs** | Burst + IJobParallelFor | Coroutines for heavy work |
|
||||
| **Multiplayer** | Netcode for GameObjects | UNet |
|
||||
|
||||
---
|
||||
|
||||
**Sources:**
|
||||
- https://docs.unity3d.com/6000.0/Documentation/Manual/BestPracticeGuides.html
|
||||
- https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/index.html
|
||||
- https://docs.unity3d.com/Packages/com.unity.inputsystem@1.11/manual/index.html
|
||||
156
docs/engine-reference/unity/deprecated-apis.md
Normal file
156
docs/engine-reference/unity/deprecated-apis.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# Unity 6.3 LTS — Deprecated APIs
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
|
||||
Quick lookup table for deprecated APIs and their replacements.
|
||||
Format: **Don't use X** → **Use Y instead**
|
||||
|
||||
---
|
||||
|
||||
## Input
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| `Input.GetKey()` | `Keyboard.current[Key.X].isPressed` | New Input System |
|
||||
| `Input.GetKeyDown()` | `Keyboard.current[Key.X].wasPressedThisFrame` | New Input System |
|
||||
| `Input.GetMouseButton()` | `Mouse.current.leftButton.isPressed` | New Input System |
|
||||
| `Input.GetAxis()` | `InputAction` callbacks | New Input System |
|
||||
| `Input.mousePosition` | `Mouse.current.position.ReadValue()` | New Input System |
|
||||
|
||||
**Migration:** Install `com.unity.inputsystem` package.
|
||||
|
||||
---
|
||||
|
||||
## UI
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| `Canvas` (UGUI) | `UIDocument` (UI Toolkit) | UI Toolkit is now production-ready |
|
||||
| `Text` component | `TextMeshPro` or UI Toolkit `Label` | Better rendering, fewer draw calls |
|
||||
| `Image` component | UI Toolkit `VisualElement` with background | More flexible styling |
|
||||
|
||||
**Migration:** UGUI still works, but UI Toolkit is recommended for new projects.
|
||||
|
||||
---
|
||||
|
||||
## DOTS/Entities
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| `ComponentSystem` | `ISystem` (unmanaged) | Entities 1.0+ complete rewrite |
|
||||
| `JobComponentSystem` | `ISystem` with `IJobEntity` | Burst-compatible |
|
||||
| `GameObjectEntity` | Pure ECS workflow | No GameObject conversion |
|
||||
| `EntityManager.CreateEntity()` (old signature) | `EntityManager.CreateEntity(EntityArchetype)` | Explicit archetype |
|
||||
| `ComponentDataFromEntity<T>` | `ComponentLookup<T>` | Entities 1.0+ rename |
|
||||
|
||||
**Migration:** See Entities package migration guide. Major refactor required.
|
||||
|
||||
---
|
||||
|
||||
## Rendering
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| `CommandBuffer.DrawMesh()` | RenderGraph API | URP/HDRP render passes |
|
||||
| `OnPreRender()` / `OnPostRender()` | `RenderPipelineManager` callbacks | SRP compatibility |
|
||||
| `Camera.SetReplacementShader()` | Custom render pass | Not supported in SRP |
|
||||
|
||||
---
|
||||
|
||||
## Physics
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| `Physics.RaycastAll()` | `Physics.RaycastNonAlloc()` | Avoid GC allocations |
|
||||
| `Rigidbody.velocity` (direct write) | `Rigidbody.AddForce()` | Better physics stability |
|
||||
|
||||
---
|
||||
|
||||
## Asset Loading
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| `Resources.Load()` | Addressables | Better memory control, async loading |
|
||||
| Synchronous asset loading | `Addressables.LoadAssetAsync()` | Non-blocking |
|
||||
|
||||
---
|
||||
|
||||
## Animation
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| Legacy Animation component | Animator Controller | Mecanim system |
|
||||
| `Animation.Play()` | `Animator.Play()` | State machine control |
|
||||
|
||||
---
|
||||
|
||||
## Particles
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| Legacy Particle System | Visual Effect Graph | GPU-accelerated, more performant |
|
||||
|
||||
---
|
||||
|
||||
## Scripting
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| `WWW` class | `UnityWebRequest` | Modern async networking |
|
||||
| `Application.LoadLevel()` | `SceneManager.LoadScene()` | Scene management |
|
||||
|
||||
---
|
||||
|
||||
## Platform-Specific
|
||||
|
||||
### WebGL
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| WebGL 1.0 | WebGL 2.0 or WebGPU | Unity 6+ defaults to WebGPU |
|
||||
|
||||
---
|
||||
|
||||
## Quick Migration Patterns
|
||||
|
||||
### Input Example
|
||||
```csharp
|
||||
// ❌ Deprecated
|
||||
if (Input.GetKeyDown(KeyCode.Space)) {
|
||||
Jump();
|
||||
}
|
||||
|
||||
// ✅ New Input System
|
||||
using UnityEngine.InputSystem;
|
||||
if (Keyboard.current.spaceKey.wasPressedThisFrame) {
|
||||
Jump();
|
||||
}
|
||||
```
|
||||
|
||||
### Asset Loading Example
|
||||
```csharp
|
||||
// ❌ Deprecated
|
||||
var prefab = Resources.Load<GameObject>("Enemies/Goblin");
|
||||
|
||||
// ✅ Addressables
|
||||
var handle = Addressables.LoadAssetAsync<GameObject>("Enemies/Goblin");
|
||||
await handle.Task;
|
||||
var prefab = handle.Result;
|
||||
```
|
||||
|
||||
### UI Example
|
||||
```csharp
|
||||
// ❌ Deprecated (UGUI)
|
||||
GetComponent<Text>().text = "Score: 100";
|
||||
|
||||
// ✅ TextMeshPro
|
||||
GetComponent<TextMeshProUGUI>().text = "Score: 100";
|
||||
|
||||
// ✅ UI Toolkit
|
||||
rootVisualElement.Q<Label>("score-label").text = "Score: 100";
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Sources:**
|
||||
- https://docs.unity3d.com/6000.0/Documentation/Manual/deprecated-features.html
|
||||
- https://docs.unity3d.com/Packages/com.unity.inputsystem@1.11/manual/Migration.html
|
||||
289
docs/engine-reference/unity/modules/animation.md
Normal file
289
docs/engine-reference/unity/modules/animation.md
Normal file
@@ -0,0 +1,289 @@
|
||||
# Unity 6.3 — Animation Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** Unity 6 animation improvements, Timeline enhancements
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Unity 6.3 animation systems:
|
||||
- **Animator Controller (Mecanim)**: State machine-based (RECOMMENDED)
|
||||
- **Timeline**: Cinematic sequences, cutscenes
|
||||
- **Animation Rigging**: Procedural runtime animation
|
||||
- **Legacy Animation**: Deprecated, avoid
|
||||
|
||||
---
|
||||
|
||||
## Key Changes from 2022 LTS
|
||||
|
||||
### Animation Rigging Package (Production-Ready in Unity 6)
|
||||
|
||||
```csharp
|
||||
// Install: Package Manager > Animation Rigging
|
||||
// Runtime IK, aim constraints, procedural animation
|
||||
```
|
||||
|
||||
### Timeline Improvements
|
||||
- Better performance
|
||||
- More track types
|
||||
- Improved signal system
|
||||
|
||||
---
|
||||
|
||||
## Animator Controller (Mecanim)
|
||||
|
||||
### Basic Setup
|
||||
|
||||
```csharp
|
||||
// Create: Assets > Create > Animator Controller
|
||||
// Add to GameObject: Add Component > Animator
|
||||
// Assign Controller: Animator > Controller = YourAnimatorController
|
||||
```
|
||||
|
||||
### State Transitions
|
||||
|
||||
```csharp
|
||||
Animator animator = GetComponent<Animator>();
|
||||
|
||||
// ✅ Trigger transition
|
||||
animator.SetTrigger("Jump");
|
||||
|
||||
// ✅ Bool parameter
|
||||
animator.SetBool("IsRunning", true);
|
||||
|
||||
// ✅ Float parameter (blend trees)
|
||||
animator.SetFloat("Speed", currentSpeed);
|
||||
|
||||
// ✅ Integer parameter
|
||||
animator.SetInteger("WeaponType", 2);
|
||||
```
|
||||
|
||||
### Animation Layers
|
||||
- **Base Layer**: Default animations (locomotion)
|
||||
- **Override Layers**: Replace base layer (e.g., weapon swap)
|
||||
- **Additive Layers**: Add on top of base (e.g., breathing, aim offset)
|
||||
|
||||
```csharp
|
||||
// Set layer weight (0-1)
|
||||
animator.SetLayerWeight(1, 0.5f); // 50% blend
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Blend Trees
|
||||
|
||||
### 1D Blend Tree (Speed blending)
|
||||
|
||||
```csharp
|
||||
// Idle (Speed = 0) → Walk (Speed = 0.5) → Run (Speed = 1.0)
|
||||
animator.SetFloat("Speed", moveSpeed);
|
||||
```
|
||||
|
||||
### 2D Blend Tree (Directional movement)
|
||||
|
||||
```csharp
|
||||
// X-axis: Strafe (-1 to 1)
|
||||
// Y-axis: Forward/Back (-1 to 1)
|
||||
animator.SetFloat("MoveX", input.x);
|
||||
animator.SetFloat("MoveY", input.y);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Animation Events
|
||||
|
||||
### Trigger Events from Animation Clips
|
||||
|
||||
```csharp
|
||||
// Add in Animation window: Right-click timeline > Add Animation Event
|
||||
// Must have matching method on GameObject:
|
||||
|
||||
public void OnFootstep() {
|
||||
// Play footstep sound
|
||||
AudioSource.PlayClipAtPoint(footstepClip, transform.position);
|
||||
}
|
||||
|
||||
public void OnAttackHit() {
|
||||
// Deal damage
|
||||
DealDamageInFrontOfPlayer();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Root Motion
|
||||
|
||||
### Character Movement via Animation
|
||||
|
||||
```csharp
|
||||
Animator animator = GetComponent<Animator>();
|
||||
animator.applyRootMotion = true; // Move character based on animation
|
||||
|
||||
void OnAnimatorMove() {
|
||||
// Custom root motion handling
|
||||
transform.position += animator.deltaPosition;
|
||||
transform.rotation *= animator.deltaRotation;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Animation Rigging (Unity 6+)
|
||||
|
||||
### IK (Inverse Kinematics)
|
||||
|
||||
```csharp
|
||||
// Install: Package Manager > Animation Rigging
|
||||
// Add: Rig Builder component + Rig GameObject
|
||||
|
||||
// Two Bone IK (Arm/Leg)
|
||||
// - Add Two Bone IK Constraint
|
||||
// - Assign Tip (hand/foot), Mid (elbow/knee), Root (shoulder/hip)
|
||||
// - Set Target (where hand/foot should reach)
|
||||
|
||||
// Runtime control:
|
||||
TwoBoneIKConstraint ikConstraint = rig.GetComponentInChildren<TwoBoneIKConstraint>();
|
||||
ikConstraint.data.target = targetTransform;
|
||||
ikConstraint.weight = 1f; // 0-1 blend
|
||||
```
|
||||
|
||||
### Aim Constraint (Look At)
|
||||
|
||||
```csharp
|
||||
// Character looks at target
|
||||
MultiAimConstraint aimConstraint = rig.GetComponentInChildren<MultiAimConstraint>();
|
||||
aimConstraint.data.sourceObjects[0] = new WeightedTransform(targetTransform, 1f);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Timeline (Cutscenes)
|
||||
|
||||
### Basic Timeline Setup
|
||||
|
||||
```csharp
|
||||
// Create: Assets > Create > Timeline
|
||||
// Add to GameObject: Add Component > Playable Director
|
||||
// Assign Timeline: Playable Director > Playable = YourTimeline
|
||||
|
||||
// Play from script:
|
||||
PlayableDirector director = GetComponent<PlayableDirector>();
|
||||
director.Play();
|
||||
```
|
||||
|
||||
### Timeline Tracks
|
||||
- **Activation Track**: Enable/disable GameObjects
|
||||
- **Animation Track**: Play animations on Animator
|
||||
- **Audio Track**: Synchronized audio playback
|
||||
- **Cinemachine Track**: Camera movement
|
||||
- **Signal Track**: Trigger events at specific times
|
||||
|
||||
### Signal System (Events)
|
||||
|
||||
```csharp
|
||||
// Create Signal Asset: Assets > Create > Signals > Signal
|
||||
// Add Signal Emitter to Timeline track
|
||||
// Add Signal Receiver component to GameObject
|
||||
|
||||
public class CutsceneEvents : MonoBehaviour {
|
||||
public void OnDialogueStart() {
|
||||
// Triggered by signal
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Animation Playback Control
|
||||
|
||||
### Play Animation Directly (No State Machine)
|
||||
|
||||
```csharp
|
||||
// ✅ CrossFade (smooth transition)
|
||||
animator.CrossFade("Attack", 0.2f); // 0.2s transition
|
||||
|
||||
// ✅ Play (instant)
|
||||
animator.Play("Idle");
|
||||
|
||||
// ❌ Avoid: Legacy Animation component
|
||||
Animation anim = GetComponent<Animation>(); // DEPRECATED
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Animation Curves
|
||||
|
||||
### Custom Property Animation
|
||||
|
||||
```csharp
|
||||
// In Animation window: Add Property > Custom Component > Your Script > Your Float
|
||||
|
||||
public class WeaponTrail : MonoBehaviour {
|
||||
public float trailIntensity; // Animated by clip
|
||||
|
||||
void Update() {
|
||||
// Intensity controlled by animation curve
|
||||
trailRenderer.startWidth = trailIntensity;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Culling
|
||||
- `Animator > Culling Mode`:
|
||||
- **Always Animate**: Always update (expensive)
|
||||
- **Cull Update Transforms**: Stop updating bones when off-screen (RECOMMENDED)
|
||||
- **Cull Completely**: Stop all animation when off-screen
|
||||
|
||||
### LOD (Level of Detail)
|
||||
- Simpler animations for distant characters
|
||||
- Reduce skeleton bone count for LOD meshes
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Check if Animation Finished
|
||||
|
||||
```csharp
|
||||
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
||||
if (stateInfo.IsName("Attack") && stateInfo.normalizedTime >= 1.0f) {
|
||||
// Attack animation finished
|
||||
}
|
||||
```
|
||||
|
||||
### Override Animation Speed
|
||||
|
||||
```csharp
|
||||
animator.speed = 1.5f; // 150% speed
|
||||
```
|
||||
|
||||
### Get Current Animation Name
|
||||
|
||||
```csharp
|
||||
AnimatorClipInfo[] clipInfo = animator.GetCurrentAnimatorClipInfo(0);
|
||||
string currentClip = clipInfo[0].clip.name;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Animator Window
|
||||
- `Window > Animation > Animator`
|
||||
- Visualize state machine, see active state
|
||||
|
||||
### Animation Window
|
||||
- `Window > Animation > Animation`
|
||||
- Edit animation clips, add events
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unity3d.com/6000.0/Documentation/Manual/AnimationOverview.html
|
||||
- https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/index.html
|
||||
- https://docs.unity3d.com/Packages/com.unity.timeline@1.8/manual/index.html
|
||||
284
docs/engine-reference/unity/modules/audio.md
Normal file
284
docs/engine-reference/unity/modules/audio.md
Normal file
@@ -0,0 +1,284 @@
|
||||
# Unity 6.3 — Audio Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** Unity 6 audio mixer improvements
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Unity 6.3 audio systems:
|
||||
- **AudioSource**: Play sounds on GameObjects
|
||||
- **Audio Mixer**: Mix, effect processing, dynamic mixing
|
||||
- **Spatial Audio**: 3D positioned sound
|
||||
|
||||
---
|
||||
|
||||
## Basic Audio Playback
|
||||
|
||||
### AudioSource Component
|
||||
|
||||
```csharp
|
||||
AudioSource audioSource = GetComponent<AudioSource>();
|
||||
|
||||
// ✅ Play
|
||||
audioSource.Play();
|
||||
|
||||
// ✅ Play with delay
|
||||
audioSource.PlayDelayed(0.5f); // 0.5 seconds
|
||||
|
||||
// ✅ Play one-shot (doesn't interrupt current sound)
|
||||
audioSource.PlayOneShot(clip);
|
||||
|
||||
// ✅ Stop
|
||||
audioSource.Stop();
|
||||
|
||||
// ✅ Pause/Resume
|
||||
audioSource.Pause();
|
||||
audioSource.UnPause();
|
||||
```
|
||||
|
||||
### Play Sound at Position (Static Method)
|
||||
|
||||
```csharp
|
||||
// ✅ Quick 3D sound playback (auto-destroys when done)
|
||||
AudioSource.PlayClipAtPoint(clip, transform.position);
|
||||
|
||||
// ✅ With volume
|
||||
AudioSource.PlayClipAtPoint(clip, transform.position, 0.7f);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3D Spatial Audio
|
||||
|
||||
### AudioSource 3D Settings
|
||||
|
||||
```csharp
|
||||
AudioSource source = GetComponent<AudioSource>();
|
||||
|
||||
// Spatial Blend: 0 = 2D, 1 = 3D
|
||||
source.spatialBlend = 1.0f; // Fully 3D
|
||||
|
||||
// Doppler effect (pitch shift based on velocity)
|
||||
source.dopplerLevel = 1.0f;
|
||||
|
||||
// Distance attenuation
|
||||
source.minDistance = 1f; // Full volume within this distance
|
||||
source.maxDistance = 50f; // Inaudible beyond this distance
|
||||
source.rolloffMode = AudioRolloffMode.Logarithmic; // Natural falloff
|
||||
```
|
||||
|
||||
### Volume Rolloff Curves
|
||||
- **Logarithmic**: Natural, realistic (RECOMMENDED)
|
||||
- **Linear**: Steady decrease
|
||||
- **Custom**: Define your own curve
|
||||
|
||||
---
|
||||
|
||||
## Audio Mixer (Advanced Mixing)
|
||||
|
||||
### Setup Audio Mixer
|
||||
|
||||
1. `Assets > Create > Audio Mixer`
|
||||
2. Open mixer: `Window > Audio > Audio Mixer`
|
||||
3. Create groups: Master > SFX, Music, Dialogue
|
||||
|
||||
### Assign AudioSource to Mixer Group
|
||||
|
||||
```csharp
|
||||
using UnityEngine.Audio;
|
||||
|
||||
public AudioMixerGroup sfxGroup;
|
||||
|
||||
void Start() {
|
||||
AudioSource source = GetComponent<AudioSource>();
|
||||
source.outputAudioMixerGroup = sfxGroup; // Route to SFX group
|
||||
}
|
||||
```
|
||||
|
||||
### Control Mixer from Code
|
||||
|
||||
```csharp
|
||||
using UnityEngine.Audio;
|
||||
|
||||
public AudioMixer audioMixer;
|
||||
|
||||
// ✅ Set volume (exposed parameter)
|
||||
audioMixer.SetFloat("MusicVolume", -10f); // dB (-80 to 0)
|
||||
|
||||
// ✅ Get volume
|
||||
audioMixer.GetFloat("MusicVolume", out float volume);
|
||||
|
||||
// Convert linear (0-1) to dB
|
||||
float volumeDB = Mathf.Log10(volumeLinear) * 20f;
|
||||
audioMixer.SetFloat("MusicVolume", volumeDB);
|
||||
```
|
||||
|
||||
### Expose Mixer Parameters
|
||||
In Audio Mixer window:
|
||||
1. Right-click parameter (e.g., Volume)
|
||||
2. "Expose 'Volume' to script"
|
||||
3. Rename in "Exposed Parameters" tab (e.g., "MusicVolume")
|
||||
|
||||
---
|
||||
|
||||
## Audio Effects
|
||||
|
||||
### Add Effects to Mixer Groups
|
||||
|
||||
In Audio Mixer:
|
||||
- Click group (e.g., SFX)
|
||||
- Click "Add Effect"
|
||||
- Choose: Reverb, Echo, Low Pass, High Pass, Distortion, etc.
|
||||
|
||||
### Duck Music During Dialogue (Sidechain)
|
||||
|
||||
```csharp
|
||||
// Setup in Audio Mixer:
|
||||
// 1. Create "Duck Volume" snapshot
|
||||
// 2. Lower music volume in that snapshot
|
||||
// 3. Transition to snapshot when dialogue plays
|
||||
|
||||
public AudioMixerSnapshot normalSnapshot;
|
||||
public AudioMixerSnapshot duckedSnapshot;
|
||||
|
||||
public void PlayDialogue(AudioClip clip) {
|
||||
duckedSnapshot.TransitionTo(0.5f); // 0.5s transition
|
||||
audioSource.PlayOneShot(clip);
|
||||
Invoke(nameof(RestoreMusic), clip.length);
|
||||
}
|
||||
|
||||
void RestoreMusic() {
|
||||
normalSnapshot.TransitionTo(1.0f); // 1s transition back
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Audio Performance
|
||||
|
||||
### Optimize Audio Loading
|
||||
|
||||
```csharp
|
||||
// Audio Import Settings (Inspector):
|
||||
// - Load Type:
|
||||
// - Decompress On Load: Small clips (SFX), loads fully into memory
|
||||
// - Compressed In Memory: Medium clips, decompressed at runtime (RECOMMENDED)
|
||||
// - Streaming: Large clips (music), streamed from disk
|
||||
|
||||
// Compression Format:
|
||||
// - PCM: Uncompressed, highest quality, largest size
|
||||
// - ADPCM: 3.5x compression, good for SFX (RECOMMENDED for SFX)
|
||||
// - Vorbis/MP3: High compression, good for music (RECOMMENDED for music)
|
||||
```
|
||||
|
||||
### Preload Audio
|
||||
|
||||
```csharp
|
||||
// Preload audio clip before playing (avoid stutter)
|
||||
audioSource.clip.LoadAudioData();
|
||||
|
||||
// Check if loaded
|
||||
if (audioSource.clip.loadState == AudioDataLoadState.Loaded) {
|
||||
audioSource.Play();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Music Systems
|
||||
|
||||
### Crossfade Between Tracks
|
||||
|
||||
```csharp
|
||||
public IEnumerator CrossfadeMusic(AudioSource from, AudioSource to, float duration) {
|
||||
float elapsed = 0f;
|
||||
to.Play();
|
||||
|
||||
while (elapsed < duration) {
|
||||
elapsed += Time.deltaTime;
|
||||
float t = elapsed / duration;
|
||||
|
||||
from.volume = Mathf.Lerp(1f, 0f, t);
|
||||
to.volume = Mathf.Lerp(0f, 1f, t);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
from.Stop();
|
||||
}
|
||||
```
|
||||
|
||||
### Seamless Music Looping
|
||||
|
||||
```csharp
|
||||
// Audio Import Settings:
|
||||
// - Check "Loop" for seamless music loops
|
||||
audioSource.loop = true;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Random Pitch Variation (Avoid Repetition)
|
||||
|
||||
```csharp
|
||||
void PlaySoundWithVariation(AudioClip clip) {
|
||||
AudioSource source = GetComponent<AudioSource>();
|
||||
source.pitch = Random.Range(0.9f, 1.1f); // ±10% pitch variation
|
||||
source.PlayOneShot(clip);
|
||||
}
|
||||
```
|
||||
|
||||
### Footstep Sounds (Random from Array)
|
||||
|
||||
```csharp
|
||||
public AudioClip[] footstepClips;
|
||||
|
||||
void PlayFootstep() {
|
||||
AudioClip clip = footstepClips[Random.Range(0, footstepClips.Length)];
|
||||
AudioSource.PlayClipAtPoint(clip, transform.position, 0.5f);
|
||||
}
|
||||
```
|
||||
|
||||
### Check if Sound is Playing
|
||||
|
||||
```csharp
|
||||
if (audioSource.isPlaying) {
|
||||
// Sound is currently playing
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Audio Listener
|
||||
|
||||
### Single Listener Rule
|
||||
- Only ONE `AudioListener` should be active at a time
|
||||
- Usually attached to Main Camera
|
||||
|
||||
```csharp
|
||||
// Disable extra listeners
|
||||
AudioListener listener = GetComponent<AudioListener>();
|
||||
listener.enabled = false;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Audio Window
|
||||
- `Window > Audio > Audio Mixer`
|
||||
- Visualize levels, test snapshots
|
||||
|
||||
### Audio Settings
|
||||
- `Edit > Project Settings > Audio`
|
||||
- Global volume, DSP buffer size, speaker mode
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unity3d.com/6000.0/Documentation/Manual/Audio.html
|
||||
- https://docs.unity3d.com/6000.0/Documentation/Manual/AudioMixer.html
|
||||
356
docs/engine-reference/unity/modules/input.md
Normal file
356
docs/engine-reference/unity/modules/input.md
Normal file
@@ -0,0 +1,356 @@
|
||||
# Unity 6.3 — Input Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** Unity 6 uses new Input System (legacy Input deprecated)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Unity 6 input systems:
|
||||
- **Input System Package** (RECOMMENDED): Cross-platform, rebindable, modern
|
||||
- **Legacy Input Manager**: Deprecated, avoid for new projects
|
||||
|
||||
---
|
||||
|
||||
## Key Changes from 2022 LTS
|
||||
|
||||
### Legacy Input Deprecated in Unity 6
|
||||
|
||||
```csharp
|
||||
// ❌ DEPRECATED: Input class
|
||||
if (Input.GetKeyDown(KeyCode.Space)) { }
|
||||
|
||||
// ✅ NEW: Input System package
|
||||
using UnityEngine.InputSystem;
|
||||
if (Keyboard.current.spaceKey.wasPressedThisFrame) { }
|
||||
```
|
||||
|
||||
**Migration Required:** Install `com.unity.inputsystem` package.
|
||||
|
||||
---
|
||||
|
||||
## Input System Package Setup
|
||||
|
||||
### Installation
|
||||
1. `Window > Package Manager`
|
||||
2. Search "Input System"
|
||||
3. Install package
|
||||
4. Restart Unity when prompted
|
||||
|
||||
### Enable New Input System
|
||||
`Edit > Project Settings > Player > Active Input Handling`:
|
||||
- **Input System Package (New)** ✅ Recommended
|
||||
- **Both** (for migration period)
|
||||
|
||||
---
|
||||
|
||||
## Input Actions (Recommended Pattern)
|
||||
|
||||
### Create Input Actions Asset
|
||||
|
||||
1. `Assets > Create > Input Actions`
|
||||
2. Name it (e.g., "PlayerControls")
|
||||
3. Open asset, define actions:
|
||||
|
||||
```
|
||||
Action Maps:
|
||||
Gameplay
|
||||
Actions:
|
||||
- Move (Value, Vector2)
|
||||
- Jump (Button)
|
||||
- Fire (Button)
|
||||
- Look (Value, Vector2)
|
||||
```
|
||||
|
||||
4. **Generate C# Class**: Check "Generate C# Class" in Inspector
|
||||
5. Click "Apply"
|
||||
|
||||
### Use Generated Input Class
|
||||
|
||||
```csharp
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
public class PlayerController : MonoBehaviour {
|
||||
private PlayerControls controls;
|
||||
|
||||
void Awake() {
|
||||
controls = new PlayerControls();
|
||||
|
||||
// Subscribe to actions
|
||||
controls.Gameplay.Jump.performed += ctx => Jump();
|
||||
controls.Gameplay.Fire.performed += ctx => Fire();
|
||||
}
|
||||
|
||||
void OnEnable() => controls.Enable();
|
||||
void OnDisable() => controls.Disable();
|
||||
|
||||
void Update() {
|
||||
// Read continuous input
|
||||
Vector2 move = controls.Gameplay.Move.ReadValue<Vector2>();
|
||||
transform.Translate(new Vector3(move.x, 0, move.y) * Time.deltaTime);
|
||||
|
||||
Vector2 look = controls.Gameplay.Look.ReadValue<Vector2>();
|
||||
// Apply camera rotation
|
||||
}
|
||||
|
||||
void Jump() {
|
||||
Debug.Log("Jump!");
|
||||
}
|
||||
|
||||
void Fire() {
|
||||
Debug.Log("Fire!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Direct Device Access (Quick & Dirty)
|
||||
|
||||
### Keyboard
|
||||
|
||||
```csharp
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
void Update() {
|
||||
// Current state
|
||||
if (Keyboard.current.spaceKey.isPressed) { }
|
||||
|
||||
// Just pressed this frame
|
||||
if (Keyboard.current.spaceKey.wasPressedThisFrame) { }
|
||||
|
||||
// Just released this frame
|
||||
if (Keyboard.current.spaceKey.wasReleasedThisFrame) { }
|
||||
}
|
||||
```
|
||||
|
||||
### Mouse
|
||||
|
||||
```csharp
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
void Update() {
|
||||
// Mouse position
|
||||
Vector2 mousePos = Mouse.current.position.ReadValue();
|
||||
|
||||
// Mouse delta (movement)
|
||||
Vector2 mouseDelta = Mouse.current.delta.ReadValue();
|
||||
|
||||
// Mouse buttons
|
||||
if (Mouse.current.leftButton.wasPressedThisFrame) { }
|
||||
if (Mouse.current.rightButton.isPressed) { }
|
||||
|
||||
// Scroll wheel
|
||||
Vector2 scroll = Mouse.current.scroll.ReadValue();
|
||||
}
|
||||
```
|
||||
|
||||
### Gamepad
|
||||
|
||||
```csharp
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
void Update() {
|
||||
Gamepad gamepad = Gamepad.current;
|
||||
if (gamepad == null) return; // No gamepad connected
|
||||
|
||||
// Buttons
|
||||
if (gamepad.buttonSouth.wasPressedThisFrame) { } // A/Cross
|
||||
if (gamepad.buttonWest.wasPressedThisFrame) { } // X/Square
|
||||
|
||||
// Sticks
|
||||
Vector2 leftStick = gamepad.leftStick.ReadValue();
|
||||
Vector2 rightStick = gamepad.rightStick.ReadValue();
|
||||
|
||||
// Triggers
|
||||
float leftTrigger = gamepad.leftTrigger.ReadValue();
|
||||
float rightTrigger = gamepad.rightTrigger.ReadValue();
|
||||
|
||||
// D-Pad
|
||||
Vector2 dpad = gamepad.dpad.ReadValue();
|
||||
}
|
||||
```
|
||||
|
||||
### Touch (Mobile)
|
||||
|
||||
```csharp
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.EnhancedTouch;
|
||||
|
||||
void OnEnable() {
|
||||
EnhancedTouchSupport.Enable();
|
||||
}
|
||||
|
||||
void Update() {
|
||||
foreach (var touch in UnityEngine.InputSystem.EnhancedTouch.Touch.activeTouches) {
|
||||
Debug.Log($"Touch at {touch.screenPosition}");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input Action Callbacks
|
||||
|
||||
### Action Callbacks (Event-Driven)
|
||||
|
||||
```csharp
|
||||
// started: Input began (e.g., trigger pressed slightly)
|
||||
controls.Gameplay.Fire.started += ctx => Debug.Log("Fire started");
|
||||
|
||||
// performed: Input action triggered (e.g., button fully pressed)
|
||||
controls.Gameplay.Fire.performed += ctx => Debug.Log("Fire performed");
|
||||
|
||||
// canceled: Input released or interrupted
|
||||
controls.Gameplay.Fire.canceled += ctx => Debug.Log("Fire canceled");
|
||||
```
|
||||
|
||||
### Context Data
|
||||
|
||||
```csharp
|
||||
controls.Gameplay.Move.performed += ctx => {
|
||||
Vector2 value = ctx.ReadValue<Vector2>();
|
||||
float duration = ctx.duration; // How long input held
|
||||
InputControl control = ctx.control; // Which device/control triggered it
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Control Schemes & Device Switching
|
||||
|
||||
### Define Control Schemes in Input Actions Asset
|
||||
|
||||
```
|
||||
Control Schemes:
|
||||
- Keyboard&Mouse (Keyboard, Mouse)
|
||||
- Gamepad (Gamepad)
|
||||
- Touch (Touchscreen)
|
||||
```
|
||||
|
||||
### Auto-Switch on Device Change
|
||||
|
||||
```csharp
|
||||
controls.Gameplay.Move.performed += ctx => {
|
||||
if (ctx.control.device is Keyboard) {
|
||||
Debug.Log("Using keyboard");
|
||||
} else if (ctx.control.device is Gamepad) {
|
||||
Debug.Log("Using gamepad");
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rebinding (Runtime Key Mapping)
|
||||
|
||||
### Interactive Rebind
|
||||
|
||||
```csharp
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
public void RebindJumpKey() {
|
||||
var rebindOperation = controls.Gameplay.Jump.PerformInteractiveRebinding()
|
||||
.WithControlsExcluding("Mouse") // Exclude mouse bindings
|
||||
.OnComplete(operation => {
|
||||
Debug.Log("Rebind complete");
|
||||
operation.Dispose();
|
||||
})
|
||||
.Start();
|
||||
}
|
||||
```
|
||||
|
||||
### Save/Load Bindings
|
||||
|
||||
```csharp
|
||||
// Save
|
||||
string rebinds = controls.SaveBindingOverridesAsJson();
|
||||
PlayerPrefs.SetString("InputBindings", rebinds);
|
||||
|
||||
// Load
|
||||
string rebinds = PlayerPrefs.GetString("InputBindings");
|
||||
controls.LoadBindingOverridesFromJson(rebinds);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Action Types
|
||||
|
||||
### Button (Press/Release)
|
||||
- Single press/release
|
||||
- Example: Jump, Fire
|
||||
|
||||
### Value (Continuous)
|
||||
- Continuous value (float, Vector2)
|
||||
- Example: Move, Look, Aim
|
||||
|
||||
### Pass-Through (Immediate)
|
||||
- No processing, immediate value
|
||||
- Example: Mouse position
|
||||
|
||||
---
|
||||
|
||||
## Processors (Input Modifiers)
|
||||
|
||||
### Scale
|
||||
|
||||
```csharp
|
||||
// In Input Actions asset: Action > Properties > Processors > Add > Scale
|
||||
// Multiply input by value (e.g., invert Y-axis)
|
||||
```
|
||||
|
||||
### Invert
|
||||
|
||||
```csharp
|
||||
// In Input Actions asset: Action > Properties > Processors > Add > Invert
|
||||
// Flip input sign
|
||||
```
|
||||
|
||||
### Dead Zone
|
||||
|
||||
```csharp
|
||||
// In Input Actions asset: Action > Properties > Processors > Add > Stick Deadzone
|
||||
// Ignore small stick movements
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PlayerInput Component (Simplified Setup)
|
||||
|
||||
### Automatic Input Setup
|
||||
|
||||
```csharp
|
||||
// Add Component: Player Input
|
||||
// Assign Input Actions asset
|
||||
// Behavior: Send Messages / Invoke Unity Events / Invoke C# Events
|
||||
|
||||
// Send Messages example:
|
||||
public class Player : MonoBehaviour {
|
||||
public void OnMove(InputValue value) {
|
||||
Vector2 move = value.Get<Vector2>();
|
||||
// Handle movement
|
||||
}
|
||||
|
||||
public void OnJump(InputValue value) {
|
||||
if (value.isPressed) {
|
||||
Jump();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Input Debugger
|
||||
- `Window > Analysis > Input Debugger`
|
||||
- See active devices, input values, action states
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unity3d.com/Packages/com.unity.inputsystem@1.11/manual/index.html
|
||||
- https://docs.unity3d.com/Packages/com.unity.inputsystem@1.11/manual/QuickStartGuide.html
|
||||
330
docs/engine-reference/unity/modules/navigation.md
Normal file
330
docs/engine-reference/unity/modules/navigation.md
Normal file
@@ -0,0 +1,330 @@
|
||||
# Unity 6.3 — Navigation Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** Unity 6 NavMesh improvements
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Unity 6 navigation systems:
|
||||
- **NavMesh**: Built-in pathfinding for AI agents
|
||||
- **NavMeshComponents**: Package for runtime NavMesh building
|
||||
|
||||
---
|
||||
|
||||
## NavMesh Basics
|
||||
|
||||
### Bake Navigation Mesh
|
||||
|
||||
1. Mark walkable surfaces:
|
||||
- Select GameObject (floor/terrain)
|
||||
- Inspector > Navigation > Object tab
|
||||
- Check "Navigation Static"
|
||||
|
||||
2. Bake NavMesh:
|
||||
- `Window > AI > Navigation`
|
||||
- Bake tab
|
||||
- Click "Bake"
|
||||
|
||||
3. Configure settings:
|
||||
- **Agent Radius**: How wide the agent is (0.5m default)
|
||||
- **Agent Height**: How tall the agent is (2m default)
|
||||
- **Max Slope**: Maximum walkable slope (45° default)
|
||||
- **Step Height**: Maximum climbable step (0.4m default)
|
||||
|
||||
---
|
||||
|
||||
## NavMeshAgent (AI Movement)
|
||||
|
||||
### Basic Agent Setup
|
||||
|
||||
```csharp
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
public class Enemy : MonoBehaviour {
|
||||
private NavMeshAgent agent;
|
||||
public Transform target;
|
||||
|
||||
void Start() {
|
||||
agent = GetComponent<NavMeshAgent>();
|
||||
}
|
||||
|
||||
void Update() {
|
||||
// ✅ Move to target
|
||||
agent.SetDestination(target.position);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### NavMeshAgent Properties
|
||||
|
||||
```csharp
|
||||
NavMeshAgent agent = GetComponent<NavMeshAgent>();
|
||||
|
||||
// Speed
|
||||
agent.speed = 3.5f;
|
||||
|
||||
// Acceleration
|
||||
agent.acceleration = 8f;
|
||||
|
||||
// Stopping distance
|
||||
agent.stoppingDistance = 2f; // Stop 2m before destination
|
||||
|
||||
// Auto-braking (slow down at destination)
|
||||
agent.autoBraking = true;
|
||||
|
||||
// Rotation speed
|
||||
agent.angularSpeed = 120f; // Degrees per second
|
||||
|
||||
// Obstacle avoidance
|
||||
agent.obstacleAvoidanceType = ObstacleAvoidanceType.HighQualityObstacleAvoidance;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Check Path Status
|
||||
|
||||
```csharp
|
||||
void Update() {
|
||||
agent.SetDestination(target.position);
|
||||
|
||||
// Check if agent has a path
|
||||
if (agent.hasPath) {
|
||||
// Check if path is complete
|
||||
if (agent.pathStatus == NavMeshPathStatus.PathComplete) {
|
||||
Debug.Log("Valid path");
|
||||
} else if (agent.pathStatus == NavMeshPathStatus.PathPartial) {
|
||||
Debug.Log("Partial path (destination unreachable)");
|
||||
} else {
|
||||
Debug.Log("Invalid path");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if agent reached destination
|
||||
if (!agent.pathPending && agent.remainingDistance <= agent.stoppingDistance) {
|
||||
Debug.Log("Reached destination");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Calculate Path (Don't Move Yet)
|
||||
|
||||
```csharp
|
||||
NavMeshPath path = new NavMeshPath();
|
||||
agent.CalculatePath(targetPosition, path);
|
||||
|
||||
if (path.status == NavMeshPathStatus.PathComplete) {
|
||||
// Valid path exists
|
||||
agent.SetPath(path); // Apply the path
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## NavMesh Areas (Walkable Costs)
|
||||
|
||||
### Define Areas
|
||||
`Window > AI > Navigation > Areas tab`
|
||||
- **Walkable**: Cost 1 (default)
|
||||
- **Not Walkable**: Unwalkable
|
||||
- **Jump**: Cost 2 (prefer other routes)
|
||||
- **Custom**: Define your own
|
||||
|
||||
### Assign Area Costs
|
||||
|
||||
```csharp
|
||||
// Prefer shorter paths over low-cost paths
|
||||
agent.areaMask = NavMesh.AllAreas; // Walk on all areas
|
||||
|
||||
// Only walk on "Walkable" area (avoid "Jump")
|
||||
agent.areaMask = 1 << NavMesh.GetAreaFromName("Walkable");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## NavMesh Obstacles (Dynamic Obstacles)
|
||||
|
||||
### NavMeshObstacle Component
|
||||
|
||||
```csharp
|
||||
// Add: GameObject > Add Component > NavMesh Obstacle
|
||||
|
||||
// Carve: Create hole in NavMesh (agents avoid)
|
||||
// Don't Carve: Agent pushes through (local avoidance)
|
||||
```
|
||||
|
||||
### Dynamic Carving (Moving Obstacles)
|
||||
|
||||
```csharp
|
||||
NavMeshObstacle obstacle = GetComponent<NavMeshObstacle>();
|
||||
obstacle.carving = true; // Create dynamic hole in NavMesh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Off-Mesh Links (Jumps, Teleports)
|
||||
|
||||
### Create Off-Mesh Link
|
||||
|
||||
1. `GameObject > Create Empty` (at jump start)
|
||||
2. Add `Off Mesh Link` component
|
||||
3. Set Start/End transforms
|
||||
4. Configure:
|
||||
- **Bi-Directional**: Can traverse both ways
|
||||
- **Cost Override**: Path cost for this link
|
||||
|
||||
### Detect Off-Mesh Link Traversal
|
||||
|
||||
```csharp
|
||||
void Update() {
|
||||
// Check if agent is on an off-mesh link
|
||||
if (agent.isOnOffMeshLink) {
|
||||
// Manually traverse (e.g., play jump animation)
|
||||
StartCoroutine(TraverseOffMeshLink());
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator TraverseOffMeshLink() {
|
||||
OffMeshLinkData data = agent.currentOffMeshLinkData;
|
||||
Vector3 startPos = agent.transform.position;
|
||||
Vector3 endPos = data.endPos;
|
||||
|
||||
float duration = 0.5f;
|
||||
float elapsed = 0f;
|
||||
|
||||
while (elapsed < duration) {
|
||||
agent.transform.position = Vector3.Lerp(startPos, endPos, elapsed / duration);
|
||||
elapsed += Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
agent.CompleteOffMeshLink(); // Resume normal pathfinding
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## NavMeshComponents Package (Runtime Baking)
|
||||
|
||||
### Installation
|
||||
1. `Window > Package Manager`
|
||||
2. Add from Git URL: `com.unity.ai.navigation`
|
||||
|
||||
### Runtime NavMesh Baking
|
||||
|
||||
```csharp
|
||||
using Unity.AI.Navigation;
|
||||
|
||||
public class NavMeshBuilder : MonoBehaviour {
|
||||
public NavMeshSurface surface;
|
||||
|
||||
void Start() {
|
||||
// Bake NavMesh at runtime
|
||||
surface.BuildNavMesh();
|
||||
}
|
||||
|
||||
void UpdateNavMesh() {
|
||||
// Update NavMesh after terrain changes
|
||||
surface.UpdateNavMesh(surface.navMeshData);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Patrol Between Waypoints
|
||||
|
||||
```csharp
|
||||
public Transform[] waypoints;
|
||||
private int currentWaypoint = 0;
|
||||
|
||||
void Update() {
|
||||
if (!agent.pathPending && agent.remainingDistance < 0.5f) {
|
||||
// Reached waypoint, move to next
|
||||
currentWaypoint = (currentWaypoint + 1) % waypoints.Length;
|
||||
agent.SetDestination(waypoints[currentWaypoint].position);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Chase Player
|
||||
|
||||
```csharp
|
||||
public Transform player;
|
||||
public float chaseRange = 10f;
|
||||
|
||||
void Update() {
|
||||
float distance = Vector3.Distance(transform.position, player.position);
|
||||
|
||||
if (distance <= chaseRange) {
|
||||
agent.SetDestination(player.position);
|
||||
} else {
|
||||
agent.ResetPath(); // Stop moving
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Flee from Player
|
||||
|
||||
```csharp
|
||||
public Transform player;
|
||||
public float fleeRange = 5f;
|
||||
|
||||
void Update() {
|
||||
float distance = Vector3.Distance(transform.position, player.position);
|
||||
|
||||
if (distance <= fleeRange) {
|
||||
// Run away from player
|
||||
Vector3 fleeDirection = transform.position - player.position;
|
||||
Vector3 fleeTarget = transform.position + fleeDirection.normalized * 10f;
|
||||
|
||||
agent.SetDestination(fleeTarget);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### NavMesh Visualization
|
||||
- `Window > AI > Navigation > Bake tab`
|
||||
- Check "Show NavMesh" to visualize walkable areas
|
||||
|
||||
### Agent Path Gizmos
|
||||
|
||||
```csharp
|
||||
void OnDrawGizmos() {
|
||||
if (agent != null && agent.hasPath) {
|
||||
Gizmos.color = Color.green;
|
||||
Vector3[] corners = agent.path.corners;
|
||||
|
||||
for (int i = 0; i < corners.Length - 1; i++) {
|
||||
Gizmos.DrawLine(corners[i], corners[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
- **Limit Obstacle Avoidance Quality**: Use `LowQualityObstacleAvoidance` for distant agents
|
||||
- **Update Frequency**: Don't call `SetDestination()` every frame if target hasn't moved
|
||||
- **Area Masks**: Limit walkable areas to reduce pathfinding search space
|
||||
- **NavMesh Tiles**: Use tiled NavMesh for large worlds (NavMeshComponents package)
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unity3d.com/6000.0/Documentation/Manual/Navigation.html
|
||||
- https://docs.unity3d.com/Packages/com.unity.ai.navigation@2.0/manual/index.html
|
||||
351
docs/engine-reference/unity/modules/networking.md
Normal file
351
docs/engine-reference/unity/modules/networking.md
Normal file
@@ -0,0 +1,351 @@
|
||||
# Unity 6.3 — Networking Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** Unity 6 uses Netcode for GameObjects (UNet deprecated)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Unity 6 networking options:
|
||||
- **Netcode for GameObjects** (RECOMMENDED): Official Unity multiplayer framework
|
||||
- **Mirror**: Community-driven (UNet successor)
|
||||
- **Photon**: Third-party service (PUN2)
|
||||
- **Custom**: Low-level sockets
|
||||
|
||||
**UNet (Legacy)**: Deprecated, do not use.
|
||||
|
||||
---
|
||||
|
||||
## Netcode for GameObjects
|
||||
|
||||
### Installation
|
||||
1. `Window > Package Manager`
|
||||
2. Search "Netcode for GameObjects"
|
||||
3. Install `com.unity.netcode.gameobjects`
|
||||
|
||||
---
|
||||
|
||||
## Basic Setup
|
||||
|
||||
### NetworkManager
|
||||
|
||||
```csharp
|
||||
// Add to scene: GameObject > Add Component > NetworkManager
|
||||
|
||||
// Or create custom NetworkManager:
|
||||
using Unity.Netcode;
|
||||
|
||||
public class CustomNetworkManager : MonoBehaviour {
|
||||
void Start() {
|
||||
NetworkManager.Singleton.StartHost(); // Server + client
|
||||
// OR
|
||||
NetworkManager.Singleton.StartServer(); // Dedicated server
|
||||
// OR
|
||||
NetworkManager.Singleton.StartClient(); // Client only
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## NetworkObject (Networked GameObjects)
|
||||
|
||||
### Mark GameObject as Networked
|
||||
|
||||
1. Add `NetworkObject` component to GameObject
|
||||
2. Must be in root of prefab (not nested)
|
||||
3. Register prefab in `NetworkManager > NetworkPrefabs List`
|
||||
|
||||
### Spawn Network Objects
|
||||
|
||||
```csharp
|
||||
using Unity.Netcode;
|
||||
|
||||
public class GameManager : NetworkBehaviour {
|
||||
public GameObject playerPrefab;
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void SpawnPlayerServerRpc(ulong clientId) {
|
||||
GameObject player = Instantiate(playerPrefab);
|
||||
player.GetComponent<NetworkObject>().SpawnAsPlayerObject(clientId);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## NetworkBehaviour (Networked Scripts)
|
||||
|
||||
### NetworkBehaviour Base Class
|
||||
|
||||
```csharp
|
||||
using Unity.Netcode;
|
||||
|
||||
public class Player : NetworkBehaviour {
|
||||
// Called when spawned on network
|
||||
public override void OnNetworkSpawn() {
|
||||
if (IsOwner) {
|
||||
// Only run on owner's client
|
||||
GetComponent<Camera>().enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Update() {
|
||||
if (!IsOwner) return; // Only owner can control
|
||||
|
||||
// Handle input
|
||||
if (Input.GetKey(KeyCode.W)) {
|
||||
MoveServerRpc(Vector3.forward);
|
||||
}
|
||||
}
|
||||
|
||||
[ServerRpc]
|
||||
void MoveServerRpc(Vector3 direction) {
|
||||
// Runs on server
|
||||
transform.position += direction * Time.deltaTime;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Network Variables (Synchronized State)
|
||||
|
||||
### NetworkVariable<T>
|
||||
|
||||
```csharp
|
||||
using Unity.Netcode;
|
||||
|
||||
public class Player : NetworkBehaviour {
|
||||
// ✅ Auto-synced across clients
|
||||
private NetworkVariable<int> health = new NetworkVariable<int>(100);
|
||||
|
||||
public override void OnNetworkSpawn() {
|
||||
// Subscribe to value changes
|
||||
health.OnValueChanged += OnHealthChanged;
|
||||
}
|
||||
|
||||
void OnHealthChanged(int oldValue, int newValue) {
|
||||
Debug.Log($"Health changed: {oldValue} -> {newValue}");
|
||||
UpdateHealthUI(newValue);
|
||||
}
|
||||
|
||||
[ServerRpc]
|
||||
public void TakeDamageServerRpc(int damage) {
|
||||
// Only server can modify NetworkVariable
|
||||
health.Value -= damage;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### NetworkVariable Permissions
|
||||
|
||||
```csharp
|
||||
// Server can write, clients read-only (default)
|
||||
private NetworkVariable<int> score = new NetworkVariable<int>();
|
||||
|
||||
// Owner can write
|
||||
private NetworkVariable<int> ammo = new NetworkVariable<int>(
|
||||
default,
|
||||
NetworkVariableReadPermission.Everyone,
|
||||
NetworkVariableWritePermission.Owner
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## RPCs (Remote Procedure Calls)
|
||||
|
||||
### ServerRpc (Client → Server)
|
||||
|
||||
```csharp
|
||||
// Client calls, server executes
|
||||
[ServerRpc]
|
||||
void FireWeaponServerRpc() {
|
||||
// Runs on server
|
||||
Debug.Log("Server: Weapon fired");
|
||||
}
|
||||
|
||||
// Call from client:
|
||||
if (IsOwner && Input.GetKeyDown(KeyCode.Space)) {
|
||||
FireWeaponServerRpc();
|
||||
}
|
||||
```
|
||||
|
||||
### ClientRpc (Server → All Clients)
|
||||
|
||||
```csharp
|
||||
// Server calls, all clients execute
|
||||
[ClientRpc]
|
||||
void PlayExplosionClientRpc(Vector3 position) {
|
||||
// Runs on all clients
|
||||
Instantiate(explosionPrefab, position, Quaternion.identity);
|
||||
}
|
||||
|
||||
// Call from server:
|
||||
[ServerRpc]
|
||||
void ExplodeServerRpc(Vector3 position) {
|
||||
// Server logic
|
||||
DealDamageToNearbyPlayers(position);
|
||||
|
||||
// Notify all clients
|
||||
PlayExplosionClientRpc(position);
|
||||
}
|
||||
```
|
||||
|
||||
### RPC Parameters
|
||||
|
||||
```csharp
|
||||
// ✅ Supported: Primitives, structs, strings, arrays
|
||||
[ServerRpc]
|
||||
void SetNameServerRpc(string playerName) { }
|
||||
|
||||
[ClientRpc]
|
||||
void UpdateScoresClientRpc(int[] scores) { }
|
||||
|
||||
// ❌ Not supported: MonoBehaviour, GameObject (use NetworkObjectReference)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Network Ownership
|
||||
|
||||
### Check Ownership
|
||||
|
||||
```csharp
|
||||
if (IsOwner) {
|
||||
// This client owns this NetworkObject
|
||||
}
|
||||
|
||||
if (IsServer) {
|
||||
// Running on server
|
||||
}
|
||||
|
||||
if (IsClient) {
|
||||
// Running on client
|
||||
}
|
||||
|
||||
if (IsLocalPlayer) {
|
||||
// This is the local player object
|
||||
}
|
||||
```
|
||||
|
||||
### Transfer Ownership
|
||||
|
||||
```csharp
|
||||
// Server transfers ownership
|
||||
NetworkObject netObj = GetComponent<NetworkObject>();
|
||||
netObj.ChangeOwnership(newOwnerClientId);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## NetworkObjectReference (Pass GameObjects in RPCs)
|
||||
|
||||
```csharp
|
||||
using Unity.Netcode;
|
||||
|
||||
[ServerRpc]
|
||||
void AttackTargetServerRpc(NetworkObjectReference targetRef) {
|
||||
if (targetRef.TryGet(out NetworkObject target)) {
|
||||
// Got the target object
|
||||
target.GetComponent<Health>().TakeDamage(10);
|
||||
}
|
||||
}
|
||||
|
||||
// Call:
|
||||
NetworkObject targetNetObj = target.GetComponent<NetworkObject>();
|
||||
AttackTargetServerRpc(targetNetObj);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Client-Server Architecture
|
||||
|
||||
### Server-Authoritative Pattern (RECOMMENDED)
|
||||
|
||||
```csharp
|
||||
public class Player : NetworkBehaviour {
|
||||
private NetworkVariable<Vector3> position = new NetworkVariable<Vector3>();
|
||||
|
||||
void Update() {
|
||||
if (IsOwner) {
|
||||
// Client: Send input to server
|
||||
Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
|
||||
MoveServerRpc(input);
|
||||
}
|
||||
|
||||
// All clients: Sync to networked position
|
||||
transform.position = position.Value;
|
||||
}
|
||||
|
||||
[ServerRpc]
|
||||
void MoveServerRpc(Vector3 input) {
|
||||
// Server: Validate and apply movement
|
||||
position.Value += input * Time.deltaTime * moveSpeed;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Network Transport
|
||||
|
||||
### Unity Transport (Default)
|
||||
|
||||
```csharp
|
||||
// Configured in NetworkManager:
|
||||
// - Transport: Unity Transport
|
||||
// - Address: 127.0.0.1 (localhost) or server IP
|
||||
// - Port: 7777 (default)
|
||||
```
|
||||
|
||||
### Connection Events
|
||||
|
||||
```csharp
|
||||
void Start() {
|
||||
NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnected;
|
||||
NetworkManager.Singleton.OnClientDisconnectCallback += OnClientDisconnected;
|
||||
}
|
||||
|
||||
void OnClientConnected(ulong clientId) {
|
||||
Debug.Log($"Client {clientId} connected");
|
||||
}
|
||||
|
||||
void OnClientDisconnected(ulong clientId) {
|
||||
Debug.Log($"Client {clientId} disconnected");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
### Reduce Network Traffic
|
||||
- Use `NetworkVariable` for state that changes infrequently
|
||||
- Batch multiple changes before syncing
|
||||
- Use delta compression for large data
|
||||
|
||||
### Prediction & Reconciliation
|
||||
- Run movement locally for responsiveness
|
||||
- Reconcile with server authoritative state
|
||||
- Use interpolation for smooth movement
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Network Profiler
|
||||
- `Window > Analysis > Network Profiler`
|
||||
- Monitor bandwidth, RPC calls, variable updates
|
||||
|
||||
### Network Simulator (Test Latency/Packet Loss)
|
||||
- `NetworkManager > Network Simulator`
|
||||
- Add artificial lag and packet loss for testing
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs-multiplayer.unity3d.com/netcode/current/about/
|
||||
- https://docs-multiplayer.unity3d.com/netcode/current/learn/bossroom/
|
||||
268
docs/engine-reference/unity/modules/physics.md
Normal file
268
docs/engine-reference/unity/modules/physics.md
Normal file
@@ -0,0 +1,268 @@
|
||||
# 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
|
||||
238
docs/engine-reference/unity/modules/rendering.md
Normal file
238
docs/engine-reference/unity/modules/rendering.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# Unity 6.3 — Rendering Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** LLM trained on Unity 2022 LTS; Unity 6 has major rendering changes
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Unity 6.3 LTS uses **Scriptable Render Pipelines (SRP)** as the modern rendering architecture:
|
||||
- **URP (Universal Render Pipeline)**: Cross-platform, mobile-friendly (RECOMMENDED)
|
||||
- **HDRP (High Definition Render Pipeline)**: High-end PC/console, photorealistic
|
||||
- **Built-in Pipeline**: Deprecated, avoid for new projects
|
||||
|
||||
---
|
||||
|
||||
## Key Changes from 2022 LTS
|
||||
|
||||
### RenderGraph API (Unity 6+)
|
||||
Custom render passes now use RenderGraph instead of CommandBuffer:
|
||||
|
||||
```csharp
|
||||
// ✅ Unity 6+ (RenderGraph)
|
||||
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) {
|
||||
using var builder = renderGraph.AddRasterRenderPass<PassData>("MyPass", out var passData);
|
||||
builder.SetRenderFunc((PassData data, RasterGraphContext ctx) => {
|
||||
// Rendering commands
|
||||
});
|
||||
}
|
||||
|
||||
// ❌ Old (CommandBuffer - still works but deprecated)
|
||||
public override void Execute(ScriptableRenderContext context, ref RenderingData data) { }
|
||||
```
|
||||
|
||||
### GPU Resident Drawer (Unity 6+)
|
||||
Automatic batching for massive draw call reduction:
|
||||
|
||||
```csharp
|
||||
// Enable in URP Asset settings:
|
||||
// Rendering > GPU Resident Drawer = Enabled
|
||||
// Automatically batches thousands of objects with minimal CPU overhead
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## URP Quick Reference
|
||||
|
||||
### Creating a URP Asset
|
||||
1. `Assets > Create > Rendering > URP Asset (with Universal Renderer)`
|
||||
2. Assign to `Project Settings > Graphics > Scriptable Render Pipeline Settings`
|
||||
|
||||
### URP Renderer Features
|
||||
Add custom render passes:
|
||||
|
||||
```csharp
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
public class OutlineRendererFeature : ScriptableRendererFeature {
|
||||
OutlineRenderPass pass;
|
||||
|
||||
public override void Create() {
|
||||
pass = new OutlineRenderPass();
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData data) {
|
||||
renderer.EnqueuePass(pass);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Materials & Shaders
|
||||
|
||||
### Shader Graph (Visual Shader Editor)
|
||||
Unity 6 Shader Graph is production-ready for all shader types:
|
||||
|
||||
```csharp
|
||||
// Create: Assets > Create > Shader Graph > URP > Lit Shader Graph
|
||||
// No code needed, visual node-based editing
|
||||
```
|
||||
|
||||
### HLSL Custom Shaders (URP)
|
||||
|
||||
```hlsl
|
||||
// URP Lit shader template
|
||||
Shader "Custom/URPLit" {
|
||||
Properties {
|
||||
_BaseColor ("Base Color", Color) = (1,1,1,1)
|
||||
}
|
||||
SubShader {
|
||||
Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" }
|
||||
|
||||
Pass {
|
||||
Name "ForwardLit"
|
||||
Tags { "LightMode"="UniversalForward" }
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
|
||||
struct Attributes {
|
||||
float4 positionOS : POSITION;
|
||||
};
|
||||
|
||||
struct Varyings {
|
||||
float4 positionCS : SV_POSITION;
|
||||
};
|
||||
|
||||
Varyings vert(Attributes input) {
|
||||
Varyings output;
|
||||
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
|
||||
return output;
|
||||
}
|
||||
|
||||
half4 frag(Varyings input) : SV_Target {
|
||||
return half4(1, 0, 0, 1); // Red
|
||||
}
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Lighting
|
||||
|
||||
### Baked Lighting (Unity 6 Progressive Lightmapper)
|
||||
|
||||
```csharp
|
||||
// Mark objects as static: Inspector > Static > Contribute GI
|
||||
// Bake: Window > Rendering > Lighting > Generate Lighting
|
||||
```
|
||||
|
||||
### Real-Time Lights (URP)
|
||||
|
||||
```csharp
|
||||
// Main Light (Directional): Auto-handled by URP
|
||||
// Additional Lights: Limited by "Additional Lights" setting in URP Asset
|
||||
|
||||
// Check light count in shader:
|
||||
int lightCount = GetAdditionalLightsCount();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Post-Processing
|
||||
|
||||
### Volume System (Unity 6+)
|
||||
|
||||
```csharp
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
// Add Volume component to GameObject
|
||||
// Add Volume Profile asset
|
||||
// Configure effects: Bloom, Color Grading, Depth of Field, etc.
|
||||
|
||||
// Script access:
|
||||
Volume volume = GetComponent<Volume>();
|
||||
if (volume.profile.TryGet<Bloom>(out var bloom)) {
|
||||
bloom.intensity.value = 2.5f;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance
|
||||
|
||||
### SRP Batcher (Auto-batching)
|
||||
|
||||
```csharp
|
||||
// Enable: URP Asset > Advanced > SRP Batcher = Enabled
|
||||
// Batches draws with same shader variant (minimal CPU overhead)
|
||||
```
|
||||
|
||||
### GPU Instancing
|
||||
|
||||
```csharp
|
||||
// Material: Enable "Enable GPU Instancing" checkbox
|
||||
// Batches identical meshes (same material + mesh)
|
||||
|
||||
Graphics.RenderMeshInstanced(
|
||||
new RenderParams(material),
|
||||
mesh,
|
||||
0,
|
||||
matrices // NativeArray<Matrix4x4>
|
||||
);
|
||||
```
|
||||
|
||||
### Occlusion Culling
|
||||
|
||||
```csharp
|
||||
// Window > Rendering > Occlusion Culling
|
||||
// Bake occlusion data for static geometry
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Custom Camera Rendering
|
||||
|
||||
```csharp
|
||||
// Get URP camera data
|
||||
var cameraData = frameData.Get<UniversalCameraData>();
|
||||
var camera = cameraData.camera;
|
||||
|
||||
// Access render targets
|
||||
var colorTarget = cameraData.renderer.cameraColorTargetHandle;
|
||||
```
|
||||
|
||||
### Screen-Space Effects
|
||||
|
||||
```csharp
|
||||
// Create ScriptableRendererFeature
|
||||
// Inject pass at specific point: AfterRenderingOpaques, AfterRenderingTransparents, etc.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Frame Debugger
|
||||
- `Window > Analysis > Frame Debugger`
|
||||
- Step through draw calls, inspect state
|
||||
|
||||
### Rendering Debugger (Unity 6+)
|
||||
- `Window > Analysis > Rendering Debugger`
|
||||
- Live view of URP settings, overdraw, lighting
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@17.0/manual/index.html
|
||||
- https://docs.unity3d.com/6000.0/Documentation/Manual/render-pipelines.html
|
||||
377
docs/engine-reference/unity/modules/ui.md
Normal file
377
docs/engine-reference/unity/modules/ui.md
Normal file
@@ -0,0 +1,377 @@
|
||||
# Unity 6.3 — UI Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** Unity 6 UI Toolkit is production-ready for runtime UI
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Unity 6 UI systems:
|
||||
- **UI Toolkit** (RECOMMENDED): Modern, performant, HTML/CSS-like (production-ready in Unity 6)
|
||||
- **UGUI (Canvas)**: Legacy system, still supported but not recommended for new projects
|
||||
- **IMGUI**: Editor-only, deprecated for runtime UI
|
||||
|
||||
---
|
||||
|
||||
## UI Toolkit (Modern UI)
|
||||
|
||||
### Setup UI Document
|
||||
|
||||
1. Create UXML (UI structure):
|
||||
- `Assets > Create > UI Toolkit > UI Document`
|
||||
2. Create USS (styling):
|
||||
- `Assets > Create > UI Toolkit > StyleSheet`
|
||||
3. Add to scene:
|
||||
- `GameObject > UI Toolkit > UI Document`
|
||||
- Assign UXML to `UIDocument > Source Asset`
|
||||
|
||||
---
|
||||
|
||||
### UXML (UI Structure)
|
||||
|
||||
```xml
|
||||
<!-- MainMenu.uxml -->
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements">
|
||||
<ui:VisualElement class="container">
|
||||
<ui:Label text="Main Menu" class="title" />
|
||||
<ui:Button name="play-button" text="Play" />
|
||||
<ui:Button name="settings-button" text="Settings" />
|
||||
<ui:Button name="quit-button" text="Quit" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### USS (Styling)
|
||||
|
||||
```css
|
||||
/* MainMenu.uss */
|
||||
.container {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgb(30, 30, 30);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 48px;
|
||||
color: white;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
Button {
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
margin: 10px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
Button:hover {
|
||||
background-color: rgb(100, 150, 200);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### C# Scripting (UI Toolkit)
|
||||
|
||||
```csharp
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
public class MainMenu : MonoBehaviour {
|
||||
void OnEnable() {
|
||||
var root = GetComponent<UIDocument>().rootVisualElement;
|
||||
|
||||
// Query elements by name
|
||||
var playButton = root.Q<Button>("play-button");
|
||||
var settingsButton = root.Q<Button>("settings-button");
|
||||
var quitButton = root.Q<Button>("quit-button");
|
||||
|
||||
// Register callbacks
|
||||
playButton.clicked += OnPlayClicked;
|
||||
settingsButton.clicked += OnSettingsClicked;
|
||||
quitButton.clicked += Application.Quit;
|
||||
}
|
||||
|
||||
void OnPlayClicked() {
|
||||
Debug.Log("Play clicked");
|
||||
// Load game scene
|
||||
}
|
||||
|
||||
void OnSettingsClicked() {
|
||||
Debug.Log("Settings clicked");
|
||||
// Open settings menu
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Common UI Elements
|
||||
|
||||
```csharp
|
||||
// Label (text display)
|
||||
var label = root.Q<Label>("score-label");
|
||||
label.text = "Score: 100";
|
||||
|
||||
// Button
|
||||
var button = root.Q<Button>("submit-button");
|
||||
button.clicked += OnSubmit;
|
||||
|
||||
// TextField (text input)
|
||||
var textField = root.Q<TextField>("name-input");
|
||||
string playerName = textField.value;
|
||||
|
||||
// Toggle (checkbox)
|
||||
var toggle = root.Q<Toggle>("music-toggle");
|
||||
bool isMusicEnabled = toggle.value;
|
||||
|
||||
// Slider
|
||||
var slider = root.Q<Slider>("volume-slider");
|
||||
float volume = slider.value; // 0-1
|
||||
|
||||
// DropdownField (dropdown menu)
|
||||
var dropdown = root.Q<DropdownField>("difficulty-dropdown");
|
||||
dropdown.choices = new List<string> { "Easy", "Normal", "Hard" };
|
||||
dropdown.value = "Normal";
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Dynamic UI Creation (No UXML)
|
||||
|
||||
```csharp
|
||||
void CreateUI() {
|
||||
var root = GetComponent<UIDocument>().rootVisualElement;
|
||||
|
||||
// Create elements
|
||||
var container = new VisualElement();
|
||||
container.AddToClassList("container");
|
||||
|
||||
var label = new Label("Hello, UI Toolkit!");
|
||||
var button = new Button(() => Debug.Log("Clicked")) { text = "Click Me" };
|
||||
|
||||
container.Add(label);
|
||||
container.Add(button);
|
||||
root.Add(container);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### USS Flexbox Layout
|
||||
|
||||
```css
|
||||
/* Horizontal layout */
|
||||
.horizontal {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
/* Vertical layout (default) */
|
||||
.vertical {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Center children */
|
||||
.centered {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Spacing */
|
||||
.spaced {
|
||||
justify-content: space-between;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## UGUI (Legacy Canvas UI)
|
||||
|
||||
### Basic Setup (Still Works in Unity 6)
|
||||
|
||||
```csharp
|
||||
// GameObject > UI > Canvas (creates Canvas, EventSystem)
|
||||
|
||||
// UI Elements:
|
||||
// - Text (use TextMeshPro instead)
|
||||
// - Button
|
||||
// - Image
|
||||
// - Slider
|
||||
// - Toggle
|
||||
// - InputField
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### UGUI Scripting
|
||||
|
||||
```csharp
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro; // TextMeshPro
|
||||
|
||||
public class LegacyUI : MonoBehaviour {
|
||||
public TextMeshProUGUI scoreText;
|
||||
public Button playButton;
|
||||
public Slider volumeSlider;
|
||||
|
||||
void Start() {
|
||||
// Update text
|
||||
scoreText.text = "Score: 100";
|
||||
|
||||
// Button click
|
||||
playButton.onClick.AddListener(OnPlayClicked);
|
||||
|
||||
// Slider value changed
|
||||
volumeSlider.onValueChanged.AddListener(OnVolumeChanged);
|
||||
}
|
||||
|
||||
void OnPlayClicked() {
|
||||
Debug.Log("Play clicked");
|
||||
}
|
||||
|
||||
void OnVolumeChanged(float value) {
|
||||
AudioListener.volume = value;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### TextMeshPro (Better Text Rendering)
|
||||
|
||||
```csharp
|
||||
// Install: Window > TextMeshPro > Import TMP Essential Resources
|
||||
|
||||
// Use TMP_Text instead of Unity's Text component
|
||||
using TMPro;
|
||||
|
||||
public TextMeshProUGUI tmpText;
|
||||
tmpText.text = "High Quality Text";
|
||||
tmpText.fontSize = 24;
|
||||
tmpText.color = Color.white;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Canvas Settings (UGUI)
|
||||
|
||||
### Render Modes
|
||||
|
||||
```csharp
|
||||
// Screen Space - Overlay: UI rendered on top of everything (no camera needed)
|
||||
// Screen Space - Camera: UI rendered by specific camera (allows effects)
|
||||
// World Space: UI in 3D world (e.g., floating health bars)
|
||||
```
|
||||
|
||||
### Canvas Scaler (Responsive UI)
|
||||
|
||||
```csharp
|
||||
// UI Scale Mode:
|
||||
// - Constant Pixel Size: UI elements have fixed pixel size
|
||||
// - Scale With Screen Size: UI scales based on reference resolution (RECOMMENDED)
|
||||
// - Constant Physical Size: UI elements have fixed physical size (cm)
|
||||
|
||||
// Example: Scale With Screen Size
|
||||
// Reference Resolution: 1920x1080
|
||||
// Screen Match Mode: Match Width Or Height (0.5 = balanced)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Layout Groups (UGUI)
|
||||
|
||||
### Horizontal Layout Group
|
||||
|
||||
```csharp
|
||||
// Auto-arranges children horizontally
|
||||
// Add: GameObject > Add Component > Horizontal Layout Group
|
||||
```
|
||||
|
||||
### Vertical Layout Group
|
||||
|
||||
```csharp
|
||||
// Auto-arranges children vertically
|
||||
```
|
||||
|
||||
### Grid Layout Group
|
||||
|
||||
```csharp
|
||||
// Arranges children in a grid
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance (UI Toolkit vs UGUI)
|
||||
|
||||
### UI Toolkit Advantages
|
||||
- ✅ Faster rendering (retained mode)
|
||||
- ✅ Better for complex UIs with many elements
|
||||
- ✅ Easier styling (CSS-like)
|
||||
- ✅ Better for dynamic UIs
|
||||
|
||||
### UGUI Advantages
|
||||
- ✅ More mature, widely documented
|
||||
- ✅ Better integration with Unity Editor
|
||||
- ✅ Easier for beginners
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Health Bar (UI Toolkit)
|
||||
|
||||
```csharp
|
||||
var healthBar = root.Q<VisualElement>("health-bar");
|
||||
healthBar.style.width = new StyleLength(new Length(healthPercent, LengthUnit.Percent));
|
||||
```
|
||||
|
||||
### Health Bar (UGUI)
|
||||
|
||||
```csharp
|
||||
public Image healthBarImage;
|
||||
|
||||
void UpdateHealth(float percent) {
|
||||
healthBarImage.fillAmount = percent; // 0-1
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Fade In/Out (UI Toolkit)
|
||||
|
||||
```csharp
|
||||
IEnumerator FadeIn(VisualElement element, float duration) {
|
||||
float elapsed = 0f;
|
||||
while (elapsed < duration) {
|
||||
elapsed += Time.deltaTime;
|
||||
element.style.opacity = Mathf.Lerp(0f, 1f, elapsed / duration);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### UI Toolkit Debugger
|
||||
- `Window > UI Toolkit > Debugger`
|
||||
- Inspect element hierarchy, styles, layout
|
||||
|
||||
### UGUI Event System Debugger
|
||||
- Select EventSystem in Hierarchy
|
||||
- Inspector shows active input module, raycast info
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unity3d.com/6000.0/Documentation/Manual/UIElements.html
|
||||
- https://docs.unity3d.com/Packages/com.unity.ui@2.0/manual/index.html
|
||||
- https://docs.unity3d.com/Packages/com.unity.ugui@2.0/manual/index.html
|
||||
378
docs/engine-reference/unity/plugins/addressables.md
Normal file
378
docs/engine-reference/unity/plugins/addressables.md
Normal file
@@ -0,0 +1,378 @@
|
||||
# Unity 6.3 — Addressables
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Status:** Production-Ready
|
||||
**Package:** `com.unity.addressables` (Package Manager)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Addressables** is Unity's advanced asset management system that replaces `Resources.Load()`
|
||||
with async loading, remote content delivery, and better memory control.
|
||||
|
||||
**Use Addressables for:**
|
||||
- Async asset loading (non-blocking)
|
||||
- DLC and remote content
|
||||
- Memory optimization (load/unload on demand)
|
||||
- Asset dependency management
|
||||
- Large projects with many assets
|
||||
|
||||
**DON'T use Addressables for:**
|
||||
- Tiny projects (overhead not worth it)
|
||||
- Assets needed immediately at startup (use direct references)
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### Install via Package Manager
|
||||
|
||||
1. `Window > Package Manager`
|
||||
2. Unity Registry > Search "Addressables"
|
||||
3. Install `Addressables`
|
||||
|
||||
---
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### 1. **Addressable Assets**
|
||||
- Assets marked as "Addressable" (assigned unique keys)
|
||||
- Can be loaded by key at runtime
|
||||
|
||||
### 2. **Asset Groups**
|
||||
- Organize assets (e.g., "UI", "Weapons", "Level1")
|
||||
- Groups determine build settings (local vs remote)
|
||||
|
||||
### 3. **Async Loading**
|
||||
- All loading is async (non-blocking)
|
||||
- Returns `AsyncOperationHandle`
|
||||
|
||||
### 4. **Reference Counting**
|
||||
- Addressables tracks asset usage
|
||||
- Must manually release assets when done
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Mark Assets as Addressable
|
||||
|
||||
1. Select asset in Project window
|
||||
2. Inspector > Check "Addressable"
|
||||
3. Assign key (e.g., "Enemies/Goblin")
|
||||
|
||||
**OR via script:**
|
||||
```csharp
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.AddressableAssets;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
|
||||
AddressableAssetSettings.AddAssetEntry(guid, "MyAssetKey", "Default Local Group");
|
||||
#endif
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Create Groups
|
||||
|
||||
`Window > Asset Management > Addressables > Groups`
|
||||
|
||||
- **Default Local Group**: Bundled with build
|
||||
- **Remote Group**: Hosted on server (CDN)
|
||||
|
||||
---
|
||||
|
||||
## Basic Loading
|
||||
|
||||
### Load Asset Async
|
||||
|
||||
```csharp
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
|
||||
public class AssetLoader : MonoBehaviour {
|
||||
async void Start() {
|
||||
// ✅ Load asset asynchronously
|
||||
AsyncOperationHandle<GameObject> handle = Addressables.LoadAssetAsync<GameObject>("Enemies/Goblin");
|
||||
await handle.Task;
|
||||
|
||||
if (handle.Status == AsyncOperationStatus.Succeeded) {
|
||||
GameObject prefab = handle.Result;
|
||||
Instantiate(prefab);
|
||||
} else {
|
||||
Debug.LogError("Failed to load asset");
|
||||
}
|
||||
|
||||
// ⚠️ IMPORTANT: Release when done
|
||||
Addressables.Release(handle);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Load and Instantiate
|
||||
|
||||
```csharp
|
||||
async void SpawnEnemy() {
|
||||
// ✅ Load and instantiate in one step
|
||||
AsyncOperationHandle<GameObject> handle = Addressables.InstantiateAsync("Enemies/Goblin");
|
||||
await handle.Task;
|
||||
|
||||
GameObject enemy = handle.Result;
|
||||
// Use enemy...
|
||||
|
||||
// ✅ Release when destroying
|
||||
Addressables.ReleaseInstance(enemy);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Load Multiple Assets
|
||||
|
||||
```csharp
|
||||
async void LoadAllWeapons() {
|
||||
// Load all assets with label "Weapons"
|
||||
AsyncOperationHandle<IList<GameObject>> handle = Addressables.LoadAssetsAsync<GameObject>("Weapons", null);
|
||||
await handle.Task;
|
||||
|
||||
foreach (var weapon in handle.Result) {
|
||||
Debug.Log($"Loaded: {weapon.name}");
|
||||
}
|
||||
|
||||
Addressables.Release(handle);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Asset Labels (Tags)
|
||||
|
||||
### Assign Labels
|
||||
|
||||
1. `Window > Asset Management > Addressables > Groups`
|
||||
2. Select asset > Inspector > Labels > Add label (e.g., "Level1", "UI")
|
||||
|
||||
### Load by Label
|
||||
|
||||
```csharp
|
||||
// Load all assets with label "Level1"
|
||||
Addressables.LoadAssetsAsync<GameObject>("Level1", null);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Remote Content (DLC)
|
||||
|
||||
### Setup Remote Groups
|
||||
|
||||
1. Create new group: `Window > Addressables > Groups > Create New Group > Packed Assets`
|
||||
2. Group Settings:
|
||||
- **Build Path**: `ServerData/[BuildTarget]`
|
||||
- **Load Path**: `http://yourcdn.com/content/[BuildTarget]`
|
||||
|
||||
### Build Remote Content
|
||||
|
||||
1. `Window > Asset Management > Addressables > Build > New Build > Default Build Script`
|
||||
2. Upload `ServerData/` folder to CDN
|
||||
3. Game loads assets from remote server
|
||||
|
||||
---
|
||||
|
||||
## Preloading / Caching
|
||||
|
||||
### Download Dependencies
|
||||
|
||||
```csharp
|
||||
async void PreloadLevel() {
|
||||
// Download all assets in group without loading into memory
|
||||
AsyncOperationHandle handle = Addressables.DownloadDependenciesAsync("Level1");
|
||||
await handle.Task;
|
||||
|
||||
// Now "Level1" assets are cached, load instantly
|
||||
Addressables.Release(handle);
|
||||
}
|
||||
```
|
||||
|
||||
### Check Download Size
|
||||
|
||||
```csharp
|
||||
async void CheckDownloadSize() {
|
||||
AsyncOperationHandle<long> handle = Addressables.GetDownloadSizeAsync("Level1");
|
||||
await handle.Task;
|
||||
|
||||
long sizeInBytes = handle.Result;
|
||||
Debug.Log($"Download size: {sizeInBytes / (1024 * 1024)} MB");
|
||||
|
||||
Addressables.Release(handle);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Memory Management
|
||||
|
||||
### Release Assets
|
||||
|
||||
```csharp
|
||||
// ✅ Always release when done
|
||||
Addressables.Release(handle);
|
||||
|
||||
// ✅ For instantiated objects
|
||||
Addressables.ReleaseInstance(gameObject);
|
||||
```
|
||||
|
||||
### Check Reference Count
|
||||
|
||||
```csharp
|
||||
// Addressables uses reference counting
|
||||
// Asset is unloaded when refCount == 0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Asset References (Inspector-Assigned)
|
||||
|
||||
### Use AssetReference
|
||||
|
||||
```csharp
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
public class EnemySpawner : MonoBehaviour {
|
||||
// ✅ Assign in Inspector (drag & drop)
|
||||
public AssetReference enemyPrefab;
|
||||
|
||||
async void SpawnEnemy() {
|
||||
AsyncOperationHandle<GameObject> handle = enemyPrefab.InstantiateAsync();
|
||||
await handle.Task;
|
||||
|
||||
GameObject enemy = handle.Result;
|
||||
// Use enemy...
|
||||
|
||||
enemyPrefab.ReleaseInstance(enemy);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scenes
|
||||
|
||||
### Load Addressable Scene
|
||||
|
||||
```csharp
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
async void LoadScene() {
|
||||
AsyncOperationHandle<SceneInstance> handle = Addressables.LoadSceneAsync("MainMenu", LoadSceneMode.Additive);
|
||||
await handle.Task;
|
||||
|
||||
SceneInstance sceneInstance = handle.Result;
|
||||
// Scene loaded
|
||||
|
||||
// Unload scene
|
||||
await Addressables.UnloadSceneAsync(handle).Task;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Lazy Loading (Load on Demand)
|
||||
|
||||
```csharp
|
||||
Dictionary<string, AsyncOperationHandle<GameObject>> loadedAssets = new();
|
||||
|
||||
async Task<GameObject> GetAsset(string key) {
|
||||
if (!loadedAssets.ContainsKey(key)) {
|
||||
var handle = Addressables.LoadAssetAsync<GameObject>(key);
|
||||
await handle.Task;
|
||||
loadedAssets[key] = handle;
|
||||
}
|
||||
return loadedAssets[key].Result;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Cleanup on Scene Unload
|
||||
|
||||
```csharp
|
||||
void OnDestroy() {
|
||||
// Release all handles
|
||||
foreach (var handle in loadedAssets.Values) {
|
||||
Addressables.Release(handle);
|
||||
}
|
||||
loadedAssets.Clear();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Content Catalog Updates (Live Updates)
|
||||
|
||||
### Check for Catalog Updates
|
||||
|
||||
```csharp
|
||||
async void CheckForUpdates() {
|
||||
AsyncOperationHandle<List<string>> handle = Addressables.CheckForCatalogUpdates();
|
||||
await handle.Task;
|
||||
|
||||
if (handle.Result.Count > 0) {
|
||||
Debug.Log("Updates available");
|
||||
await Addressables.UpdateCatalogs(handle.Result).Task;
|
||||
}
|
||||
|
||||
Addressables.Release(handle);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
- **Preload** frequently used assets at startup
|
||||
- **Release** assets immediately when not needed
|
||||
- Use **labels** to batch-load related assets
|
||||
- **Cache** remote content for offline use
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Addressables Event Viewer
|
||||
|
||||
`Window > Asset Management > Addressables > Event Viewer`
|
||||
|
||||
- Shows all load/release operations
|
||||
- Memory usage per asset
|
||||
- Reference counts
|
||||
|
||||
### Addressables Profiler
|
||||
|
||||
`Window > Asset Management > Addressables > Profiler`
|
||||
|
||||
- Real-time asset usage
|
||||
- Bundle loading stats
|
||||
|
||||
---
|
||||
|
||||
## Migration from Resources
|
||||
|
||||
```csharp
|
||||
// ❌ OLD: Resources.Load (synchronous, blocks frame)
|
||||
GameObject prefab = Resources.Load<GameObject>("Enemies/Goblin");
|
||||
|
||||
// ✅ NEW: Addressables (async, non-blocking)
|
||||
var handle = await Addressables.LoadAssetAsync<GameObject>("Enemies/Goblin").Task;
|
||||
GameObject prefab = handle.Result;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unity3d.com/Packages/com.unity.addressables@2.0/manual/index.html
|
||||
- https://learn.unity.com/tutorial/addressables
|
||||
348
docs/engine-reference/unity/plugins/cinemachine.md
Normal file
348
docs/engine-reference/unity/plugins/cinemachine.md
Normal file
@@ -0,0 +1,348 @@
|
||||
# Unity 6.3 — Cinemachine
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Status:** Production-Ready
|
||||
**Package:** `com.unity.cinemachine` v3.0+ (Package Manager)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Cinemachine** is Unity's virtual camera system that enables professional, dynamic camera
|
||||
behavior without manual scripting. It's the industry standard for Unity camera work.
|
||||
|
||||
**Use Cinemachine for:**
|
||||
- 3rd person follow cameras
|
||||
- Cutscenes and cinematics
|
||||
- Camera blending and transitions
|
||||
- Dynamic camera framing
|
||||
- Screen shake and camera effects
|
||||
|
||||
**⚠️ Knowledge Gap:** Cinemachine 3.0 (Unity 6) is a major rewrite from 2.x.
|
||||
Many API names and components changed.
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### Install via Package Manager
|
||||
|
||||
1. `Window > Package Manager`
|
||||
2. Unity Registry > Search "Cinemachine"
|
||||
3. Install `Cinemachine` (version 3.0+)
|
||||
|
||||
---
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### 1. **Virtual Cameras**
|
||||
- Define camera behavior (position, rotation, lens)
|
||||
- Multiple virtual cameras can exist; only one is "live" at a time
|
||||
|
||||
### 2. **Cinemachine Brain**
|
||||
- Component on main Camera
|
||||
- Blends between virtual cameras
|
||||
- Applies virtual camera settings to Unity Camera
|
||||
|
||||
### 3. **Priorit**ies**
|
||||
- Virtual cameras have priority values
|
||||
- Highest priority camera is active
|
||||
- Blends smoothly when priority changes
|
||||
|
||||
---
|
||||
|
||||
## Basic Setup
|
||||
|
||||
### 1. Add Cinemachine Brain to Main Camera
|
||||
|
||||
```csharp
|
||||
// Automatically added when creating first virtual camera
|
||||
// Or manually: Add Component > Cinemachine Brain
|
||||
```
|
||||
|
||||
### 2. Create Virtual Camera
|
||||
|
||||
`GameObject > Cinemachine > Cinemachine Camera`
|
||||
|
||||
This creates a **CinemachineCamera** GameObject with default settings.
|
||||
|
||||
---
|
||||
|
||||
## Virtual Camera Components
|
||||
|
||||
### CinemachineCamera (Unity 6 / Cinemachine 3.0+)
|
||||
|
||||
```csharp
|
||||
using Unity.Cinemachine;
|
||||
|
||||
public class CameraController : MonoBehaviour {
|
||||
public CinemachineCamera virtualCamera;
|
||||
|
||||
void Start() {
|
||||
// Set priority (higher = active)
|
||||
virtualCamera.Priority = 10;
|
||||
|
||||
// Set follow target
|
||||
virtualCamera.Follow = playerTransform;
|
||||
|
||||
// Set look-at target
|
||||
virtualCamera.LookAt = playerTransform;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Follow Modes (Body Component)
|
||||
|
||||
### 3rd Person Follow (Orbital Follow)
|
||||
|
||||
```csharp
|
||||
// In Inspector:
|
||||
// CinemachineCamera > Body > 3rd Person Follow
|
||||
|
||||
// Configure:
|
||||
// - Shoulder Offset: (0.5, 0, 0) for over-shoulder
|
||||
// - Camera Distance: 5.0
|
||||
// - Vertical Damping: 0.5 (smooth up/down)
|
||||
```
|
||||
|
||||
### Framing Transposer (Smooth Follow)
|
||||
|
||||
```csharp
|
||||
// CinemachineCamera > Body > Position Composer
|
||||
|
||||
// Configure:
|
||||
// - Screen Position: Center (0.5, 0.5)
|
||||
// - Dead Zone: Don't move camera if target within zone
|
||||
// - Damping: Smooth following
|
||||
```
|
||||
|
||||
### Hard Lock (Exact Follow)
|
||||
|
||||
```csharp
|
||||
// CinemachineCamera > Body > Hard Lock to Target
|
||||
// Camera exactly matches target position (no offset or damping)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Aim Modes (Aim Component)
|
||||
|
||||
### Composer (Frame Target)
|
||||
|
||||
```csharp
|
||||
// CinemachineCamera > Aim > Composer
|
||||
|
||||
// Configure:
|
||||
// - Tracked Object Offset: Aim at target's head instead of feet
|
||||
// - Screen Position: Where target appears on screen
|
||||
// - Dead Zone: Don't rotate if target within zone
|
||||
```
|
||||
|
||||
### Look At Target
|
||||
|
||||
```csharp
|
||||
// CinemachineCamera > Aim > Rotate With Follow Target
|
||||
// Camera rotation matches target rotation (e.g., first-person)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Blending Between Cameras
|
||||
|
||||
### Priority-Based Blending
|
||||
|
||||
```csharp
|
||||
public CinemachineCamera normalCamera; // Priority: 10
|
||||
public CinemachineCamera aimCamera; // Priority: 5
|
||||
|
||||
void StartAiming() {
|
||||
// Set aim camera to higher priority
|
||||
aimCamera.Priority = 15; // Now active
|
||||
// Brain automatically blends from normalCamera to aimCamera
|
||||
}
|
||||
|
||||
void StopAiming() {
|
||||
aimCamera.Priority = 5; // Back to normal
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Blend Times
|
||||
|
||||
```csharp
|
||||
// Create Custom Blends Asset:
|
||||
// Assets > Create > Cinemachine > Cinemachine Blender Settings
|
||||
|
||||
// In Cinemachine Brain:
|
||||
// - Custom Blends = your asset
|
||||
// - Configure blend times per camera pair
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Camera Shake
|
||||
|
||||
### Impulse Source (Trigger Shake)
|
||||
|
||||
```csharp
|
||||
using Unity.Cinemachine;
|
||||
|
||||
public class ExplosionShake : MonoBehaviour {
|
||||
public CinemachineImpulseSource impulseSource;
|
||||
|
||||
void Explode() {
|
||||
// Trigger camera shake
|
||||
impulseSource.GenerateImpulse();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Impulse Listener (Receive Shake)
|
||||
|
||||
```csharp
|
||||
// Add to CinemachineCamera:
|
||||
// Add Component > CinemachineImpulseListener
|
||||
|
||||
// Impulse listener automatically receives shake from nearby Impulse Sources
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Freelook Camera (Third Person with Mouse Look)
|
||||
|
||||
### Cinemachine Free Look
|
||||
|
||||
```csharp
|
||||
// GameObject > Cinemachine > Cinemachine Free Look
|
||||
|
||||
// Creates 3 rigs (Top, Middle, Bottom) that blend based on vertical input
|
||||
// Configure:
|
||||
// - Orbit Radius: Distance from target
|
||||
// - Height Offset: Camera height at each rig
|
||||
// - X/Y Axis: Mouse or joystick input
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## State-Driven Camera (Anim ator-Based)
|
||||
|
||||
### Cinemachine State-Driven Camera
|
||||
|
||||
```csharp
|
||||
// GameObject > Cinemachine > Cinemachine State-Driven Camera
|
||||
|
||||
// Configure:
|
||||
// - Animated Target: Character with Animator
|
||||
// - Layer: Animator layer to track
|
||||
// - State: Assign camera per animation state (Idle, Run, Jump, etc.)
|
||||
|
||||
// Camera automatically switches based on animation state
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dolly Tracks (Cutscenes)
|
||||
|
||||
### Cinemachine Dolly Track
|
||||
|
||||
```csharp
|
||||
// 1. Create Spline: GameObject > Cinemachine > Cinemachine Spline
|
||||
|
||||
// 2. Create Dolly Camera:
|
||||
// GameObject > Cinemachine > Cinemachine Camera
|
||||
// Body > Spline Dolly
|
||||
// Assign Spline
|
||||
|
||||
// 3. Animate dolly position on spline (Timeline or script)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Third-Person Follow Camera
|
||||
|
||||
```csharp
|
||||
// CinemachineCamera
|
||||
// - Follow: Player Transform
|
||||
// - Body: 3rd Person Follow (shoulder offset, distance: 5)
|
||||
// - Aim: Composer (frame player at center)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Aiming Camera (Zoom In)
|
||||
|
||||
```csharp
|
||||
// Normal Camera (Priority 10):
|
||||
// - Distance: 5.0
|
||||
|
||||
// Aim Camera (Priority 5):
|
||||
// - Distance: 2.0
|
||||
// - FOV: Narrower
|
||||
|
||||
// Script:
|
||||
void StartAiming() {
|
||||
aimCamera.Priority = 15; // Blend to aim camera
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Cutscene Camera Sequence
|
||||
|
||||
```csharp
|
||||
// Use Timeline:
|
||||
// 1. Create Timeline (Assets > Create > Timeline)
|
||||
// 2. Add Cinemachine Track
|
||||
// 3. Add virtual cameras as clips
|
||||
// 4. Timeline automatically blends between cameras
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration from Cinemachine 2.x (Unity 2021)
|
||||
|
||||
### API Changes (Unity 6 / Cinemachine 3.0)
|
||||
|
||||
```csharp
|
||||
// ❌ OLD (Cinemachine 2.x):
|
||||
CinemachineVirtualCamera vcam;
|
||||
vcam.m_Follow = target;
|
||||
|
||||
// ✅ NEW (Cinemachine 3.0+):
|
||||
CinemachineCamera vcam;
|
||||
vcam.Follow = target; // Cleaner API
|
||||
```
|
||||
|
||||
**Major Changes:**
|
||||
- `CinemachineVirtualCamera` → `CinemachineCamera`
|
||||
- `m_Follow`, `m_LookAt` → `Follow`, `LookAt` (no "m_" prefix)
|
||||
- Components renamed for clarity
|
||||
- Better performance
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
- Limit active virtual cameras (only activate when needed)
|
||||
- Use lower-priority cameras instead of destroying/creating
|
||||
- Disable virtual cameras when far from player
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Cinemachine Debug
|
||||
|
||||
```csharp
|
||||
// Window > Analysis > Cinemachine Debugger
|
||||
// Shows active camera, blend info, shot quality
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unity3d.com/Packages/com.unity.cinemachine@3.0/manual/index.html
|
||||
- https://learn.unity.com/tutorial/cinemachine
|
||||
420
docs/engine-reference/unity/plugins/dots-entities.md
Normal file
420
docs/engine-reference/unity/plugins/dots-entities.md
Normal file
@@ -0,0 +1,420 @@
|
||||
# Unity 6.3 — DOTS / Entities (ECS)
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Status:** Production-Ready (Entities 1.3+, Unity 6.3 LTS)
|
||||
**Package:** `com.unity.entities` (Package Manager)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**DOTS (Data-Oriented Technology Stack)** is Unity's high-performance ECS (Entity Component System)
|
||||
framework. It's designed for games with massive scale (1000s-10,000s of entities).
|
||||
|
||||
**Use DOTS for:**
|
||||
- RTS games (1000s of units)
|
||||
- Simulations (crowds, traffic, physics)
|
||||
- Procedural content generation
|
||||
- Performance-critical systems
|
||||
|
||||
**DON'T use DOTS for:**
|
||||
- Small games (overhead not worth it)
|
||||
- Gameplay requiring frequent structural changes
|
||||
- Heavy use of UnityEngine APIs (MonoBehaviour is easier)
|
||||
|
||||
**⚠️ Knowledge Gap:** Entities 1.0+ (Unity 6) is a complete rewrite from 0.x.
|
||||
Many tutorials for Entities 0.x are now outdated.
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### Install via Package Manager
|
||||
|
||||
1. `Window > Package Manager`
|
||||
2. Unity Registry > Search "Entities"
|
||||
3. Install:
|
||||
- `Entities` (ECS core)
|
||||
- `Burst` (LLVM compiler)
|
||||
- `Jobs` (auto-installed)
|
||||
- `Mathematics` (SIMD math)
|
||||
|
||||
---
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### 1. **Entity**
|
||||
- Lightweight ID (int)
|
||||
- No behavior, just an identifier
|
||||
|
||||
### 2. **Component**
|
||||
- Data only (no methods)
|
||||
- Struct implementing `IComponentData`
|
||||
|
||||
### 3. **System**
|
||||
- Logic that operates on components
|
||||
- Struct implementing `ISystem`
|
||||
|
||||
### 4. **Archetype**
|
||||
- Unique combination of component types
|
||||
- Entities with same components share archetype
|
||||
|
||||
---
|
||||
|
||||
## Basic ECS Pattern
|
||||
|
||||
### Define Component
|
||||
|
||||
```csharp
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
|
||||
// ✅ Component: Data only, no methods
|
||||
public struct Position : IComponentData {
|
||||
public float3 Value;
|
||||
}
|
||||
|
||||
public struct Velocity : IComponentData {
|
||||
public float3 Value;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Define System
|
||||
|
||||
```csharp
|
||||
using Unity.Entities;
|
||||
using Unity.Burst;
|
||||
|
||||
// ✅ System: Logic that processes entities
|
||||
[BurstCompile]
|
||||
public partial struct MovementSystem : ISystem {
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState state) {
|
||||
float deltaTime = SystemAPI.Time.DeltaTime;
|
||||
|
||||
// Query all entities with Position + Velocity
|
||||
foreach (var (transform, velocity) in
|
||||
SystemAPI.Query<RefRW<Position>, RefRO<Velocity>>()) {
|
||||
|
||||
transform.ValueRW.Value += velocity.ValueRO.Value * deltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Create Entities
|
||||
|
||||
```csharp
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
|
||||
public partial class EntitySpawner : SystemBase {
|
||||
protected override void OnUpdate() {
|
||||
var em = EntityManager;
|
||||
|
||||
// Create entity
|
||||
Entity entity = em.CreateEntity();
|
||||
|
||||
// Add components
|
||||
em.AddComponentData(entity, new Position { Value = float3.zero });
|
||||
em.AddComponentData(entity, new Velocity { Value = new float3(1, 0, 0) });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Hybrid ECS (MonoBehaviour + ECS)
|
||||
|
||||
### Baker (Convert GameObject to Entity)
|
||||
|
||||
```csharp
|
||||
using Unity.Entities;
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayerAuthoring : MonoBehaviour {
|
||||
public float speed;
|
||||
}
|
||||
|
||||
public class PlayerBaker : Baker<PlayerAuthoring> {
|
||||
public override void Bake(PlayerAuthoring authoring) {
|
||||
var entity = GetEntity(TransformUsageFlags.Dynamic);
|
||||
|
||||
AddComponent(entity, new Position { Value = authoring.transform.position });
|
||||
AddComponent(entity, new Velocity { Value = new float3(authoring.speed, 0, 0) });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**How it works:**
|
||||
1. Add `PlayerAuthoring` to GameObject in editor
|
||||
2. Baker automatically converts to Entity at runtime
|
||||
3. Entity has Position + Velocity components
|
||||
|
||||
---
|
||||
|
||||
## Queries
|
||||
|
||||
### Query All Entities with Components
|
||||
|
||||
```csharp
|
||||
foreach (var (position, velocity) in
|
||||
SystemAPI.Query<RefRW<Position>, RefRO<Velocity>>()) {
|
||||
|
||||
position.ValueRW.Value += velocity.ValueRO.Value * deltaTime;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Query with Entity
|
||||
|
||||
```csharp
|
||||
foreach (var (position, velocity, entity) in
|
||||
SystemAPI.Query<RefRW<Position>, RefRO<Velocity>>().WithEntityAccess()) {
|
||||
|
||||
// Access entity ID
|
||||
Debug.Log($"Entity: {entity}");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Query with Filters
|
||||
|
||||
```csharp
|
||||
// Only entities with "Enemy" tag
|
||||
foreach (var position in
|
||||
SystemAPI.Query<RefRW<Position>>().WithAll<EnemyTag>()) {
|
||||
// Process enemies only
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Jobs (Parallel Execution)
|
||||
|
||||
### IJobEntity (Parallel Foreach)
|
||||
|
||||
```csharp
|
||||
using Unity.Entities;
|
||||
using Unity.Burst;
|
||||
|
||||
[BurstCompile]
|
||||
public partial struct MovementJob : IJobEntity {
|
||||
public float DeltaTime;
|
||||
|
||||
// Execute runs in parallel for each entity
|
||||
void Execute(ref Position position, in Velocity velocity) {
|
||||
position.Value += velocity.Value * DeltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
public partial struct MovementSystem : ISystem {
|
||||
public void OnUpdate(ref SystemState state) {
|
||||
var job = new MovementJob {
|
||||
DeltaTime = SystemAPI.Time.DeltaTime
|
||||
};
|
||||
job.ScheduleParallel(); // Parallel execution
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Burst Compiler (Performance)
|
||||
|
||||
### Enable Burst
|
||||
|
||||
```csharp
|
||||
using Unity.Burst;
|
||||
|
||||
[BurstCompile] // 10-100x faster than regular C#
|
||||
public partial struct MySystem : ISystem {
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState state) {
|
||||
// Burst-compiled code
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Burst Restrictions:**
|
||||
- No managed references (classes, strings, etc.)
|
||||
- Only blittable types (structs, primitives, Unity.Mathematics types)
|
||||
- No exceptions
|
||||
|
||||
---
|
||||
|
||||
## Entity Command Buffers (Structural Changes)
|
||||
|
||||
### Deferred Structural Changes
|
||||
|
||||
```csharp
|
||||
using Unity.Entities;
|
||||
|
||||
public partial struct SpawnSystem : ISystem {
|
||||
public void OnUpdate(ref SystemState state) {
|
||||
var ecb = new EntityCommandBuffer(Allocator.Temp);
|
||||
|
||||
// Defer entity creation (don't modify during iteration)
|
||||
foreach (var spawner in SystemAPI.Query<Spawner>()) {
|
||||
Entity newEntity = ecb.CreateEntity();
|
||||
ecb.AddComponent(newEntity, new Position { Value = spawner.SpawnPos });
|
||||
}
|
||||
|
||||
ecb.Playback(state.EntityManager); // Apply changes
|
||||
ecb.Dispose();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dynamic Buffers (Array-Like Components)
|
||||
|
||||
### Define Dynamic Buffer
|
||||
|
||||
```csharp
|
||||
public struct PathWaypoint : IBufferElementData {
|
||||
public float3 Position;
|
||||
}
|
||||
```
|
||||
|
||||
### Use Dynamic Buffer
|
||||
|
||||
```csharp
|
||||
// Add buffer to entity
|
||||
var buffer = EntityManager.AddBuffer<PathWaypoint>(entity);
|
||||
buffer.Add(new PathWaypoint { Position = new float3(0, 0, 0) });
|
||||
buffer.Add(new PathWaypoint { Position = new float3(10, 0, 0) });
|
||||
|
||||
// Query buffer
|
||||
foreach (var buffer in SystemAPI.Query<DynamicBuffer<PathWaypoint>>()) {
|
||||
foreach (var waypoint in buffer) {
|
||||
Debug.Log(waypoint.Position);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tags (Zero-Size Components)
|
||||
|
||||
### Define Tag
|
||||
|
||||
```csharp
|
||||
public struct EnemyTag : IComponentData { } // Empty component = tag
|
||||
```
|
||||
|
||||
### Use Tag for Filtering
|
||||
|
||||
```csharp
|
||||
// Only process entities with EnemyTag
|
||||
foreach (var position in
|
||||
SystemAPI.Query<RefRW<Position>>().WithAll<EnemyTag>()) {
|
||||
// Enemy-specific logic
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## System Ordering
|
||||
|
||||
### Explicit Ordering
|
||||
|
||||
```csharp
|
||||
[UpdateBefore(typeof(PhysicsSystem))]
|
||||
public partial struct InputSystem : ISystem { }
|
||||
|
||||
[UpdateAfter(typeof(PhysicsSystem))]
|
||||
public partial struct RenderSystem : ISystem { }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Patterns
|
||||
|
||||
### Chunk Iteration (Maximum Performance)
|
||||
|
||||
```csharp
|
||||
public void OnUpdate(ref SystemState state) {
|
||||
var query = SystemAPI.QueryBuilder().WithAll<Position, Velocity>().Build();
|
||||
|
||||
var chunks = query.ToArchetypeChunkArray(Allocator.Temp);
|
||||
var positionType = state.GetComponentTypeHandle<Position>();
|
||||
var velocityType = state.GetComponentTypeHandle<Velocity>(true); // Read-only
|
||||
|
||||
foreach (var chunk in chunks) {
|
||||
var positions = chunk.GetNativeArray(ref positionType);
|
||||
var velocities = chunk.GetNativeArray(ref velocityType);
|
||||
|
||||
for (int i = 0; i < chunk.Count; i++) {
|
||||
positions[i] = new Position {
|
||||
Value = positions[i].Value + velocities[i].Value * deltaTime
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
chunks.Dispose();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration from MonoBehaviour
|
||||
|
||||
```csharp
|
||||
// ❌ OLD: MonoBehaviour (OOP)
|
||||
public class Enemy : MonoBehaviour {
|
||||
public float speed;
|
||||
void Update() {
|
||||
transform.position += Vector3.forward * speed * Time.deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ NEW: DOTS (ECS)
|
||||
public struct EnemyData : IComponentData {
|
||||
public float Speed;
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
public partial struct EnemyMovementSystem : ISystem {
|
||||
public void OnUpdate(ref SystemState state) {
|
||||
float dt = SystemAPI.Time.DeltaTime;
|
||||
foreach (var (transform, enemy) in
|
||||
SystemAPI.Query<RefRW<LocalTransform>, RefRO<EnemyData>>()) {
|
||||
transform.ValueRW.Position += new float3(0, 0, enemy.ValueRO.Speed * dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Entities Hierarchy Window
|
||||
|
||||
`Window > Entities > Hierarchy`
|
||||
|
||||
- Shows all entities and their components
|
||||
- Filter by archetype, component type
|
||||
|
||||
### Entities Profiler
|
||||
|
||||
`Window > Analysis > Profiler > Entities`
|
||||
|
||||
- System execution times
|
||||
- Memory usage per archetype
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/index.html
|
||||
- https://docs.unity3d.com/Packages/com.unity.burst@1.8/manual/index.html
|
||||
- https://learn.unity.com/tutorial/entity-component-system
|
||||
Reference in New Issue
Block a user