添加 claude code game studios 到项目
This commit is contained in:
63
docs/engine-reference/README.md
Normal file
63
docs/engine-reference/README.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Engine Reference Documentation
|
||||
|
||||
This directory contains curated, version-pinned documentation snapshots for the
|
||||
game engine(s) used in this project. These files exist because **LLM knowledge
|
||||
has a cutoff date** and game engines update frequently.
|
||||
|
||||
## Why This Exists
|
||||
|
||||
Claude's training data has a knowledge cutoff (currently May 2025). Game engines
|
||||
like Godot, Unity, and Unreal ship updates that introduce breaking API changes,
|
||||
new features, and deprecated patterns. Without these reference files, agents will
|
||||
suggest outdated code.
|
||||
|
||||
## Structure
|
||||
|
||||
Each engine gets its own directory:
|
||||
|
||||
```
|
||||
<engine>/
|
||||
├── VERSION.md # Pinned version, verification date, knowledge gap window
|
||||
├── breaking-changes.md # API changes between versions, organized by risk level
|
||||
├── deprecated-apis.md # "Don't use X → Use Y" lookup tables
|
||||
├── current-best-practices.md # New practices not in model training data
|
||||
└── modules/ # Per-subsystem quick references (~150 lines max each)
|
||||
├── rendering.md
|
||||
├── physics.md
|
||||
└── ...
|
||||
```
|
||||
|
||||
## How Agents Use These Files
|
||||
|
||||
Engine-specialist agents are instructed to:
|
||||
|
||||
1. Read `VERSION.md` to confirm the current engine version
|
||||
2. Check `deprecated-apis.md` before suggesting any engine API
|
||||
3. Consult `breaking-changes.md` for version-specific concerns
|
||||
4. Read relevant `modules/*.md` for subsystem-specific work
|
||||
|
||||
## Maintenance
|
||||
|
||||
### When to Update
|
||||
|
||||
- After upgrading the engine version
|
||||
- When the LLM model is updated (new knowledge cutoff)
|
||||
- After running `/refresh-docs` (if available)
|
||||
- When you discover an API the model gets wrong
|
||||
|
||||
### How to Update
|
||||
|
||||
1. Update `VERSION.md` with the new engine version and date
|
||||
2. Add new entries to `breaking-changes.md` for the version transition
|
||||
3. Move newly deprecated APIs into `deprecated-apis.md`
|
||||
4. Update `current-best-practices.md` with new patterns
|
||||
5. Update relevant `modules/*.md` with API changes
|
||||
6. Set "Last verified" dates on all modified files
|
||||
|
||||
### Quality Rules
|
||||
|
||||
- Every file must have a "Last verified: YYYY-MM-DD" date
|
||||
- Keep module files under 150 lines (context budget)
|
||||
- Include code examples showing correct/incorrect patterns
|
||||
- Link to official documentation URLs for verification
|
||||
- Only document things that differ from the model's training data
|
||||
31
docs/engine-reference/godot/VERSION.md
Normal file
31
docs/engine-reference/godot/VERSION.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Godot Engine — Version Reference
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Engine Version** | Godot 4.6 |
|
||||
| **Release Date** | January 2026 |
|
||||
| **Project Pinned** | 2026-02-12 |
|
||||
| **Last Docs Verified** | 2026-02-12 |
|
||||
| **LLM Knowledge Cutoff** | May 2025 |
|
||||
|
||||
## Knowledge Gap Warning
|
||||
|
||||
The LLM's training data likely covers Godot up to ~4.3. Versions 4.4, 4.5,
|
||||
and 4.6 introduced significant changes that the model does NOT know about.
|
||||
Always cross-reference this directory before suggesting Godot API calls.
|
||||
|
||||
## Post-Cutoff Version Timeline
|
||||
|
||||
| Version | Release | Risk Level | Key Theme |
|
||||
|---------|---------|------------|-----------|
|
||||
| 4.4 | ~Mid 2025 | MEDIUM | Jolt physics option, FileAccess return types, shader texture type changes |
|
||||
| 4.5 | ~Late 2025 | HIGH | Accessibility (AccessKit), variadic args, @abstract, shader baker, SMAA |
|
||||
| 4.6 | Jan 2026 | HIGH | Jolt default, glow rework, D3D12 default on Windows, IK restored |
|
||||
|
||||
## Verified Sources
|
||||
|
||||
- Official docs: https://docs.godotengine.org/en/stable/
|
||||
- 4.5→4.6 migration: https://docs.godotengine.org/en/stable/tutorials/migrating/upgrading_to_godot_4.6.html
|
||||
- 4.4→4.5 migration: https://docs.godotengine.org/en/stable/tutorials/migrating/upgrading_to_godot_4.5.html
|
||||
- Changelog: https://github.com/godotengine/godot/blob/master/CHANGELOG.md
|
||||
- Release notes: https://godotengine.org/releases/4.6/
|
||||
70
docs/engine-reference/godot/breaking-changes.md
Normal file
70
docs/engine-reference/godot/breaking-changes.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Godot — Breaking Changes
|
||||
|
||||
Last verified: 2026-02-12
|
||||
|
||||
Changes between Godot versions, focused on post-LLM-cutoff changes (4.4+).
|
||||
|
||||
## 4.5 → 4.6 (Jan 2026 — POST-CUTOFF, HIGH RISK)
|
||||
|
||||
| Subsystem | Change | Details |
|
||||
|-----------|--------|---------|
|
||||
| Physics | Jolt is now the DEFAULT 3D physics engine | New projects use Jolt automatically. Existing projects keep their setting. Some HingeJoint3D properties (like `damp`) only work with GodotPhysics. |
|
||||
| Rendering | Glow processes BEFORE tonemapping | Was after tonemapping. Scenes with glow will look different. Adjust intensity/blend in WorldEnvironment. |
|
||||
| Rendering | D3D12 default on Windows | Was Vulkan. For better driver compatibility. |
|
||||
| Rendering | AgX tonemapper new controls | White point and contrast parameters added. |
|
||||
| Core | Quaternion initializes to identity | Was zero. Unlikely to affect most code but technically breaking. |
|
||||
| UI | Dual-focus system | Mouse/touch focus now separate from keyboard/gamepad focus. Visual feedback differs by input method. |
|
||||
| Animation | IK system fully restored | CCDIK, FABRIK, Jacobian IK, Spline IK, TwoBoneIK via SkeletonModifier3D nodes. |
|
||||
| Editor | New "Modern" theme default | Grayscale replaces blue-tint. Restore: Editor Settings → Interface → Theme → Style: Classic |
|
||||
| Editor | "Select Mode" keybind changed | New "Select Mode" (v key) prevents accidental transforms. Old mode renamed "Transform Mode" (q key). |
|
||||
| 2D | TileMapLayer scene tile rotation | Scene tiles can now be rotated like atlas tiles. |
|
||||
| Localization | CSV plural form support | No longer requires Gettext for plurals. Context columns added. |
|
||||
| C# | Automatic string extraction | Translation strings auto-extracted from C# code. |
|
||||
| Plugins | New EditorDock class | Specialized container for plugin docks with layout control. |
|
||||
|
||||
## 4.4 → 4.5 (Late 2025 — POST-CUTOFF, HIGH RISK)
|
||||
|
||||
| Subsystem | Change | Details |
|
||||
|-----------|--------|---------|
|
||||
| GDScript | Variadic arguments added | Functions can accept `...` arbitrary params — new language feature |
|
||||
| GDScript | `@abstract` decorator | Abstract classes and methods now enforceable |
|
||||
| GDScript | Script backtracing | Detailed call stacks available even in Release builds |
|
||||
| Rendering | Stencil buffer support | New capability for advanced visual effects |
|
||||
| Rendering | SMAA 1x antialiasing | New post-processing AA option |
|
||||
| Rendering | Shader Baker | Pre-compiles shaders — reportedly 20x faster startup on some demos |
|
||||
| Rendering | Bent normal maps, specular occlusion | New material features |
|
||||
| Accessibility | Screen reader support | Control nodes work with accessibility tools via AccessKit |
|
||||
| Editor | Live translation preview | Test GUI layouts in different languages in-editor |
|
||||
| Physics | 3D interpolation rearchitected | Moved from RenderingServer to SceneTree. API unchanged but internals differ. |
|
||||
| Animation | BoneConstraint3D | New: AimModifier3D, CopyTransformModifier3D, ConvertTransformModifier3D |
|
||||
| Resources | `duplicate_deep()` added | New explicit method for deep duplication of nested resources |
|
||||
| Navigation | Dedicated 2D navigation server | No longer a proxy to 3D navigation; smaller export for 2D games |
|
||||
| UI | FoldableContainer node | New accordion-style container for collapsible UI sections |
|
||||
| UI | Recursive Control behavior | Disable mouse/focus interactions across entire node hierarchies |
|
||||
| Platform | visionOS export support | New platform target |
|
||||
| Platform | SDL3 gamepad driver | Delegated gamepad handling to SDL library |
|
||||
| Platform | Android 16KB page support | Required for Google Play targeting Android 15+ |
|
||||
|
||||
## 4.3 → 4.4 (Mid 2025 — NEAR CUTOFF, VERIFY)
|
||||
|
||||
| Subsystem | Change | Details |
|
||||
|-----------|--------|---------|
|
||||
| Core | `FileAccess.store_*` return `bool` | Was `void`. Methods: `store_8`, `store_16`, `store_32`, `store_64`, `store_buffer`, `store_csv_line`, `store_double`, `store_float`, `store_half`, `store_line`, `store_pascal_string`, `store_real`, `store_string`, `store_var` |
|
||||
| Core | `OS.execute_with_pipe` | Added optional `blocking` parameter |
|
||||
| Core | `RegEx.compile/create_from_string` | Added optional `show_error` parameter |
|
||||
| Rendering | `RenderingDevice.draw_list_begin` | Many parameters removed; `breadcrumb` parameter added |
|
||||
| Rendering | Shader texture types | Parameter/return types changed from `Texture2D` to `Texture` |
|
||||
| Particles | `.restart()` method | Added optional `keep_seed` parameter (CPU/GPU 2D/3D) |
|
||||
| GUI | `RichTextLabel.push_meta` | Added optional `tooltip` parameter |
|
||||
| GUI | `GraphEdit.connect_node` | Added optional `keep_alive` parameter |
|
||||
|
||||
## 4.2 → 4.3 (In Training Data — LOW RISK)
|
||||
|
||||
| Subsystem | Change | Details |
|
||||
|-----------|--------|---------|
|
||||
| Animation | `Skeleton3D.add_bone` returns `int32` | Was `void` |
|
||||
| Animation | `bone_pose_updated` signal | Replaced by `skeleton_updated` |
|
||||
| TileMap | `TileMapLayer` replaces `TileMap` | One node per layer instead of multi-layer single node |
|
||||
| Navigation | `NavigationRegion2D` | Removed `avoidance_layers`, `constrain_avoidance` properties |
|
||||
| Editor | `EditorSceneFormatImporterFBX` | Renamed to `EditorSceneFormatImporterFBX2GLTF` |
|
||||
| Animation | AnimationMixer base class | AnimationPlayer and AnimationTree now extend AnimationMixer |
|
||||
107
docs/engine-reference/godot/current-best-practices.md
Normal file
107
docs/engine-reference/godot/current-best-practices.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Godot — Current Best Practices
|
||||
|
||||
Last verified: 2026-02-12 | Engine: Godot 4.6
|
||||
|
||||
Practices that are **new or changed** since the model's training data (~4.3).
|
||||
This supplements (not replaces) the agent's built-in knowledge.
|
||||
|
||||
## GDScript (4.5+)
|
||||
|
||||
- **Variadic arguments**: Functions can accept arbitrary parameter counts
|
||||
```gdscript
|
||||
func log_values(prefix: String, values: Variant...) -> void:
|
||||
for v in values:
|
||||
print(prefix, ": ", v)
|
||||
```
|
||||
|
||||
- **Abstract classes and methods**: Use `@abstract` to enforce inheritance
|
||||
```gdscript
|
||||
@abstract
|
||||
class_name BaseEnemy extends CharacterBody3D
|
||||
|
||||
@abstract
|
||||
func get_attack_pattern() -> Array[Attack]:
|
||||
pass # Subclasses MUST override
|
||||
```
|
||||
|
||||
- **Script backtracing**: Detailed call stacks available even in Release builds
|
||||
|
||||
## Physics (4.6)
|
||||
|
||||
- **Jolt Physics is the default 3D engine** for new projects
|
||||
- Better determinism and stability than GodotPhysics3D
|
||||
- Some HingeJoint3D properties (`damp`) only work with GodotPhysics
|
||||
- Switch: Project Settings → Physics → 3D → Physics Engine
|
||||
- 2D physics unchanged (still Godot Physics 2D)
|
||||
|
||||
## Rendering (4.6)
|
||||
|
||||
- **D3D12 is the default backend on Windows** (was Vulkan) — for better driver compatibility
|
||||
- **Glow now processes before tonemapping** with screen blending mode — existing glow setups may look different
|
||||
- **SSR overhauled** — significant improvement in realism, stability, and performance
|
||||
- **AgX tonemapper** — new white point and contrast controls
|
||||
|
||||
## Rendering (4.5)
|
||||
|
||||
- **Shader Baker**: Pre-compile shaders to eliminate startup hitching
|
||||
- **SMAA 1x**: New AA option — sharper than FXAA, cheaper than TAA
|
||||
- **Stencil buffer**: Available for advanced masking/portal effects
|
||||
- **Bent normal maps**: Directional occlusion in normal map textures
|
||||
- **Specular occlusion**: Ambient occlusion now affects reflections
|
||||
|
||||
## Accessibility (4.5+)
|
||||
|
||||
- **Screen reader support**: Control nodes integrate with accessibility tools via AccessKit
|
||||
- **Live translation preview**: Test GUI layouts in different languages directly in-editor
|
||||
- **FoldableContainer**: New accordion-style UI node for collapsible sections
|
||||
- **Recursive Control disable**: Disable mouse/focus interactions for entire node hierarchies with a single property
|
||||
|
||||
## Animation (4.5+)
|
||||
|
||||
- **BoneConstraint3D**: Bind bones to other bones with modifiers
|
||||
- AimModifier3D, CopyTransformModifier3D, ConvertTransformModifier3D
|
||||
|
||||
## Animation (4.6)
|
||||
|
||||
- **IK system fully restored**: Complete inverse kinematics reintroduced for 3D
|
||||
- Available modifiers: CCDIK, FABRIK, Jacobian IK, Spline IK, TwoBoneIK
|
||||
- Applied via `SkeletonModifier3D` nodes
|
||||
|
||||
## Resources (4.5+)
|
||||
|
||||
- **`duplicate_deep()`**: Explicit deep duplication for nested resource trees
|
||||
- Old `duplicate()` behavior retained for backward compatibility
|
||||
- Use `duplicate_deep()` when you need per-instance copies of nested resources
|
||||
|
||||
## Navigation (4.5+)
|
||||
|
||||
- **Dedicated 2D navigation server**: No longer proxied through 3D NavigationServer
|
||||
- Reduces export binary size for 2D-only games
|
||||
|
||||
## UI (4.6)
|
||||
|
||||
- **Dual-focus system**: Mouse/touch focus is now separate from keyboard/gamepad focus
|
||||
- Visual feedback differs depending on input method
|
||||
- Consider this when designing custom focus behavior
|
||||
|
||||
## Editor Workflow (4.6)
|
||||
|
||||
- Flexible dock drag-and-drop with blue outline preview (including bottom panel)
|
||||
- Most panels support floating windows (except Debugger)
|
||||
- New keyboard shortcuts: Alt+O (Output), Alt+S (Shader)
|
||||
- Export variable auto-generation: drag resource from FileSystem into script editor
|
||||
- Live preview in Quick Open dialog when "Live Preview" enabled
|
||||
- New "Select Mode" (v key) prevents accidental transforms; old mode renamed "Transform Mode" (q key)
|
||||
|
||||
## Tooling
|
||||
|
||||
- **ripgrep has no `gdscript` type**: `*.gd` is registered under `gap` (GAP programming language).
|
||||
`rg --type gdscript` is a hard error — the search never executes.
|
||||
Always use `rg --glob "*.gd"` (shell) or `glob: "*.gd"` (Grep tool) to filter GDScript files.
|
||||
|
||||
## Platform (4.5+)
|
||||
|
||||
- **visionOS export**: First new platform since open-sourcing (windowed app mode)
|
||||
- **SDL3 gamepad driver**: Better cross-platform gamepad support
|
||||
- **Android**: Edge-to-edge display, camera feed access, 16KB page support (Android 15+)
|
||||
- **Linux**: Wayland subwindow support for multi-window capability
|
||||
43
docs/engine-reference/godot/deprecated-apis.md
Normal file
43
docs/engine-reference/godot/deprecated-apis.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Godot — Deprecated APIs
|
||||
|
||||
Last verified: 2026-02-12
|
||||
|
||||
If an agent suggests any API in the "Deprecated" column, it MUST be replaced
|
||||
with the "Use Instead" column.
|
||||
|
||||
## Nodes & Classes
|
||||
|
||||
| Deprecated | Use Instead | Since | Notes |
|
||||
|------------|-------------|-------|-------|
|
||||
| `TileMap` | `TileMapLayer` | 4.3 | One node per layer instead of multi-layer node |
|
||||
| `VisibilityNotifier2D` | `VisibleOnScreenNotifier2D` | 4.0 | Renamed for clarity |
|
||||
| `VisibilityNotifier3D` | `VisibleOnScreenNotifier3D` | 4.0 | Renamed for clarity |
|
||||
| `YSort` | `Node2D.y_sort_enabled` | 4.0 | Property on Node2D, not a separate node |
|
||||
| `Navigation2D` / `Navigation3D` | `NavigationServer2D` / `NavigationServer3D` | 4.0 | Server-based API |
|
||||
| `EditorSceneFormatImporterFBX` | `EditorSceneFormatImporterFBX2GLTF` | 4.3 | Renamed |
|
||||
|
||||
## Methods & Properties
|
||||
|
||||
| Deprecated | Use Instead | Since | Notes |
|
||||
|------------|-------------|-------|-------|
|
||||
| `yield()` | `await signal` | 4.0 | GDScript 2.0 coroutine syntax |
|
||||
| `connect("signal", obj, "method")` | `signal.connect(callable)` | 4.0 | Callable-based connections |
|
||||
| `instance()` | `instantiate()` | 4.0 | Renamed |
|
||||
| `PackedScene.instance()` | `PackedScene.instantiate()` | 4.0 | Renamed |
|
||||
| `get_world()` | `get_world_3d()` | 4.0 | Explicit 2D/3D split |
|
||||
| `OS.get_ticks_msec()` | `Time.get_ticks_msec()` | 4.0 | Time singleton preferred |
|
||||
| `duplicate()` for nested resources | `duplicate_deep()` | 4.5 | Explicit deep copy control |
|
||||
| `Skeleton3D` signal `bone_pose_updated` | `skeleton_updated` | 4.3 | Renamed |
|
||||
| `AnimationPlayer.method_call_mode` | `AnimationMixer.callback_mode_method` | 4.3 | Moved to base class |
|
||||
| `AnimationPlayer.playback_active` | `AnimationMixer.active` | 4.3 | Moved to base class |
|
||||
|
||||
## Patterns (Not Just APIs)
|
||||
|
||||
| Deprecated Pattern | Use Instead | Why |
|
||||
|--------------------|-------------|-----|
|
||||
| String-based `connect()` | Typed signal connections | Type-safe, refactor-friendly |
|
||||
| `$NodePath` in `_process()` | `@onready var` cached reference | Performance: path lookup every frame |
|
||||
| Untyped `Array` / `Dictionary` | `Array[Type]`, typed variables | GDScript compiler optimizations |
|
||||
| `Texture2D` in shader parameters | `Texture` base type | Changed in 4.4 |
|
||||
| Manual post-process viewport chains | `Compositor` + `CompositorEffect` | Structured post-processing (4.3+) |
|
||||
| GodotPhysics3D for new projects | Jolt Physics 3D | Default since 4.6; better stability |
|
||||
76
docs/engine-reference/godot/modules/animation.md
Normal file
76
docs/engine-reference/godot/modules/animation.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Godot Animation — Quick Reference
|
||||
|
||||
Last verified: 2026-02-12 | Engine: Godot 4.6
|
||||
|
||||
## What Changed Since ~4.3 (LLM Cutoff)
|
||||
|
||||
### 4.6 Changes
|
||||
- **IK system fully restored**: Complete inverse kinematics for 3D skeletons
|
||||
- CCDIK, FABRIK, Jacobian IK, Spline IK, TwoBoneIK
|
||||
- Applied via `SkeletonModifier3D` nodes (not the old IK approach)
|
||||
- **Animation editor QoL**: Solo/hide/lock/delete for Bezier node groups; draggable timeline
|
||||
|
||||
### 4.5 Changes
|
||||
- **BoneConstraint3D**: Bind bones to other bones with modifiers
|
||||
- `AimModifier3D`, `CopyTransformModifier3D`, `ConvertTransformModifier3D`
|
||||
|
||||
### 4.3 Changes (in training data)
|
||||
- **AnimationMixer**: Base class for both AnimationPlayer and AnimationTree
|
||||
- `method_call_mode` → `callback_mode_method`
|
||||
- `playback_active` → `active`
|
||||
- `bone_pose_updated` signal → `skeleton_updated`
|
||||
- **`Skeleton3D.add_bone()`**: Now returns `int32` (was `void`)
|
||||
|
||||
## Current API Patterns
|
||||
|
||||
### AnimationPlayer (unchanged API, new base class)
|
||||
```gdscript
|
||||
@onready var anim_player: AnimationPlayer = %AnimationPlayer
|
||||
|
||||
func play_attack() -> void:
|
||||
anim_player.play(&"attack")
|
||||
await anim_player.animation_finished
|
||||
```
|
||||
|
||||
### IK Setup (4.6 — NEW)
|
||||
```gdscript
|
||||
# Add SkeletonModifier3D-based IK nodes as children of Skeleton3D
|
||||
# Available types:
|
||||
# - SkeletonModifier3D (base)
|
||||
# - TwoBoneIK (arms, legs)
|
||||
# - FABRIK (chains, tentacles)
|
||||
# - CCDIK (tails, spines)
|
||||
# - Jacobian IK (complex multi-joint)
|
||||
# - Spline IK (along curves)
|
||||
|
||||
# Configure in editor or code:
|
||||
# 1. Add IK modifier node as child of Skeleton3D
|
||||
# 2. Set target bone and tip bone
|
||||
# 3. Add a Marker3D as the IK target
|
||||
# 4. IK solver runs automatically each frame
|
||||
```
|
||||
|
||||
### BoneConstraint3D (4.5 — NEW)
|
||||
```gdscript
|
||||
# Add as child of Skeleton3D
|
||||
# Types:
|
||||
# - AimModifier3D: Point bone at target
|
||||
# - CopyTransformModifier3D: Mirror another bone's transform
|
||||
# - ConvertTransformModifier3D: Remap transform values
|
||||
```
|
||||
|
||||
### AnimationTree (base class changed in 4.3)
|
||||
```gdscript
|
||||
# AnimationTree now extends AnimationMixer (not Node directly)
|
||||
# Use AnimationMixer properties:
|
||||
@onready var anim_tree: AnimationTree = %AnimationTree
|
||||
|
||||
func _ready() -> void:
|
||||
anim_tree.active = true # NOT playback_active (deprecated 4.3)
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
- Using `playback_active` instead of `active` (deprecated since 4.3)
|
||||
- Using `bone_pose_updated` signal instead of `skeleton_updated` (renamed in 4.3)
|
||||
- Using old IK approach instead of SkeletonModifier3D system (restored in 4.6)
|
||||
- Not checking `is AnimationMixer` when type-checking animation nodes
|
||||
79
docs/engine-reference/godot/modules/audio.md
Normal file
79
docs/engine-reference/godot/modules/audio.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Godot Audio — Quick Reference
|
||||
|
||||
Last verified: 2026-02-12 | Engine: Godot 4.6
|
||||
|
||||
## What Changed Since ~4.3 (LLM Cutoff)
|
||||
|
||||
No major breaking changes to the audio API in 4.4–4.6. The core audio system
|
||||
remains stable. Key updates are workflow improvements:
|
||||
|
||||
### 4.6 Changes
|
||||
- **No audio-specific breaking changes** in this release
|
||||
|
||||
### 4.5 Changes
|
||||
- **No audio-specific breaking changes** in this release
|
||||
|
||||
## Current API Patterns
|
||||
|
||||
### Playing Audio
|
||||
```gdscript
|
||||
@onready var sfx_player: AudioStreamPlayer = %SFXPlayer
|
||||
@onready var music_player: AudioStreamPlayer = %MusicPlayer
|
||||
|
||||
func play_sfx(stream: AudioStream) -> void:
|
||||
sfx_player.stream = stream
|
||||
sfx_player.play()
|
||||
|
||||
func play_music(stream: AudioStream, fade_time: float = 1.0) -> void:
|
||||
var tween: Tween = create_tween()
|
||||
tween.tween_property(music_player, "volume_db", -80.0, fade_time)
|
||||
await tween.finished
|
||||
music_player.stream = stream
|
||||
music_player.volume_db = 0.0
|
||||
music_player.play()
|
||||
```
|
||||
|
||||
### 3D Spatial Audio
|
||||
```gdscript
|
||||
@onready var audio_3d: AudioStreamPlayer3D = %AudioPlayer3D
|
||||
|
||||
func _ready() -> void:
|
||||
audio_3d.max_distance = 50.0
|
||||
audio_3d.attenuation_model = AudioStreamPlayer3D.ATTENUATION_INVERSE_DISTANCE
|
||||
audio_3d.unit_size = 10.0
|
||||
```
|
||||
|
||||
### Audio Buses
|
||||
```gdscript
|
||||
# Set bus volumes
|
||||
AudioServer.set_bus_volume_db(AudioServer.get_bus_index(&"Music"), volume_db)
|
||||
AudioServer.set_bus_volume_db(AudioServer.get_bus_index(&"SFX"), volume_db)
|
||||
|
||||
# Mute a bus
|
||||
AudioServer.set_bus_mute(AudioServer.get_bus_index(&"Music"), true)
|
||||
```
|
||||
|
||||
### Object Pooling for SFX
|
||||
```gdscript
|
||||
# Pre-create multiple AudioStreamPlayer nodes for concurrent sounds
|
||||
var _sfx_pool: Array[AudioStreamPlayer] = []
|
||||
|
||||
func _ready() -> void:
|
||||
for i in range(8):
|
||||
var player := AudioStreamPlayer.new()
|
||||
player.bus = &"SFX"
|
||||
add_child(player)
|
||||
_sfx_pool.append(player)
|
||||
|
||||
func play_pooled(stream: AudioStream) -> void:
|
||||
for player in _sfx_pool:
|
||||
if not player.playing:
|
||||
player.stream = stream
|
||||
player.play()
|
||||
return
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
- Creating new AudioStreamPlayer nodes at runtime instead of pooling
|
||||
- Not using audio buses for volume categories (Music, SFX, UI, Voice)
|
||||
- Using `_process()` for audio timing instead of signals (`finished`)
|
||||
72
docs/engine-reference/godot/modules/input.md
Normal file
72
docs/engine-reference/godot/modules/input.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Godot Input — Quick Reference
|
||||
|
||||
Last verified: 2026-02-12 | Engine: Godot 4.6
|
||||
|
||||
## What Changed Since ~4.3 (LLM Cutoff)
|
||||
|
||||
### 4.6 Changes
|
||||
- **Dual-focus system**: Mouse/touch focus is now separate from keyboard/gamepad focus
|
||||
- Visual feedback differs by input method
|
||||
- Custom focus implementations may need updating
|
||||
- **Select Mode keybind changed**: "Select Mode" is now `v` key; old mode renamed "Transform Mode" (`q` key)
|
||||
|
||||
### 4.5 Changes
|
||||
- **SDL3 gamepad driver**: Gamepad handling delegated to SDL library for better cross-platform support
|
||||
- **Recursive Control disable**: Single property disables mouse/focus for entire node hierarchies
|
||||
|
||||
### 4.3 Changes (in training data)
|
||||
- **InputEventShortcut**: Dedicated event type for menu shortcuts (optional)
|
||||
|
||||
## Current API Patterns
|
||||
|
||||
### Input Actions (unchanged)
|
||||
```gdscript
|
||||
func _physics_process(delta: float) -> void:
|
||||
var input_dir: Vector2 = Input.get_vector(
|
||||
&"move_left", &"move_right", &"move_forward", &"move_back"
|
||||
)
|
||||
if Input.is_action_just_pressed(&"jump"):
|
||||
jump()
|
||||
```
|
||||
|
||||
### Input Events (unchanged)
|
||||
```gdscript
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
|
||||
handle_click(event.position)
|
||||
elif event is InputEventKey:
|
||||
if event.keycode == KEY_ESCAPE and event.pressed:
|
||||
toggle_pause()
|
||||
```
|
||||
|
||||
### Focus Management (4.6 — CHANGED)
|
||||
```gdscript
|
||||
# Mouse/touch and keyboard/gamepad focus are now SEPARATE
|
||||
# Visual styles may differ depending on which input method is active
|
||||
# If you have custom focus drawing, test with both input methods
|
||||
|
||||
# Standard approach still works:
|
||||
func _ready() -> void:
|
||||
%StartButton.grab_focus() # Keyboard/gamepad focus
|
||||
|
||||
# But be aware: mouse hover focus != keyboard focus in 4.6
|
||||
```
|
||||
|
||||
### Gamepad (4.5+ — SDL3 backend)
|
||||
```gdscript
|
||||
# API unchanged, but SDL3 provides:
|
||||
# - Better device detection across platforms
|
||||
# - Improved rumble support
|
||||
# - More consistent button mapping
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event is InputEventJoypadButton:
|
||||
if event.button_index == JOY_BUTTON_A and event.pressed:
|
||||
confirm_selection()
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
- Not testing both mouse and keyboard focus paths (dual-focus in 4.6)
|
||||
- Assuming `grab_focus()` affects mouse focus (it only affects keyboard/gamepad in 4.6)
|
||||
- Using string literals instead of `StringName` (`&"action"`) for action names in hot paths
|
||||
101
docs/engine-reference/godot/modules/navigation.md
Normal file
101
docs/engine-reference/godot/modules/navigation.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Godot Navigation — Quick Reference
|
||||
|
||||
Last verified: 2026-02-12 | Engine: Godot 4.6
|
||||
|
||||
## What Changed Since ~4.3 (LLM Cutoff)
|
||||
|
||||
### 4.5 Changes
|
||||
- **Dedicated 2D navigation server**: No longer a proxy to 3D NavigationServer
|
||||
- Reduces export binary size for 2D-only games
|
||||
- API remains the same for both 2D and 3D
|
||||
|
||||
### 4.3 Changes (in training data)
|
||||
- **`NavigationRegion2D`**: Removed `avoidance_layers` and `constrain_avoidance` properties
|
||||
|
||||
## Current API Patterns
|
||||
|
||||
### NavigationAgent3D (Preferred for Most Cases)
|
||||
```gdscript
|
||||
@onready var nav_agent: NavigationAgent3D = %NavigationAgent3D
|
||||
|
||||
func _ready() -> void:
|
||||
nav_agent.path_desired_distance = 0.5
|
||||
nav_agent.target_desired_distance = 1.0
|
||||
nav_agent.velocity_computed.connect(_on_velocity_computed)
|
||||
|
||||
func navigate_to(target: Vector3) -> void:
|
||||
nav_agent.target_position = target
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if nav_agent.is_navigation_finished():
|
||||
return
|
||||
var next_pos: Vector3 = nav_agent.get_next_path_position()
|
||||
var direction: Vector3 = global_position.direction_to(next_pos)
|
||||
nav_agent.velocity = direction * move_speed
|
||||
|
||||
func _on_velocity_computed(safe_velocity: Vector3) -> void:
|
||||
velocity = safe_velocity
|
||||
move_and_slide()
|
||||
```
|
||||
|
||||
### NavigationAgent2D
|
||||
```gdscript
|
||||
@onready var nav_agent: NavigationAgent2D = %NavigationAgent2D
|
||||
|
||||
func navigate_to(target: Vector2) -> void:
|
||||
nav_agent.target_position = target
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if nav_agent.is_navigation_finished():
|
||||
return
|
||||
var next_pos: Vector2 = nav_agent.get_next_path_position()
|
||||
var direction: Vector2 = global_position.direction_to(next_pos)
|
||||
velocity = direction * move_speed
|
||||
move_and_slide()
|
||||
```
|
||||
|
||||
### Low-Level Path Query (3D)
|
||||
```gdscript
|
||||
# Direct server query for custom pathfinding logic
|
||||
var query := NavigationPathQueryParameters3D.new()
|
||||
query.map = get_world_3d().navigation_map
|
||||
query.start_position = global_position
|
||||
query.target_position = target_pos
|
||||
query.navigation_layers = navigation_layers
|
||||
|
||||
var result := NavigationPathQueryResult3D.new()
|
||||
NavigationServer3D.query_path(query, result)
|
||||
var path: PackedVector3Array = result.path
|
||||
```
|
||||
|
||||
### Avoidance
|
||||
```gdscript
|
||||
# Enable RVO2-based local avoidance
|
||||
nav_agent.avoidance_enabled = true
|
||||
nav_agent.radius = 0.5
|
||||
nav_agent.max_speed = move_speed
|
||||
nav_agent.neighbor_distance = 10.0
|
||||
|
||||
# Use velocity_computed signal for avoidance-safe movement
|
||||
nav_agent.velocity_computed.connect(_on_velocity_computed)
|
||||
|
||||
# Set velocity each frame (avoidance needs this)
|
||||
nav_agent.velocity = desired_velocity
|
||||
```
|
||||
|
||||
### Navigation Layers
|
||||
```gdscript
|
||||
# Use layers to separate walkable areas by agent type
|
||||
# Layer 1: Ground units
|
||||
# Layer 2: Flying units
|
||||
# Layer 3: Swimming units
|
||||
nav_agent.navigation_layers = 1 # Ground only
|
||||
nav_agent.navigation_layers = 1 | 2 # Ground + Flying
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
- Calling `get_next_path_position()` without checking `is_navigation_finished()`
|
||||
- Not setting `velocity` on the agent when avoidance is enabled (required for RVO2)
|
||||
- Using `NavigationRegion2D.avoidance_layers` (removed in 4.3)
|
||||
- Forgetting to bake navigation mesh after modifying geometry
|
||||
- Not setting `navigation_layers` (defaults to all layers)
|
||||
76
docs/engine-reference/godot/modules/networking.md
Normal file
76
docs/engine-reference/godot/modules/networking.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Godot Networking — Quick Reference
|
||||
|
||||
Last verified: 2026-02-12 | Engine: Godot 4.6
|
||||
|
||||
## What Changed Since ~4.3 (LLM Cutoff)
|
||||
|
||||
### 4.6 Changes
|
||||
- **Networking section in breaking changes**: See the official migration guide for
|
||||
specifics at the 4.5→4.6 level
|
||||
|
||||
### 4.5 Changes
|
||||
- **No major networking API breaks** — core multiplayer API remains stable
|
||||
|
||||
## Current API Patterns
|
||||
|
||||
### High-Level Multiplayer
|
||||
```gdscript
|
||||
# Server
|
||||
func host_game(port: int = 9999) -> void:
|
||||
var peer := ENetMultiplayerPeer.new()
|
||||
peer.create_server(port)
|
||||
multiplayer.multiplayer_peer = peer
|
||||
multiplayer.peer_connected.connect(_on_peer_connected)
|
||||
multiplayer.peer_disconnected.connect(_on_peer_disconnected)
|
||||
|
||||
# Client
|
||||
func join_game(address: String, port: int = 9999) -> void:
|
||||
var peer := ENetMultiplayerPeer.new()
|
||||
peer.create_client(address, port)
|
||||
multiplayer.multiplayer_peer = peer
|
||||
```
|
||||
|
||||
### RPCs
|
||||
```gdscript
|
||||
# Server-authoritative pattern
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func request_action(action_data: Dictionary) -> void:
|
||||
if not multiplayer.is_server():
|
||||
return
|
||||
# Validate on server, then broadcast
|
||||
_execute_action.rpc(action_data)
|
||||
|
||||
@rpc("authority", "call_local", "reliable")
|
||||
func _execute_action(action_data: Dictionary) -> void:
|
||||
# All peers execute the validated action
|
||||
pass
|
||||
```
|
||||
|
||||
### MultiplayerSpawner and MultiplayerSynchronizer
|
||||
```gdscript
|
||||
# Use MultiplayerSpawner for automatic node replication
|
||||
# Use MultiplayerSynchronizer for property synchronization
|
||||
|
||||
# MultiplayerSynchronizer setup:
|
||||
# 1. Add as child of the node to sync
|
||||
# 2. Configure replication properties in editor
|
||||
# 3. Set visibility filters for relevancy
|
||||
```
|
||||
|
||||
### SceneMultiplayer Configuration
|
||||
```gdscript
|
||||
func _ready() -> void:
|
||||
var scene_mp := multiplayer as SceneMultiplayer
|
||||
scene_mp.auth_callback = _authenticate_peer
|
||||
scene_mp.server_relay = false # Direct peer connections
|
||||
|
||||
func _authenticate_peer(id: int, data: PackedByteArray) -> void:
|
||||
# Custom authentication logic
|
||||
pass
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
- Not using `"any_peer"` for client-to-server RPCs (defaults to authority only)
|
||||
- Trusting client data without server-side validation
|
||||
- Using `"unreliable"` for game state changes (use for position updates only)
|
||||
- Not setting multiplayer authority (`set_multiplayer_authority()`) on spawned nodes
|
||||
76
docs/engine-reference/godot/modules/physics.md
Normal file
76
docs/engine-reference/godot/modules/physics.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Godot Physics — Quick Reference
|
||||
|
||||
Last verified: 2026-02-12 | Engine: Godot 4.6
|
||||
|
||||
## What Changed Since ~4.3 (LLM Cutoff)
|
||||
|
||||
### 4.6 Changes
|
||||
- **Jolt Physics is the DEFAULT 3D engine** for new projects
|
||||
- Existing projects keep their current physics engine setting
|
||||
- Better determinism, stability, and performance than GodotPhysics3D
|
||||
- Some HingeJoint3D properties (`damp`) only work with GodotPhysics3D
|
||||
- 2D physics UNCHANGED (still Godot Physics 2D)
|
||||
|
||||
### 4.5 Changes
|
||||
- **3D physics interpolation rearchitected**: Moved from RenderingServer to SceneTree
|
||||
- User-facing API unchanged, but internal behavior may differ in edge cases
|
||||
|
||||
## Physics Engine Selection (4.6)
|
||||
|
||||
```
|
||||
Project Settings → Physics → 3D → Physics Engine:
|
||||
- Jolt Physics (DEFAULT for new projects)
|
||||
- GodotPhysics3D (legacy, still available)
|
||||
```
|
||||
|
||||
### Jolt vs GodotPhysics3D
|
||||
|
||||
| Feature | Jolt (default) | GodotPhysics3D |
|
||||
|---------|---------------|----------------|
|
||||
| Determinism | Better | Inconsistent |
|
||||
| Stability | Better | Adequate |
|
||||
| Performance | Better for complex scenes | Adequate |
|
||||
| HingeJoint3D `damp` | NOT supported | Supported |
|
||||
| Runtime warnings | Yes, for unsupported properties | No |
|
||||
| Collision margins | May behave differently | Original behavior |
|
||||
|
||||
## Current API Patterns
|
||||
|
||||
### Basic Physics Setup (unchanged)
|
||||
```gdscript
|
||||
# CharacterBody3D movement — API unchanged across engines
|
||||
extends CharacterBody3D
|
||||
|
||||
@export var speed: float = 5.0
|
||||
@export var jump_velocity: float = 4.5
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if not is_on_floor():
|
||||
velocity += get_gravity() * delta
|
||||
|
||||
if Input.is_action_just_pressed("jump") and is_on_floor():
|
||||
velocity.y = jump_velocity
|
||||
|
||||
var input_dir: Vector2 = Input.get_vector("left", "right", "forward", "back")
|
||||
var direction: Vector3 = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
|
||||
velocity.x = direction.x * speed
|
||||
velocity.z = direction.z * speed
|
||||
|
||||
move_and_slide()
|
||||
```
|
||||
|
||||
### Raycasting (unchanged)
|
||||
```gdscript
|
||||
var space_state: PhysicsDirectSpaceState3D = get_world_3d().direct_space_state
|
||||
var query := PhysicsRayQueryParameters3D.create(from, to)
|
||||
query.collision_mask = collision_mask
|
||||
var result: Dictionary = space_state.intersect_ray(query)
|
||||
if result:
|
||||
var hit_point: Vector3 = result.position
|
||||
var hit_normal: Vector3 = result.normal
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
- Assuming GodotPhysics3D is the default (Jolt since 4.6)
|
||||
- Using HingeJoint3D `damp` property without checking physics engine (Jolt ignores it)
|
||||
- Not testing collision edge cases when switching between physics engines
|
||||
59
docs/engine-reference/godot/modules/rendering.md
Normal file
59
docs/engine-reference/godot/modules/rendering.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Godot Rendering — Quick Reference
|
||||
|
||||
Last verified: 2026-02-12 | Engine: Godot 4.6
|
||||
|
||||
## What Changed Since ~4.3 (LLM Cutoff)
|
||||
|
||||
### 4.6 Changes
|
||||
- **D3D12 is the default rendering backend on Windows** (was Vulkan)
|
||||
- **Glow processes before tonemapping** (was after) — uses screen blending mode
|
||||
- **AgX tonemapper**: new white point and contrast controls
|
||||
- **SSR overhauled**: better realism, visual stability, and performance
|
||||
|
||||
### 4.5 Changes
|
||||
- **Shader Baker**: Pre-compiles shaders to reduce startup time
|
||||
- **SMAA 1x**: New anti-aliasing option (sharper than FXAA, cheaper than TAA)
|
||||
- **Stencil buffer support**: Enables selective geometry masking/portal effects
|
||||
- **Bent normal maps**: Directional occlusion encoded in normal map textures
|
||||
- **Specular occlusion**: Ambient occlusion now correctly affects reflections
|
||||
|
||||
### 4.4 Changes
|
||||
- **`RenderingDevice.draw_list_begin`**: Many parameters removed; optional `breadcrumb` added
|
||||
- **Shader texture types**: Changed from `Texture2D` to `Texture` base type
|
||||
- **Particles `.restart()`**: Added optional `keep_seed` parameter
|
||||
|
||||
### 4.3 Changes (in training data)
|
||||
- **Compositor node**: `Compositor` + `CompositorEffect` for post-processing chains
|
||||
|
||||
## Current API Patterns
|
||||
|
||||
### Post-Processing (4.3+)
|
||||
```gdscript
|
||||
# Use Compositor node — NOT manual viewport shader chains
|
||||
# Add Compositor as child of WorldEnvironment or Camera3D
|
||||
# Create CompositorEffect resources for each post-process step
|
||||
```
|
||||
|
||||
### Anti-Aliasing Options (4.6)
|
||||
```
|
||||
Project Settings → Rendering → Anti Aliasing:
|
||||
- MSAA 2D/3D: Hardware MSAA (quality but expensive)
|
||||
- Screen Space AA: FXAA (fast, blurry) or SMAA (sharp, moderate cost) # SMAA new in 4.5
|
||||
- TAA: Temporal (best quality, ghosting on fast motion)
|
||||
```
|
||||
|
||||
### Rendering Backend Selection (4.6)
|
||||
```
|
||||
Project Settings → Rendering → Renderer:
|
||||
- Forward+ (default): Full featured, desktop-focused
|
||||
- Mobile: Optimized for mobile/low-end, limited features
|
||||
- Compatibility: OpenGL 3.3 / WebGL 2, broadest hardware support
|
||||
|
||||
Windows default backend: D3D12 (was Vulkan pre-4.6)
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
- Assuming Vulkan is the default backend on Windows (D3D12 since 4.6)
|
||||
- Using manual viewport chains instead of Compositor for post-processing
|
||||
- Using `Texture2D` in shader uniform types (use `Texture` since 4.4)
|
||||
- Not using Shader Baker for projects with many shader variants
|
||||
82
docs/engine-reference/godot/modules/ui.md
Normal file
82
docs/engine-reference/godot/modules/ui.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Godot UI — Quick Reference
|
||||
|
||||
Last verified: 2026-02-12 | Engine: Godot 4.6
|
||||
|
||||
## What Changed Since ~4.3 (LLM Cutoff)
|
||||
|
||||
### 4.6 Changes
|
||||
- **Dual-focus system**: Mouse/touch focus is now SEPARATE from keyboard/gamepad focus
|
||||
- Visual feedback differs by input method
|
||||
- Custom focus implementations may need updating
|
||||
- **TabContainer**: Tab properties editable directly in Inspector
|
||||
- **TileMapLayer scene tile rotation**: Scene tiles can be rotated like atlas tiles
|
||||
|
||||
### 4.5 Changes
|
||||
- **FoldableContainer**: New accordion-style UI node for collapsible sections
|
||||
- **Recursive Control behavior**: Disable mouse/focus for entire node hierarchies
|
||||
with a single property
|
||||
- **Screen reader support**: Control nodes work with AccessKit
|
||||
- **Live translation preview**: Test different locales in-editor
|
||||
- **`RichTextLabel.push_meta`**: Added optional `tooltip` parameter (from 4.4)
|
||||
|
||||
### 4.4 Changes
|
||||
- **`GraphEdit.connect_node`**: Added optional `keep_alive` parameter
|
||||
|
||||
## Current API Patterns
|
||||
|
||||
### Theme and Style (4.6)
|
||||
```gdscript
|
||||
# Editor uses new "Modern" theme by default
|
||||
# For game UI, use custom themes as before:
|
||||
var theme := Theme.new()
|
||||
theme.set_color(&"font_color", &"Label", Color.WHITE)
|
||||
theme.set_font_size(&"font_size", &"Label", 24)
|
||||
```
|
||||
|
||||
### Focus Management (4.6 — CHANGED)
|
||||
```gdscript
|
||||
# Keyboard/gamepad focus (grab_focus still works)
|
||||
func _ready() -> void:
|
||||
%StartButton.grab_focus()
|
||||
|
||||
# IMPORTANT: In 4.6, mouse hover is separate from keyboard focus
|
||||
# Both can be active simultaneously on different controls
|
||||
# Test your UI with BOTH mouse and keyboard/gamepad
|
||||
|
||||
# Focus neighbors (unchanged)
|
||||
%Button1.focus_neighbor_bottom = %Button2.get_path()
|
||||
%Button1.focus_neighbor_right = %Button3.get_path()
|
||||
```
|
||||
|
||||
### FoldableContainer (4.5 — NEW)
|
||||
```gdscript
|
||||
# Accordion-style collapsible container
|
||||
# Add as parent of content you want to make collapsible
|
||||
# Children show/hide when header is clicked
|
||||
# Configure via editor properties or code
|
||||
```
|
||||
|
||||
### Recursive Disable (4.5 — NEW)
|
||||
```gdscript
|
||||
# Disable all mouse/focus interactions for a hierarchy
|
||||
# Useful for disabling entire menu sections
|
||||
%SettingsPanel.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
# In 4.5+, this can propagate recursively to children
|
||||
```
|
||||
|
||||
### Localization-Ready UI (best practice)
|
||||
```gdscript
|
||||
# Use tr() for all visible strings
|
||||
label.text = tr("MENU_START_GAME")
|
||||
|
||||
# Use auto-wrap for labels (text length varies by language)
|
||||
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
|
||||
# Test with live translation preview in editor (4.5+)
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
- Assuming `grab_focus()` affects mouse focus (keyboard/gamepad only in 4.6)
|
||||
- Not testing UI with both mouse and gamepad after upgrading to 4.6
|
||||
- Hardcoding strings instead of using `tr()` for localization
|
||||
- Not using `FoldableContainer` for collapsible UI (new in 4.5, cleaner than custom)
|
||||
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
|
||||
210
docs/engine-reference/unreal/PLUGINS.md
Normal file
210
docs/engine-reference/unreal/PLUGINS.md
Normal file
@@ -0,0 +1,210 @@
|
||||
# Unreal Engine 5.7 — Optional Plugins & Systems
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
|
||||
This document indexes **optional plugins and systems** available in Unreal Engine 5.7.
|
||||
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
|
||||
**⚠️ Experimental** - May have breaking changes in future versions
|
||||
**📦 Plugin Required** - Must be enabled in `Edit > Plugins`
|
||||
|
||||
---
|
||||
|
||||
## Production-Ready Systems (Detailed Docs Available)
|
||||
|
||||
### ✅ Gameplay Ability System (GAS)
|
||||
- **Purpose:** Modular ability system (abilities, attributes, effects, cooldowns, costs)
|
||||
- **When to use:** RPGs, MOBAs, shooters with abilities, any ability-based gameplay
|
||||
- **Knowledge Gap:** GAS stable since UE4, UE5 improvements post-cutoff
|
||||
- **Status:** Production-Ready
|
||||
- **Plugin:** `GameplayAbilities` (built-in, enable in Plugins)
|
||||
- **Detailed Docs:** [plugins/gameplay-ability-system.md](plugins/gameplay-ability-system.md)
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/gameplay-ability-system-for-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
### ✅ CommonUI
|
||||
- **Purpose:** Cross-platform UI framework (automatic gamepad/mouse/touch input routing)
|
||||
- **When to use:** Multi-platform games (console + PC), input-agnostic UI
|
||||
- **Knowledge Gap:** Production-ready in UE5+, major improvements post-cutoff
|
||||
- **Status:** Production-Ready
|
||||
- **Plugin:** `CommonUI` (built-in, enable in Plugins)
|
||||
- **Detailed Docs:** [plugins/common-ui.md](plugins/common-ui.md)
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/commonui-plugin-for-advanced-user-interfaces-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
### ✅ Gameplay Camera System
|
||||
- **Purpose:** Modular camera management (camera modes, blending, context-aware cameras)
|
||||
- **When to use:** Games needing dynamic camera behavior (3rd person, aiming, vehicles)
|
||||
- **Knowledge Gap:** NEW in UE 5.5, completely post-cutoff
|
||||
- **Status:** ⚠️ Experimental (UE 5.5-5.7)
|
||||
- **Plugin:** `GameplayCameras` (built-in, enable in Plugins)
|
||||
- **Detailed Docs:** [plugins/gameplay-camera-system.md](plugins/gameplay-camera-system.md)
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/gameplay-cameras-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
### ✅ PCG (Procedural Content Generation)
|
||||
- **Purpose:** Node-based procedural world generation (foliage, props, terrain details)
|
||||
- **When to use:** Open worlds, procedural levels, large-scale environment population
|
||||
- **Knowledge Gap:** Experimental in UE 5.0-5.6, production-ready in 5.7
|
||||
- **Status:** Production-Ready (as of UE 5.7)
|
||||
- **Plugin:** `PCG` (built-in, enable in Plugins)
|
||||
- **Detailed Docs:** [plugins/pcg.md](plugins/pcg.md)
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/procedural-content-generation-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
## Other Production-Ready Plugins (Brief Overview)
|
||||
|
||||
### 🟡 Mass Entity
|
||||
- **Purpose:** High-performance ECS for large-scale AI/crowds (10,000+ entities)
|
||||
- **When to use:** RTS, city simulators, massive crowds, large-scale AI
|
||||
- **Status:** Production-Ready (UE 5.1+)
|
||||
- **Plugin:** `MassEntity`, `MassGameplay`, `MassCrowd`
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/mass-entity-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Niagara Fluids
|
||||
- **Purpose:** GPU fluid simulation (smoke, fire, liquids)
|
||||
- **When to use:** Realistic fire/smoke effects, water simulation
|
||||
- **Status:** Experimental → Production-Ready (UE 5.4+)
|
||||
- **Plugin:** `NiagaraFluids` (built-in)
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/niagara-fluids-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Water Plugin
|
||||
- **Purpose:** Ocean, river, lake rendering with buoyancy
|
||||
- **When to use:** Games with water bodies, boats, swimming
|
||||
- **Status:** Production-Ready (UE 5.0+)
|
||||
- **Plugin:** `Water` (built-in)
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/water-system-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Landmass Plugin
|
||||
- **Purpose:** Terrain sculpting and landscape editing
|
||||
- **When to use:** Large-scale terrain modification, procedural landscapes
|
||||
- **Status:** Production-Ready
|
||||
- **Plugin:** `Landmass` (built-in)
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/landmass-plugin-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Chaos Destruction
|
||||
- **Purpose:** Real-time fracture and destruction
|
||||
- **When to use:** Destructible environments (walls, buildings, objects)
|
||||
- **Status:** Production-Ready (UE 5.0+)
|
||||
- **Plugin:** `ChaosDestruction` (built-in)
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/destruction-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Chaos Vehicle
|
||||
- **Purpose:** Advanced vehicle physics (wheeled vehicles, suspension)
|
||||
- **When to use:** Racing games, vehicle-heavy gameplay
|
||||
- **Status:** Production-Ready (replaces PhysX Vehicles)
|
||||
- **Plugin:** `ChaosVehicles` (built-in)
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/chaos-vehicles-overview-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Geometry Scripting
|
||||
- **Purpose:** Runtime procedural mesh generation and editing
|
||||
- **When to use:** Dynamic mesh creation, procedural modeling
|
||||
- **Status:** Production-Ready (UE 5.1+)
|
||||
- **Plugin:** `GeometryScripting` (built-in)
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/geometry-scripting-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Motion Design Tools
|
||||
- **Purpose:** Motion graphics, procedural animation, keyframe animation
|
||||
- **When to use:** UI animations, procedural motion, keyframed sequences
|
||||
- **Status:** Experimental → Production-Ready (UE 5.4+)
|
||||
- **Plugin:** `MotionDesign` (built-in)
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/motion-design-mode-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
## Experimental Plugins (Use with Caution)
|
||||
|
||||
### ⚠️ AI Assistant (UE 5.7+)
|
||||
- **Purpose:** In-editor AI guidance and help
|
||||
- **Status:** Experimental
|
||||
- **Plugin:** Enable in UE 5.7 settings
|
||||
- **Official:** Announced in UE 5.7 release
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ OpenXR (VR/AR)
|
||||
- **Purpose:** Cross-platform VR/AR support
|
||||
- **When to use:** VR/AR games
|
||||
- **Status:** Production-Ready for VR, Experimental for AR
|
||||
- **Plugin:** `OpenXR` (built-in)
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/openxr-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ Online Subsystem (EOS, Steam, etc.)
|
||||
- **Purpose:** Platform-agnostic online services (matchmaking, friends, achievements)
|
||||
- **When to use:** Multiplayer games with online features
|
||||
- **Status:** Production-Ready
|
||||
- **Plugin:** `OnlineSubsystem`, `OnlineSubsystemEOS`, `OnlineSubsystemSteam`
|
||||
- **Official:** https://docs.unrealengine.com/5.7/en-US/online-subsystem-in-unreal-engine/
|
||||
|
||||
---
|
||||
|
||||
## Deprecated Plugins (Avoid for New Projects)
|
||||
|
||||
### ❌ PhysX Vehicles
|
||||
- **Deprecated:** Use Chaos Vehicles instead
|
||||
- **Status:** Legacy, not recommended
|
||||
|
||||
---
|
||||
|
||||
### ❌ Old Replication Graph
|
||||
- **Deprecated:** Replaced by Iris (UE 5.1+)
|
||||
- **Status:** Use Iris for modern networking
|
||||
|
||||
---
|
||||
|
||||
## On-Demand WebSearch Strategy
|
||||
|
||||
For plugins NOT listed above, use the following approach when users ask:
|
||||
|
||||
1. **WebSearch** for latest documentation: `"Unreal Engine 5.7 [plugin name]"`
|
||||
2. Verify if plugin is:
|
||||
- Post-cutoff (beyond May 2025 training data)
|
||||
- Experimental vs Production-Ready
|
||||
- Still supported in UE 5.7
|
||||
3. Optionally cache findings in `plugins/[plugin-name].md` for future reference
|
||||
|
||||
---
|
||||
|
||||
## Quick Decision Guide
|
||||
|
||||
**I need abilities/skills/buffs** → **Gameplay Ability System (GAS)**
|
||||
**I need cross-platform UI (console + PC)** → **CommonUI**
|
||||
**I need dynamic cameras** → **Gameplay Camera System**
|
||||
**I need procedural worlds** → **PCG**
|
||||
**I need large crowds (1000s of AI)** → **Mass Entity**
|
||||
**I need destructible environments** → **Chaos Destruction**
|
||||
**I need vehicles** → **Chaos Vehicles**
|
||||
**I need water/oceans** → **Water Plugin**
|
||||
**I need VR/AR** → **OpenXR**
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-02-13
|
||||
**Engine Version:** Unreal Engine 5.7
|
||||
**LLM Knowledge Cutoff:** May 2025
|
||||
54
docs/engine-reference/unreal/VERSION.md
Normal file
54
docs/engine-reference/unreal/VERSION.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Unreal Engine — Version Reference
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Engine Version** | Unreal Engine 5.7 |
|
||||
| **Release Date** | November 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 Unreal Engine up to ~5.3. Versions 5.4, 5.5,
|
||||
5.6, and 5.7 introduced significant changes that the model does NOT know about.
|
||||
Always cross-reference this directory before suggesting Unreal API calls.
|
||||
|
||||
## Post-Cutoff Version Timeline
|
||||
|
||||
| Version | Release | Risk Level | Key Theme |
|
||||
|---------|---------|------------|-----------|
|
||||
| 5.4 | ~Mid 2025 | HIGH | Motion Design tools, animation improvements, PCG enhancements |
|
||||
| 5.5 | ~Sep 2025 | HIGH | Megalights (millions of lights), animation authoring, MegaCity demo |
|
||||
| 5.6 | ~Oct 2025 | MEDIUM | Performance optimizations, bug fixes |
|
||||
| 5.7 | Nov 2025 | HIGH | PCG production-ready, Substrate production-ready, AI assistant |
|
||||
|
||||
## Major Changes from UE 5.3 to UE 5.7
|
||||
|
||||
### Breaking Changes
|
||||
- **Substrate Material System**: New material framework (replaces legacy materials)
|
||||
- **PCG (Procedural Content Generation)**: Production-ready, major API changes
|
||||
- **Megalights**: New lighting system (millions of dynamic lights)
|
||||
- **Animation Authoring**: New rigging and animation tools
|
||||
- **AI Assistant**: In-editor AI guidance (experimental)
|
||||
|
||||
### New Features (Post-Cutoff)
|
||||
- **Megalights**: Dynamic lighting at massive scale (millions of lights)
|
||||
- **Substrate Materials**: Production-ready modular material system
|
||||
- **PCG Framework**: Procedural world generation (production-ready in 5.7)
|
||||
- **Enhanced Virtual Production**: MetaHuman integration, deeper VP workflows
|
||||
- **Animation Improvements**: Better rigging, blending, procedural animation
|
||||
- **AI Assistant**: In-editor AI help (experimental)
|
||||
|
||||
### Deprecated Systems
|
||||
- **Legacy Material System**: Migrate to Substrate for new projects
|
||||
- **Old PCG API**: Use new production-ready PCG API (5.7+)
|
||||
|
||||
## Verified Sources
|
||||
|
||||
- Official docs: https://docs.unrealengine.com/5.7/
|
||||
- UE 5.7 release notes: https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-5-7-release-notes
|
||||
- What's new in 5.7: https://dev.epicgames.com/documentation/en-us/unreal-engine/whats-new
|
||||
- UE 5.7 announcement: https://www.unrealengine.com/en-US/news/unreal-engine-5-7-is-now-available
|
||||
- UE 5.5 blog: https://www.unrealengine.com/en-US/blog/unreal-engine-5-5-is-now-available
|
||||
- Migration guides: https://docs.unrealengine.com/5.7/en-US/upgrading-projects/
|
||||
150
docs/engine-reference/unreal/breaking-changes.md
Normal file
150
docs/engine-reference/unreal/breaking-changes.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# Unreal Engine 5.7 — Breaking Changes
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
|
||||
This document tracks breaking API changes and behavioral differences between Unreal Engine 5.3
|
||||
(likely in model training) and Unreal Engine 5.7 (current version). Organized by risk level.
|
||||
|
||||
## HIGH RISK — Will Break Existing Code
|
||||
|
||||
### Substrate Material System (Production-Ready in 5.7)
|
||||
**Versions:** UE 5.5+ (experimental), 5.7 (production-ready)
|
||||
|
||||
Substrate replaces the legacy material system with a modular, physically accurate framework.
|
||||
|
||||
```cpp
|
||||
// ❌ OLD: Legacy material nodes (still work but deprecated)
|
||||
// Standard material graph with Base Color, Metallic, Roughness, etc.
|
||||
|
||||
// ✅ NEW: Substrate material layers
|
||||
// Use Substrate nodes: Substrate Slab, Substrate Blend, etc.
|
||||
// Modular material authoring with true physical accuracy
|
||||
```
|
||||
|
||||
**Migration:** Enable Substrate in `Project Settings > Engine > Substrate` and rebuild materials using Substrate nodes.
|
||||
|
||||
---
|
||||
|
||||
### PCG (Procedural Content Generation) API Overhaul
|
||||
**Versions:** UE 5.7 (production-ready)
|
||||
|
||||
PCG framework reached production-ready status with major API changes.
|
||||
|
||||
```cpp
|
||||
// ❌ OLD: Experimental PCG API (pre-5.7)
|
||||
// Old node types, unstable API
|
||||
|
||||
// ✅ NEW: Production PCG API (5.7+)
|
||||
// Use FPCGContext, IPCGElement, new node types
|
||||
// Stable API, production-ready workflow
|
||||
```
|
||||
|
||||
**Migration:** Follow PCG migration guide in 5.7 docs. Expect significant refactoring for experimental PCG code.
|
||||
|
||||
---
|
||||
|
||||
### Megalights Rendering System
|
||||
**Versions:** UE 5.5+
|
||||
|
||||
New lighting system supports millions of dynamic lights.
|
||||
|
||||
```cpp
|
||||
// ❌ OLD: Limited dynamic lights (clustered forward shading)
|
||||
// Max ~100-200 dynamic lights before performance degrades
|
||||
|
||||
// ✅ NEW: Megalights (5.5+)
|
||||
// Millions of dynamic lights with minimal performance cost
|
||||
// Enable: Project Settings > Engine > Rendering > Megalights
|
||||
```
|
||||
|
||||
**Migration:** No code changes needed, but lighting behavior may differ. Test scenes after enabling.
|
||||
|
||||
---
|
||||
|
||||
## MEDIUM RISK — Behavioral Changes
|
||||
|
||||
### Enhanced Input System (Now Default)
|
||||
**Versions:** UE 5.1+ (recommended), 5.7 (default)
|
||||
|
||||
Enhanced Input is now the default input system.
|
||||
|
||||
```cpp
|
||||
// ❌ OLD: Legacy input bindings (deprecated)
|
||||
InputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
|
||||
|
||||
// ✅ NEW: Enhanced Input
|
||||
SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) {
|
||||
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(PlayerInputComponent);
|
||||
EIC->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
|
||||
}
|
||||
```
|
||||
|
||||
**Migration:** Replace legacy input bindings with Enhanced Input actions.
|
||||
|
||||
---
|
||||
|
||||
### Nanite Default Enabled
|
||||
**Versions:** UE 5.0+ (optional), 5.7 (encouraged)
|
||||
|
||||
Nanite virtualized geometry is now the recommended workflow for static meshes.
|
||||
|
||||
```cpp
|
||||
// Enable Nanite on static mesh:
|
||||
// Static Mesh Editor > Details > Nanite Settings > Enable Nanite Support
|
||||
```
|
||||
|
||||
**Migration:** Convert high-poly meshes to Nanite. Test performance on target platforms.
|
||||
|
||||
---
|
||||
|
||||
## LOW RISK — Deprecations (Still Functional)
|
||||
|
||||
### Legacy Material System
|
||||
**Status:** Deprecated but supported
|
||||
**Replacement:** Substrate Material System
|
||||
|
||||
Legacy materials still work, but Substrate is recommended for new projects.
|
||||
|
||||
---
|
||||
|
||||
### Old World Partition (UE4 Style)
|
||||
**Status:** Deprecated
|
||||
**Replacement:** World Partition (UE5+)
|
||||
|
||||
Use UE5's World Partition system for large worlds.
|
||||
|
||||
---
|
||||
|
||||
## Platform-Specific Breaking Changes
|
||||
|
||||
### Windows
|
||||
- **UE 5.7**: DirectX 12 is now default (was DX11 in older versions)
|
||||
- Update shaders for DX12 compatibility
|
||||
|
||||
### macOS
|
||||
- **UE 5.5+**: Metal 3 required (minimum macOS 13)
|
||||
|
||||
### Mobile
|
||||
- **UE 5.7**: Minimum Android API level raised to 26 (Android 8.0)
|
||||
- Minimum iOS deployment target raised to iOS 14
|
||||
|
||||
---
|
||||
|
||||
## Migration Checklist
|
||||
|
||||
When upgrading from UE 5.3 to UE 5.7:
|
||||
|
||||
- [ ] Review Substrate materials (convert if ready for new system)
|
||||
- [ ] Audit PCG usage (update to production API if using experimental)
|
||||
- [ ] Test Megalights performance (enable and benchmark)
|
||||
- [ ] Migrate legacy input to Enhanced Input
|
||||
- [ ] Convert high-poly meshes to Nanite
|
||||
- [ ] Update shaders for DX12 (Windows) or Metal 3 (macOS)
|
||||
- [ ] Verify minimum platform versions (Android 8.0, iOS 14)
|
||||
- [ ] Test Lumen and Nanite performance on target hardware
|
||||
|
||||
---
|
||||
|
||||
**Sources:**
|
||||
- https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-5-7-release-notes
|
||||
- https://dev.epicgames.com/documentation/en-us/unreal-engine/upgrading-projects-to-newer-versions-of-unreal-engine
|
||||
340
docs/engine-reference/unreal/current-best-practices.md
Normal file
340
docs/engine-reference/unreal/current-best-practices.md
Normal file
@@ -0,0 +1,340 @@
|
||||
# Unreal Engine 5.7 — Current Best Practices
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
|
||||
Modern UE5 patterns that may not be in the LLM's training data.
|
||||
These are production-ready recommendations as of UE 5.7.
|
||||
|
||||
---
|
||||
|
||||
## Project Setup
|
||||
|
||||
### Use UE 5.7 for New Projects
|
||||
- Latest features: Megalights, production-ready Substrate and PCG
|
||||
- Better performance and stability
|
||||
|
||||
### Choose the Right Rendering Features
|
||||
- **Lumen**: Real-time global illumination (RECOMMENDED for most projects)
|
||||
- **Nanite**: Virtualized geometry for high-poly meshes (RECOMMENDED for detailed environments)
|
||||
- **Megalights**: Millions of dynamic lights (RECOMMENDED for complex lighting)
|
||||
- **Substrate**: Modular material system (RECOMMENDED for new projects)
|
||||
|
||||
---
|
||||
|
||||
## C++ Coding
|
||||
|
||||
### Use Modern C++ Features (C++20 in UE5.7)
|
||||
|
||||
```cpp
|
||||
// ✅ Use TObjectPtr<T> (UE5 type-safe pointers)
|
||||
UPROPERTY()
|
||||
TObjectPtr<UStaticMeshComponent> MeshComp;
|
||||
|
||||
// ✅ Structured bindings
|
||||
if (auto [bSuccess, Value] = TryGetValue(); bSuccess) {
|
||||
// Use Value
|
||||
}
|
||||
|
||||
// ✅ Concepts and constraints (C++20)
|
||||
template<typename T>
|
||||
concept Damageable = requires(T t, float damage) {
|
||||
{ t.TakeDamage(damage) } -> std::same_as<void>;
|
||||
};
|
||||
```
|
||||
|
||||
### Use UPROPERTY() for Garbage Collection
|
||||
|
||||
```cpp
|
||||
// ✅ UPROPERTY ensures GC doesn't delete this
|
||||
UPROPERTY()
|
||||
TObjectPtr<AActor> MyActor;
|
||||
|
||||
// ❌ Raw pointers can become dangling
|
||||
AActor* MyActor; // Dangerous! May be garbage collected
|
||||
```
|
||||
|
||||
### Use UFUNCTION() for Blueprint Exposure
|
||||
|
||||
```cpp
|
||||
// ✅ Callable from Blueprint
|
||||
UFUNCTION(BlueprintCallable, Category="Combat")
|
||||
void TakeDamage(float Damage);
|
||||
|
||||
// ✅ Implementable in Blueprint
|
||||
UFUNCTION(BlueprintImplementableEvent, Category="Combat")
|
||||
void OnDeath();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Blueprint Best Practices
|
||||
|
||||
### Use Blueprint vs C++
|
||||
|
||||
- **C++**: Core gameplay systems, performance-critical code, low-level engine interaction
|
||||
- **Blueprint**: Rapid prototyping, content creation, data-driven logic, designer workflows
|
||||
|
||||
### Blueprint Performance Tips
|
||||
|
||||
```cpp
|
||||
// ✅ Use Event Tick sparingly (expensive)
|
||||
// Prefer timers or events
|
||||
|
||||
// ✅ Use Blueprint Nativization (Blueprints → C++)
|
||||
// Project Settings > Packaging > Blueprint Nativization
|
||||
|
||||
// ✅ Cache frequently accessed components
|
||||
// Don't call GetComponent every tick
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rendering (UE 5.7)
|
||||
|
||||
### Use Lumen for Global Illumination
|
||||
|
||||
```cpp
|
||||
// Enable: Project Settings > Engine > Rendering > Dynamic Global Illumination Method = Lumen
|
||||
// Real-time GI, no lightmap baking needed (RECOMMENDED)
|
||||
```
|
||||
|
||||
### Use Nanite for High-Poly Meshes
|
||||
|
||||
```cpp
|
||||
// Enable on Static Mesh: Details > Nanite Settings > Enable Nanite Support
|
||||
// Automatically LODs millions of triangles (RECOMMENDED for detailed meshes)
|
||||
```
|
||||
|
||||
### Use Megalights for Complex Lighting (UE 5.5+)
|
||||
|
||||
```cpp
|
||||
// Enable: Project Settings > Engine > Rendering > Megalights = Enabled
|
||||
// Supports millions of dynamic lights with minimal cost
|
||||
```
|
||||
|
||||
### Use Substrate Materials (Production-Ready in 5.7)
|
||||
|
||||
```cpp
|
||||
// Enable: Project Settings > Engine > Substrate > Enable Substrate
|
||||
// Modular, physically accurate materials (RECOMMENDED for new projects)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Enhanced Input System
|
||||
|
||||
### Setup Enhanced Input
|
||||
|
||||
```cpp
|
||||
// 1. Create Input Action (IA_Jump)
|
||||
// 2. Create Input Mapping Context (IMC_Default)
|
||||
// 3. Add mapping: IA_Jump → Space Bar
|
||||
|
||||
// C++ Setup:
|
||||
#include "EnhancedInputComponent.h"
|
||||
#include "EnhancedInputSubsystems.h"
|
||||
|
||||
void AMyCharacter::BeginPlay() {
|
||||
Super::BeginPlay();
|
||||
|
||||
if (APlayerController* PC = Cast<APlayerController>(GetController())) {
|
||||
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
|
||||
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer())) {
|
||||
Subsystem->AddMappingContext(DefaultMappingContext, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) {
|
||||
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(PlayerInputComponent);
|
||||
EIC->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
|
||||
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::Move);
|
||||
}
|
||||
|
||||
void AMyCharacter::Move(const FInputActionValue& Value) {
|
||||
FVector2D MoveVector = Value.Get<FVector2D>();
|
||||
AddMovementInput(GetActorForwardVector(), MoveVector.Y);
|
||||
AddMovementInput(GetActorRightVector(), MoveVector.X);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Gameplay Ability System (GAS)
|
||||
|
||||
### Use GAS for Complex Gameplay
|
||||
|
||||
```cpp
|
||||
// ✅ Use GAS for: Abilities, buffs, damage calculation, cooldowns
|
||||
// Modular, scalable, multiplayer-ready
|
||||
|
||||
// Install: Enable "Gameplay Abilities" plugin
|
||||
|
||||
// Example Ability:
|
||||
UCLASS()
|
||||
class UGA_Fireball : public UGameplayAbility {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual void ActivateAbility(...) override {
|
||||
// Ability logic
|
||||
SpawnFireball();
|
||||
CommitAbility(); // Commit cost/cooldown
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## World Partition (Large Worlds)
|
||||
|
||||
### Use World Partition for Open Worlds
|
||||
|
||||
```cpp
|
||||
// Enable: World Settings > Enable World Partition
|
||||
// Automatically streams world cells based on player location
|
||||
|
||||
// Data Layers: Organize content (e.g., "Gameplay", "Audio", "Lighting")
|
||||
// Runtime Data Layers: Load/unload at runtime
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Niagara (VFX)
|
||||
|
||||
### Use Niagara (Not Cascade)
|
||||
|
||||
```cpp
|
||||
// Create: Content Browser > Right Click > FX > Niagara System
|
||||
// GPU-accelerated, node-based particle system (RECOMMENDED)
|
||||
|
||||
// Spawn particles:
|
||||
UNiagaraComponent* NiagaraComp = UNiagaraFunctionLibrary::SpawnSystemAtLocation(
|
||||
GetWorld(),
|
||||
ExplosionSystem,
|
||||
GetActorLocation()
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MetaSounds (Audio)
|
||||
|
||||
### Use MetaSounds for Procedural Audio
|
||||
|
||||
```cpp
|
||||
// Create: Content Browser > Right Click > Sounds > MetaSound Source
|
||||
// Node-based audio, replaces Sound Cue for complex logic (RECOMMENDED)
|
||||
|
||||
// Play MetaSound:
|
||||
UAudioComponent* AudioComp = UGameplayStatics::SpawnSound2D(
|
||||
GetWorld(),
|
||||
MetaSoundSource
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Replication (Multiplayer)
|
||||
|
||||
### Server-Authoritative Pattern
|
||||
|
||||
```cpp
|
||||
// ✅ Client sends input, server validates and replicates
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_Move(FVector Direction);
|
||||
|
||||
void AMyCharacter::Server_Move_Implementation(FVector Direction) {
|
||||
// Server validates and applies movement
|
||||
AddMovementInput(Direction);
|
||||
}
|
||||
|
||||
// ✅ Replicate important state
|
||||
UPROPERTY(Replicated)
|
||||
int32 Health;
|
||||
|
||||
void AMyCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const {
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
DOREPLIFETIME(AMyCharacter, Health);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Use Object Pooling
|
||||
|
||||
```cpp
|
||||
// ✅ Reuse objects instead of Spawn/Destroy
|
||||
TArray<AActor*> ProjectilePool;
|
||||
|
||||
AActor* GetPooledProjectile() {
|
||||
for (AActor* Proj : ProjectilePool) {
|
||||
if (!Proj->IsActive()) {
|
||||
Proj->SetActive(true);
|
||||
return Proj;
|
||||
}
|
||||
}
|
||||
// Pool exhausted, spawn new
|
||||
return SpawnNewProjectile();
|
||||
}
|
||||
```
|
||||
|
||||
### Use Instanced Static Meshes
|
||||
|
||||
```cpp
|
||||
// ✅ Hierarchical Instanced Static Mesh Component (HISM)
|
||||
// Render thousands of identical meshes in one draw call
|
||||
UHierarchicalInstancedStaticMeshComponent* HISM = CreateDefaultSubobject<UHierarchicalInstancedStaticMeshComponent>(TEXT("Trees"));
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
HISM->AddInstance(FTransform(RandomLocation));
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Use Logging
|
||||
|
||||
```cpp
|
||||
// ✅ Structured logging
|
||||
UE_LOG(LogTemp, Warning, TEXT("Player health: %d"), Health);
|
||||
|
||||
// Custom log category
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogMyGame, Log, All);
|
||||
DEFINE_LOG_CATEGORY(LogMyGame);
|
||||
UE_LOG(LogMyGame, Error, TEXT("Critical error!"));
|
||||
```
|
||||
|
||||
### Use Visual Logger
|
||||
|
||||
```cpp
|
||||
// ✅ Visual debugging
|
||||
#include "VisualLogger/VisualLogger.h"
|
||||
|
||||
UE_VLOG_SEGMENT(this, LogTemp, Log, StartPos, EndPos, FColor::Red, TEXT("Raycast"));
|
||||
UE_VLOG_LOCATION(this, LogTemp, Log, TargetLocation, 50.f, FColor::Green, TEXT("Target"));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary: UE 5.7 Recommended Stack
|
||||
|
||||
| Feature | Use This (2026) | Notes |
|
||||
|---------|------------------|-------|
|
||||
| **Lighting** | Lumen + Megalights | Real-time GI, millions of lights |
|
||||
| **Geometry** | Nanite | High-poly meshes, automatic LOD |
|
||||
| **Materials** | Substrate | Modular, physically accurate |
|
||||
| **Input** | Enhanced Input | Rebindable, modular |
|
||||
| **VFX** | Niagara | GPU-accelerated |
|
||||
| **Audio** | MetaSounds | Procedural audio |
|
||||
| **World Streaming** | World Partition | Large open worlds |
|
||||
| **Gameplay** | Gameplay Ability System | Complex abilities, buffs |
|
||||
|
||||
---
|
||||
|
||||
**Sources:**
|
||||
- https://docs.unrealengine.com/5.7/en-US/
|
||||
- https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-5-7-release-notes
|
||||
170
docs/engine-reference/unreal/deprecated-apis.md
Normal file
170
docs/engine-reference/unreal/deprecated-apis.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# Unreal Engine 5.7 — 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 |
|
||||
|------------|-------------|-------|
|
||||
| `InputComponent->BindAction()` | Enhanced Input `BindAction()` | New input system |
|
||||
| `InputComponent->BindAxis()` | Enhanced Input `BindAxis()` | New input system |
|
||||
| `PlayerController->GetInputAxisValue()` | Enhanced Input Action Values | New input system |
|
||||
|
||||
**Migration:** Install Enhanced Input plugin, create Input Actions and Input Mapping Contexts.
|
||||
|
||||
---
|
||||
|
||||
## Rendering
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| Legacy material nodes | Substrate material nodes | Substrate is production-ready in 5.7 |
|
||||
| Forward shading (default) | Deferred + Lumen | Lumen is default in UE5 |
|
||||
| Old lighting workflow | Lumen Global Illumination | Real-time GI |
|
||||
|
||||
---
|
||||
|
||||
## World Building
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| UE4 World Composition | World Partition (UE5) | Streaming large worlds |
|
||||
| Level Streaming Volumes | World Partition Data Layers | Better level streaming |
|
||||
|
||||
---
|
||||
|
||||
## Animation
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| Old animation retargeting | IK Rig + IK Retargeter | UE5 retargeting system |
|
||||
| Legacy control rig | Control Rig 2.0 | Production-ready rigging |
|
||||
|
||||
---
|
||||
|
||||
## Gameplay
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| `UGameplayStatics::LoadStreamLevel()` | World Partition streaming | Use Data Layers |
|
||||
| Hardcoded input bindings | Enhanced Input system | Rebindable, modular input |
|
||||
|
||||
---
|
||||
|
||||
## Niagara (VFX)
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| Cascade particle system | Niagara | Cascade is fully deprecated |
|
||||
|
||||
---
|
||||
|
||||
## Audio
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| Old audio mixer | MetaSounds | Procedural audio system |
|
||||
| Sound Cue (for complex logic) | MetaSounds | More powerful, node-based |
|
||||
|
||||
---
|
||||
|
||||
## Networking
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| `DOREPLIFETIME()` (basic) | `DOREPLIFETIME_CONDITION()` | Conditional replication for optimization |
|
||||
|
||||
---
|
||||
|
||||
## C++ Scripting
|
||||
|
||||
| Deprecated | Replacement | Notes |
|
||||
|------------|-------------|-------|
|
||||
| `TSharedPtr<T>` for UObjects | `TObjectPtr<T>` | UE5 type-safe pointers |
|
||||
| Manual RTTI checks | `Cast<T>()` / `IsA<T>()` | Type-safe casting |
|
||||
|
||||
---
|
||||
|
||||
## Quick Migration Patterns
|
||||
|
||||
### Input Example
|
||||
```cpp
|
||||
// ❌ Deprecated
|
||||
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) {
|
||||
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
|
||||
}
|
||||
|
||||
// ✅ Enhanced Input
|
||||
#include "EnhancedInputComponent.h"
|
||||
|
||||
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) {
|
||||
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(PlayerInputComponent);
|
||||
if (EIC) {
|
||||
EIC->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Material Example
|
||||
```cpp
|
||||
// ❌ Deprecated: Legacy material
|
||||
// Use standard material graph (still works but not recommended)
|
||||
|
||||
// ✅ Substrate Material
|
||||
// Enable: Project Settings > Engine > Substrate > Enable Substrate
|
||||
// Use Substrate nodes in material editor
|
||||
```
|
||||
|
||||
### World Partition Example
|
||||
```cpp
|
||||
// ❌ Deprecated: Level streaming volumes
|
||||
// Load/unload levels manually
|
||||
|
||||
// ✅ World Partition
|
||||
// Enable: World Settings > Enable World Partition
|
||||
// Use Data Layers for streaming
|
||||
```
|
||||
|
||||
### Particle System Example
|
||||
```cpp
|
||||
// ❌ Deprecated: Cascade
|
||||
UParticleSystemComponent* PSC = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("Particles"));
|
||||
|
||||
// ✅ Niagara
|
||||
UNiagaraComponent* NiagaraComp = CreateDefaultSubobject<UNiagaraComponent>(TEXT("Niagara"));
|
||||
```
|
||||
|
||||
### Audio Example
|
||||
```cpp
|
||||
// ❌ Deprecated: Sound Cue for complex logic
|
||||
// Use Sound Cue editor nodes
|
||||
|
||||
// ✅ MetaSounds
|
||||
// Create MetaSound Source asset, use node-based audio
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary: UE 5.7 Tech Stack
|
||||
|
||||
| Feature | Use This (2026) | Avoid This (Legacy) |
|
||||
|---------|------------------|----------------------|
|
||||
| **Input** | Enhanced Input | Legacy Input Bindings |
|
||||
| **Materials** | Substrate | Legacy Material System |
|
||||
| **Lighting** | Lumen + Megalights | Lightmaps + Limited Lights |
|
||||
| **Particles** | Niagara | Cascade |
|
||||
| **Audio** | MetaSounds | Sound Cue (for logic) |
|
||||
| **World Streaming** | World Partition | World Composition |
|
||||
| **Animation Retarget** | IK Rig + Retargeter | Old Retargeting |
|
||||
| **Geometry** | Nanite (high-poly) | Standard Static Mesh LODs |
|
||||
|
||||
---
|
||||
|
||||
**Sources:**
|
||||
- https://docs.unrealengine.com/5.7/en-US/deprecated-and-removed-features/
|
||||
- https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-5-7-release-notes
|
||||
292
docs/engine-reference/unreal/modules/animation.md
Normal file
292
docs/engine-reference/unreal/modules/animation.md
Normal file
@@ -0,0 +1,292 @@
|
||||
# Unreal Engine 5.7 — Animation Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** UE 5.7 animation authoring improvements, Control Rig 2.0
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
UE 5.7 animation systems:
|
||||
- **Animation Blueprint**: State machine-based animation logic
|
||||
- **Control Rig**: Runtime procedural animation (production-ready in UE5)
|
||||
- **IK Rig + Retargeter**: Modern retargeting system
|
||||
- **Sequencer**: Cinematic animation
|
||||
|
||||
---
|
||||
|
||||
## Animation Blueprint
|
||||
|
||||
### Create Animation Blueprint
|
||||
|
||||
1. Content Browser > Right Click > Animation > Animation Blueprint
|
||||
2. Select parent class: `AnimInstance`
|
||||
3. Select skeleton
|
||||
|
||||
### Animation State Machine
|
||||
|
||||
```cpp
|
||||
// In Animation Blueprint Event Graph:
|
||||
// - State Machine drives animation states (Idle, Walk, Run, Jump)
|
||||
// - Blend Spaces for directional movement
|
||||
|
||||
// Access in C++:
|
||||
UAnimInstance* AnimInstance = Mesh->GetAnimInstance();
|
||||
AnimInstance->Montage_Play(AttackMontage);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Play Animation Montages
|
||||
|
||||
### Animation Montage
|
||||
|
||||
```cpp
|
||||
// Play montage
|
||||
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
|
||||
AnimInstance->Montage_Play(AttackMontage, 1.0f);
|
||||
|
||||
// Stop montage
|
||||
AnimInstance->Montage_Stop(0.2f, AttackMontage);
|
||||
|
||||
// Check if montage is playing
|
||||
bool bIsPlaying = AnimInstance->Montage_IsPlaying(AttackMontage);
|
||||
```
|
||||
|
||||
### Montage Notify Events
|
||||
|
||||
```cpp
|
||||
// Add notify event in Animation Montage (right-click timeline > Add Notify > New Notify)
|
||||
// Implement in C++:
|
||||
|
||||
UCLASS()
|
||||
class UMyAnimInstance : public UAnimInstance {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION()
|
||||
void AnimNotify_AttackHit() {
|
||||
// Called when notify is reached
|
||||
DealDamage();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Blend Spaces
|
||||
|
||||
### 1D Blend Space (Speed Blending)
|
||||
|
||||
```cpp
|
||||
// Create: Content Browser > Animation > Blend Space 1D
|
||||
// Horizontal Axis: Speed (0 = Idle, 1 = Walk, 2 = Run)
|
||||
// Add animations at key points
|
||||
|
||||
// Use in Anim Blueprint:
|
||||
// - Get speed from character
|
||||
// - Feed into Blend Space
|
||||
```
|
||||
|
||||
### 2D Blend Space (Directional Movement)
|
||||
|
||||
```cpp
|
||||
// Create: Content Browser > Animation > Blend Space
|
||||
// Horizontal Axis: Direction X (-1 to 1)
|
||||
// Vertical Axis: Direction Y (-1 to 1)
|
||||
// Place animations (Fwd, Back, Left, Right, diagonal)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Control Rig (Procedural Animation)
|
||||
|
||||
### Create Control Rig
|
||||
|
||||
1. Content Browser > Animation > Control Rig
|
||||
2. Select skeleton
|
||||
3. Build rig hierarchy (bones, controls, IK)
|
||||
|
||||
### Use Control Rig in Animation Blueprint
|
||||
|
||||
```cpp
|
||||
// Add "Control Rig" node to Anim Blueprint
|
||||
// Assign Control Rig asset
|
||||
// Procedurally modify bones at runtime
|
||||
```
|
||||
|
||||
### Control Rig in C++
|
||||
|
||||
```cpp
|
||||
// Get control rig component
|
||||
UControlRig* ControlRig = /* Get from animation instance */;
|
||||
|
||||
// Set control value
|
||||
ControlRig->SetControlValue<FVector>(TEXT("IK_Hand_R"), TargetLocation);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## IK Rig & Retargeting (UE5)
|
||||
|
||||
### Create IK Rig
|
||||
|
||||
1. Content Browser > Animation > IK Rig
|
||||
2. Select skeleton
|
||||
3. Add IK goals (hands, feet)
|
||||
4. Set up solver chains
|
||||
|
||||
### Retarget Animations
|
||||
|
||||
1. Create IK Rig for source skeleton
|
||||
2. Create IK Rig for target skeleton
|
||||
3. Create IK Retargeter asset
|
||||
4. Assign source and target IK Rigs
|
||||
5. Batch retarget animations
|
||||
|
||||
### Retargeting in C++
|
||||
|
||||
```cpp
|
||||
// Retargeting is primarily editor-based
|
||||
// Animations are retargeted once, then used normally
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Animation Notify States
|
||||
|
||||
### Custom Notify State (Duration-Based Events)
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class UAnimNotifyState_Invulnerable : public UAnimNotifyState {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual void NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration, const FAnimNotifyEventReference& EventReference) override {
|
||||
// Start invulnerability
|
||||
AMyCharacter* Character = Cast<AMyCharacter>(MeshComp->GetOwner());
|
||||
Character->bIsInvulnerable = true;
|
||||
}
|
||||
|
||||
virtual void NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override {
|
||||
// End invulnerability
|
||||
AMyCharacter* Character = Cast<AMyCharacter>(MeshComp->GetOwner());
|
||||
Character->bIsInvulnerable = false;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Skeletal Mesh & Sockets
|
||||
|
||||
### Attach Objects to Sockets
|
||||
|
||||
```cpp
|
||||
// Create socket in Skeletal Mesh Editor (Skeleton Tree > Add Socket)
|
||||
|
||||
// Attach component to socket
|
||||
UStaticMeshComponent* Weapon = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Weapon"));
|
||||
Weapon->SetupAttachment(GetMesh(), TEXT("hand_r_socket"));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Animation Curves
|
||||
|
||||
### Use Animation Curves
|
||||
|
||||
```cpp
|
||||
// Add curve to animation:
|
||||
// Animation Editor > Curves > Add Curve
|
||||
|
||||
// Read curve value in Anim Blueprint or C++:
|
||||
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
|
||||
float CurveValue = AnimInstance->GetCurveValue(TEXT("MyCurve"));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Root Motion
|
||||
|
||||
### Enable Root Motion
|
||||
|
||||
```cpp
|
||||
// In Animation Sequence: Asset Details > Root Motion > Enable Root Motion
|
||||
|
||||
// In Character class:
|
||||
GetCharacterMovement()->bAllowPhysicsRotationDuringAnimRootMotion = true;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Animation Layers (Linked Anim Graphs)
|
||||
|
||||
### Use Linked Anim Layers
|
||||
|
||||
```cpp
|
||||
// Create separate Anim Blueprints for layers (e.g., upper body, lower body)
|
||||
// Link in main Anim Blueprint: Add "Linked Anim Graph" node
|
||||
|
||||
// Dynamically switch layers:
|
||||
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
|
||||
AnimInstance->LinkAnimClassLayers(NewLayerClass);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sequencer (Cinematic Animation)
|
||||
|
||||
### Create Sequence
|
||||
|
||||
1. Content Browser > Cinematics > Level Sequence
|
||||
2. Add tracks: Camera, Character, Animation, etc.
|
||||
|
||||
### Play Sequence from C++
|
||||
|
||||
```cpp
|
||||
#include "LevelSequenceActor.h"
|
||||
#include "LevelSequencePlayer.h"
|
||||
|
||||
ALevelSequenceActor* SequenceActor = /* Spawn or find in level */;
|
||||
SequenceActor->GetSequencePlayer()->Play();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
### Animation Optimization
|
||||
|
||||
```cpp
|
||||
// LOD (Level of Detail) for skeletal meshes
|
||||
// Reduce bone count for distant characters
|
||||
|
||||
// Anim Blueprint optimization:
|
||||
// - Use "Anim Node Relevancy" (skip updates when not visible)
|
||||
// - Disable updates when off-screen:
|
||||
GetMesh()->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::OnlyTickPoseWhenRendered;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Animation Debug Visualization
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// showdebug animation - Show animation state info
|
||||
// a.VisualizeSkeletalMeshBones 1 - Show skeleton bones
|
||||
|
||||
// Draw debug bones:
|
||||
DrawDebugCoordinateSystem(GetWorld(), BoneLocation, BoneRotation, 50.0f, false, -1.0f, 0, 2.0f);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/animation-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/control-rig-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/ik-rig-in-unreal-engine/
|
||||
289
docs/engine-reference/unreal/modules/audio.md
Normal file
289
docs/engine-reference/unreal/modules/audio.md
Normal file
@@ -0,0 +1,289 @@
|
||||
# Unreal Engine 5.7 — Audio Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** UE 5.7 MetaSounds production-ready
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
UE 5.7 audio systems:
|
||||
- **MetaSounds**: Node-based procedural audio (RECOMMENDED, production-ready)
|
||||
- **Sound Cues**: Legacy node-based audio (use for simple cases)
|
||||
- **Audio Component**: Play sounds on actors
|
||||
|
||||
---
|
||||
|
||||
## Basic Audio Playback
|
||||
|
||||
### Play Sound at Location
|
||||
|
||||
```cpp
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
// ✅ Play 2D sound (no spatialization)
|
||||
UGameplayStatics::PlaySound2D(GetWorld(), ExplosionSound);
|
||||
|
||||
// ✅ Play sound at location (3D spatial audio)
|
||||
UGameplayStatics::PlaySoundAtLocation(GetWorld(), ExplosionSound, GetActorLocation());
|
||||
|
||||
// ✅ With volume and pitch
|
||||
UGameplayStatics::PlaySoundAtLocation(GetWorld(), ExplosionSound, GetActorLocation(), 0.7f, 1.2f);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Audio Component
|
||||
|
||||
### Audio Component (Persistent Sound)
|
||||
|
||||
```cpp
|
||||
// Create audio component
|
||||
UAudioComponent* AudioComp = CreateDefaultSubobject<UAudioComponent>(TEXT("Audio"));
|
||||
AudioComp->SetupAttachment(RootComponent);
|
||||
AudioComp->SetSound(LoopingAmbience);
|
||||
|
||||
// Play/Stop
|
||||
AudioComp->Play();
|
||||
AudioComp->Stop();
|
||||
|
||||
// Fade in/out
|
||||
AudioComp->FadeIn(2.0f); // 2 seconds
|
||||
AudioComp->FadeOut(1.5f, 0.0f); // 1.5s to volume 0
|
||||
|
||||
// Adjust volume/pitch
|
||||
AudioComp->SetVolumeMultiplier(0.5f);
|
||||
AudioComp->SetPitchMultiplier(1.2f);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3D Spatial Audio
|
||||
|
||||
### Attenuation Settings
|
||||
|
||||
```cpp
|
||||
// Create Sound Attenuation asset:
|
||||
// Content Browser > Sounds > Sound Attenuation
|
||||
|
||||
// Configure:
|
||||
// - Attenuation Shape: Sphere, Capsule, Box, Cone
|
||||
// - Falloff Distance: Distance where sound becomes inaudible
|
||||
// - Attenuation Function: Linear, Logarithmic, Inverse, etc.
|
||||
|
||||
// Assign in C++:
|
||||
AudioComp->AttenuationSettings = AttenuationAsset;
|
||||
```
|
||||
|
||||
### Attenuation Override in Code
|
||||
|
||||
```cpp
|
||||
FSoundAttenuationSettings AttenuationOverride;
|
||||
AttenuationOverride.AttenuationShape = EAttenuationShape::Sphere;
|
||||
AttenuationOverride.FalloffDistance = 1000.0f;
|
||||
AttenuationOverride.AttenuationShapeExtents = FVector(1000.0f);
|
||||
|
||||
AudioComp->AttenuationOverrides = AttenuationOverride;
|
||||
AudioComp->bOverrideAttenuation = true;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MetaSounds (Procedural Audio)
|
||||
|
||||
### Create MetaSound Source
|
||||
|
||||
1. Content Browser > Sounds > MetaSound Source
|
||||
2. Open MetaSound editor
|
||||
3. Build node graph:
|
||||
- **Inputs**: Triggers, parameters
|
||||
- **Generators**: Oscillators, noise, samples
|
||||
- **Modulators**: Envelopes, LFOs
|
||||
- **Effects**: Filters, reverb, delay
|
||||
- **Output**: Audio output
|
||||
|
||||
### Play MetaSound
|
||||
|
||||
```cpp
|
||||
// Play MetaSound like any sound
|
||||
UGameplayStatics::PlaySound2D(GetWorld(), MetaSoundSource);
|
||||
|
||||
// Or with Audio Component
|
||||
AudioComp->SetSound(MetaSoundSource);
|
||||
AudioComp->Play();
|
||||
```
|
||||
|
||||
### Set MetaSound Parameters
|
||||
|
||||
```cpp
|
||||
// Define parameter in MetaSound (Input node with exposed parameter)
|
||||
// Set parameter in C++:
|
||||
AudioComp->SetFloatParameter(FName("Volume"), 0.8f);
|
||||
AudioComp->SetIntParameter(FName("OctaveShift"), 2);
|
||||
AudioComp->SetBoolParameter(FName("EnableReverb"), true);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sound Cues (Legacy)
|
||||
|
||||
### Create Sound Cue
|
||||
|
||||
1. Content Browser > Sounds > Sound Cue
|
||||
2. Open Sound Cue editor
|
||||
3. Add nodes: Random, Modulator, Mixer, etc.
|
||||
|
||||
### Use Sound Cue
|
||||
|
||||
```cpp
|
||||
// Play like any sound
|
||||
UGameplayStatics::PlaySound2D(GetWorld(), SoundCue);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sound Classes & Sound Mixes
|
||||
|
||||
### Sound Class (Volume Groups)
|
||||
|
||||
```cpp
|
||||
// Create Sound Class: Content Browser > Sounds > Sound Class
|
||||
// Hierarchy: Master > Music, SFX, Dialogue
|
||||
|
||||
// Assign to sound asset:
|
||||
// Sound Wave > Sound Class = SFX
|
||||
|
||||
// Set volume in C++:
|
||||
UAudioSettings* AudioSettings = GetMutableDefault<UAudioSettings>();
|
||||
// Configure via Sound Class hierarchy
|
||||
```
|
||||
|
||||
### Sound Mix (Dynamic Mixing)
|
||||
|
||||
```cpp
|
||||
// Create Sound Mix asset
|
||||
// Define adjustments: Lower music during dialogue, etc.
|
||||
|
||||
// Push sound mix
|
||||
UGameplayStatics::PushSoundMixModifier(GetWorld(), DuckedMusicMix);
|
||||
|
||||
// Pop sound mix
|
||||
UGameplayStatics::PopSoundMixModifier(GetWorld(), DuckedMusicMix);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Audio Occlusion & Reverb
|
||||
|
||||
### Audio Occlusion (Walls Block Sound)
|
||||
|
||||
```cpp
|
||||
// Enable in Audio Component:
|
||||
AudioComp->bEnableOcclusion = true;
|
||||
|
||||
// Requires geometry with collision
|
||||
```
|
||||
|
||||
### Reverb Volumes
|
||||
|
||||
```cpp
|
||||
// Add Audio Volume to level (Volumes > Audio Volume)
|
||||
// Configure reverb settings in Details panel
|
||||
// Audio component automatically picks up reverb when inside volume
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Footstep Sounds (Random Variation)
|
||||
|
||||
```cpp
|
||||
// Use Sound Cue with Random node, or:
|
||||
UPROPERTY(EditAnywhere, Category = "Audio")
|
||||
TArray<TObjectPtr<USoundBase>> FootstepSounds;
|
||||
|
||||
void PlayFootstep() {
|
||||
int32 Index = FMath::RandRange(0, FootstepSounds.Num() - 1);
|
||||
UGameplayStatics::PlaySoundAtLocation(GetWorld(), FootstepSounds[Index], GetActorLocation());
|
||||
}
|
||||
```
|
||||
|
||||
### Music Crossfade
|
||||
|
||||
```cpp
|
||||
UAudioComponent* MusicA;
|
||||
UAudioComponent* MusicB;
|
||||
|
||||
void CrossfadeMusic(float Duration) {
|
||||
MusicA->FadeOut(Duration, 0.0f);
|
||||
MusicB->FadeIn(Duration);
|
||||
}
|
||||
```
|
||||
|
||||
### Check if Sound is Playing
|
||||
|
||||
```cpp
|
||||
if (AudioComp->IsPlaying()) {
|
||||
// Sound is playing
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Audio Concurrency
|
||||
|
||||
### Limit Concurrent Sounds
|
||||
|
||||
```cpp
|
||||
// Create Sound Concurrency asset:
|
||||
// Content Browser > Sounds > Sound Concurrency
|
||||
|
||||
// Configure:
|
||||
// - Max Count: Maximum instances of this sound
|
||||
// - Resolution Rule: Stop Oldest, Stop Quietest, etc.
|
||||
|
||||
// Assign to sound:
|
||||
// Sound Wave > Concurrency Settings
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
### Audio Optimization
|
||||
|
||||
```cpp
|
||||
// Compression settings (Sound Wave asset):
|
||||
// - Compression Quality: 40 (balance quality/size)
|
||||
// - Streaming: Enable for large files (music)
|
||||
|
||||
// Reduce audio mixing cost:
|
||||
// - Limit concurrent sounds via Sound Concurrency
|
||||
// - Use simple attenuation shapes
|
||||
|
||||
// Disable audio for distant actors:
|
||||
if (Distance > MaxAudibleDistance) {
|
||||
AudioComp->Stop();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Audio Debug Commands
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// au.Debug.Sounds 1 - Show active sounds
|
||||
// au.3dVisualize.Enabled 1 - Visualize 3D audio
|
||||
// stat soundwaves - Show sound statistics
|
||||
// stat soundmixes - Show active sound mixes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/audio-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/metasounds-in-unreal-engine/
|
||||
288
docs/engine-reference/unreal/modules/input.md
Normal file
288
docs/engine-reference/unreal/modules/input.md
Normal file
@@ -0,0 +1,288 @@
|
||||
# Unreal Engine 5.7 — Input Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** UE 5.7 uses Enhanced Input as default (legacy input deprecated)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
UE 5.7 input systems:
|
||||
- **Enhanced Input** (RECOMMENDED, default in UE5): Modular, rebindable, context-based
|
||||
- **Legacy Input**: Deprecated, avoid for new projects
|
||||
|
||||
---
|
||||
|
||||
## Enhanced Input System
|
||||
|
||||
### Setup Enhanced Input
|
||||
|
||||
1. **Enable Plugin**: `Edit > Plugins > Enhanced Input` (enabled by default in UE5)
|
||||
2. **Project Settings**: `Engine > Input > Default Classes > Default Player Input Class = EnhancedPlayerInput`
|
||||
|
||||
---
|
||||
|
||||
### Create Input Actions
|
||||
|
||||
1. Content Browser > Input > Input Action
|
||||
2. Name it (e.g., `IA_Jump`, `IA_Move`)
|
||||
3. Configure:
|
||||
- **Value Type**: Digital (bool), Axis1D (float), Axis2D (Vector2D), Axis3D (Vector)
|
||||
|
||||
Example Input Actions:
|
||||
- `IA_Jump`: Digital (bool)
|
||||
- `IA_Move`: Axis2D (Vector2D)
|
||||
- `IA_Look`: Axis2D (Vector2D)
|
||||
- `IA_Fire`: Digital (bool)
|
||||
|
||||
---
|
||||
|
||||
### Create Input Mapping Context
|
||||
|
||||
1. Content Browser > Input > Input Mapping Context
|
||||
2. Name it (e.g., `IMC_Default`)
|
||||
3. Add mappings:
|
||||
- `IA_Jump` → Space Bar
|
||||
- `IA_Move` → W/A/S/D keys (combine X/Y)
|
||||
- `IA_Look` → Mouse XY
|
||||
- `IA_Fire` → Left Mouse Button
|
||||
|
||||
---
|
||||
|
||||
### Bind Input in C++
|
||||
|
||||
```cpp
|
||||
#include "EnhancedInputComponent.h"
|
||||
#include "EnhancedInputSubsystems.h"
|
||||
#include "InputActionValue.h"
|
||||
|
||||
class AMyCharacter : public ACharacter {
|
||||
public:
|
||||
// Input Actions (assign in Blueprint)
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||
TObjectPtr<UInputAction> MoveAction;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||
TObjectPtr<UInputAction> LookAction;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||
TObjectPtr<UInputAction> JumpAction;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||
TObjectPtr<UInputMappingContext> DefaultMappingContext;
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override {
|
||||
Super::BeginPlay();
|
||||
|
||||
// Add Input Mapping Context
|
||||
if (APlayerController* PC = Cast<APlayerController>(Controller)) {
|
||||
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
|
||||
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer())) {
|
||||
Subsystem->AddMappingContext(DefaultMappingContext, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override {
|
||||
Super::SetupPlayerInputComponent(PlayerInputComponent);
|
||||
|
||||
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(PlayerInputComponent);
|
||||
if (EIC) {
|
||||
// Bind actions
|
||||
EIC->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
|
||||
EIC->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
|
||||
|
||||
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::Move);
|
||||
EIC->BindAction(LookAction, ETriggerEvent::Triggered, this, &AMyCharacter::Look);
|
||||
}
|
||||
}
|
||||
|
||||
void Move(const FInputActionValue& Value) {
|
||||
FVector2D MoveVector = Value.Get<FVector2D>();
|
||||
|
||||
if (Controller) {
|
||||
AddMovementInput(GetActorForwardVector(), MoveVector.Y);
|
||||
AddMovementInput(GetActorRightVector(), MoveVector.X);
|
||||
}
|
||||
}
|
||||
|
||||
void Look(const FInputActionValue& Value) {
|
||||
FVector2D LookVector = Value.Get<FVector2D>();
|
||||
|
||||
if (Controller) {
|
||||
AddControllerYawInput(LookVector.X);
|
||||
AddControllerPitchInput(LookVector.Y);
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input Triggers
|
||||
|
||||
### Trigger Types
|
||||
|
||||
Input Actions can have triggers to control when they fire:
|
||||
- **Pressed**: When input starts
|
||||
- **Released**: When input ends
|
||||
- **Hold**: Hold for duration
|
||||
- **Tap**: Quick press
|
||||
- **Pulse**: Repeated firing while held
|
||||
|
||||
### Add Trigger in Editor
|
||||
|
||||
1. Open Input Action asset
|
||||
2. Triggers > Add > Select trigger type (e.g., `Hold`)
|
||||
3. Configure (e.g., Hold Time = 0.5s)
|
||||
|
||||
---
|
||||
|
||||
## Input Modifiers
|
||||
|
||||
### Modifier Types
|
||||
|
||||
Modifiers transform input values:
|
||||
- **Negate**: Flip sign (-1 ↔ 1)
|
||||
- **Dead Zone**: Ignore small inputs
|
||||
- **Scalar**: Multiply by value
|
||||
- **Smooth**: Smoothing over time
|
||||
|
||||
### Add Modifier in Editor
|
||||
|
||||
1. Open Input Action asset
|
||||
2. Modifiers > Add > Select modifier (e.g., `Negate`)
|
||||
3. Configure
|
||||
|
||||
---
|
||||
|
||||
## Input Mapping Contexts (Context Switching)
|
||||
|
||||
### Multiple Contexts
|
||||
|
||||
```cpp
|
||||
// Define contexts
|
||||
UPROPERTY(EditAnywhere, Category = "Input")
|
||||
TObjectPtr<UInputMappingContext> DefaultContext;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Input")
|
||||
TObjectPtr<UInputMappingContext> VehicleContext;
|
||||
|
||||
// Switch context
|
||||
void EnterVehicle() {
|
||||
if (APlayerController* PC = Cast<APlayerController>(Controller)) {
|
||||
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
|
||||
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer())) {
|
||||
Subsystem->RemoveMappingContext(DefaultContext);
|
||||
Subsystem->AddMappingContext(VehicleContext, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Legacy Input (Deprecated)
|
||||
|
||||
### Legacy Input Bindings
|
||||
|
||||
```cpp
|
||||
// ❌ DEPRECATED: Do not use for new projects
|
||||
|
||||
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) {
|
||||
// Legacy action binding
|
||||
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
|
||||
|
||||
// Legacy axis binding
|
||||
PlayerInputComponent->BindAxis("MoveForward", this, &AMyCharacter::MoveForward);
|
||||
}
|
||||
|
||||
void MoveForward(float Value) {
|
||||
AddMovementInput(GetActorForwardVector(), Value);
|
||||
}
|
||||
```
|
||||
|
||||
**Migration:** Use Enhanced Input instead.
|
||||
|
||||
---
|
||||
|
||||
## Gamepad Input
|
||||
|
||||
### Gamepad with Enhanced Input
|
||||
|
||||
```cpp
|
||||
// Input Mapping Context:
|
||||
// - IA_Move → Gamepad Left Thumbstick
|
||||
// - IA_Look → Gamepad Right Thumbstick
|
||||
// - IA_Jump → Gamepad Face Button Bottom (A/Cross)
|
||||
|
||||
// No code changes needed, just add gamepad mappings to Input Mapping Context
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Touch Input (Mobile)
|
||||
|
||||
### Touch Input with Enhanced Input
|
||||
|
||||
```cpp
|
||||
// Input Mapping Context:
|
||||
// - IA_Move → Touch (virtual thumbstick)
|
||||
// - IA_Look → Touch (swipe)
|
||||
|
||||
// Use Touch Interface asset for virtual controls
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rebinding Input at Runtime
|
||||
|
||||
### Change Key Mapping
|
||||
|
||||
```cpp
|
||||
#include "PlayerMappableInputConfig.h"
|
||||
|
||||
// Get subsystem
|
||||
UEnhancedInputLocalPlayerSubsystem* Subsystem = /* Get subsystem */;
|
||||
|
||||
// Get player mappable keys
|
||||
FPlayerMappableKeySlot KeySlot = FPlayerMappableKeySlot(/*..*/);
|
||||
FKey NewKey = EKeys::F; // Rebind to F key
|
||||
|
||||
// Apply new mapping
|
||||
Subsystem->AddPlayerMappedKey(/*..*/);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input Debugging
|
||||
|
||||
### Debug Input
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// showdebug input - Show input debug info
|
||||
|
||||
// Log input values:
|
||||
UE_LOG(LogTemp, Warning, TEXT("Move Input: %s"), *MoveVector.ToString());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Check if Key Pressed (Quick & Dirty)
|
||||
|
||||
```cpp
|
||||
// For debugging only (not recommended for gameplay)
|
||||
if (GetWorld()->GetFirstPlayerController()->IsInputKeyDown(EKeys::SpaceBar)) {
|
||||
// Space bar is down
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/enhanced-input-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/enhanced-input-action-and-input-mapping-context-in-unreal-engine/
|
||||
338
docs/engine-reference/unreal/modules/navigation.md
Normal file
338
docs/engine-reference/unreal/modules/navigation.md
Normal file
@@ -0,0 +1,338 @@
|
||||
# Unreal Engine 5.7 — Navigation Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** UE 5.7 navigation improvements
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
UE 5.7 navigation systems:
|
||||
- **Nav Mesh**: Automatic pathfinding mesh for AI
|
||||
- **AI Controller**: Controls AI movement and behavior
|
||||
- **Behavior Trees**: AI decision-making (covered in AI module)
|
||||
|
||||
---
|
||||
|
||||
## Nav Mesh Setup
|
||||
|
||||
### Add Nav Mesh Bounds Volume
|
||||
|
||||
1. Place Actors > Volumes > Nav Mesh Bounds Volume
|
||||
2. Scale to cover walkable areas
|
||||
3. Press `P` to toggle Nav Mesh visualization (green overlay)
|
||||
|
||||
### Nav Mesh Settings
|
||||
|
||||
```cpp
|
||||
// Project Settings > Engine > Navigation System
|
||||
// - Generate Navigation Only Around Navigation Invokers: Performance optimization
|
||||
// - Auto Update Enabled: Rebuild NavMesh when geometry changes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## AI Controller & Movement
|
||||
|
||||
### Create AI Controller
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class AEnemyAIController : public AAIController {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
void BeginPlay() override {
|
||||
Super::BeginPlay();
|
||||
|
||||
// Move to location
|
||||
FVector TargetLocation = FVector(1000, 0, 0);
|
||||
MoveToLocation(TargetLocation);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Assign AI Controller to Pawn
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class AEnemyCharacter : public ACharacter {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AEnemyCharacter() {
|
||||
// ✅ Assign AI Controller class
|
||||
AIControllerClass = AEnemyAIController::StaticClass();
|
||||
AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Basic AI Movement
|
||||
|
||||
### Move to Location
|
||||
|
||||
```cpp
|
||||
AAIController* AIController = Cast<AAIController>(GetController());
|
||||
if (AIController) {
|
||||
FVector TargetLocation = FVector(1000, 0, 0);
|
||||
EPathFollowingRequestResult::Type Result = AIController->MoveToLocation(TargetLocation);
|
||||
|
||||
if (Result == EPathFollowingRequestResult::RequestSuccessful) {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Moving to location"));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Move to Actor
|
||||
|
||||
```cpp
|
||||
AActor* Target = /* Get target actor */;
|
||||
AIController->MoveToActor(Target, 100.0f); // Stop 100 units away
|
||||
```
|
||||
|
||||
### Stop Movement
|
||||
|
||||
```cpp
|
||||
AIController->StopMovement();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Path Following Events
|
||||
|
||||
### On Move Completed
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class AEnemyAIController : public AAIController {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
void BeginPlay() override {
|
||||
Super::BeginPlay();
|
||||
|
||||
// Bind to move completed event
|
||||
ReceiveMoveCompleted.AddDynamic(this, &AEnemyAIController::OnMoveCompleted);
|
||||
}
|
||||
|
||||
UFUNCTION()
|
||||
void OnMoveCompleted(FAIRequestID RequestID, EPathFollowingResult::Type Result) {
|
||||
if (Result == EPathFollowingResult::Success) {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Reached destination"));
|
||||
} else {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Failed to reach destination"));
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pathfinding Queries
|
||||
|
||||
### Find Path to Location
|
||||
|
||||
```cpp
|
||||
#include "NavigationSystem.h"
|
||||
#include "NavigationPath.h"
|
||||
|
||||
UNavigationSystemV1* NavSys = UNavigationSystemV1::GetCurrent(GetWorld());
|
||||
if (NavSys) {
|
||||
FVector Start = GetActorLocation();
|
||||
FVector End = TargetLocation;
|
||||
|
||||
FPathFindingQuery Query;
|
||||
Query.StartLocation = Start;
|
||||
Query.EndLocation = End;
|
||||
Query.NavData = NavSys->GetDefaultNavDataInstance();
|
||||
|
||||
FPathFindingResult Result = NavSys->FindPathSync(Query);
|
||||
|
||||
if (Result.IsSuccessful()) {
|
||||
UNavigationPath* NavPath = Result.Path.Get();
|
||||
// Use path points: NavPath->GetPathPoints()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Check if Location is Reachable
|
||||
|
||||
```cpp
|
||||
UNavigationSystemV1* NavSys = UNavigationSystemV1::GetCurrent(GetWorld());
|
||||
FNavLocation OutLocation;
|
||||
bool bReachable = NavSys->ProjectPointToNavigation(TargetLocation, OutLocation);
|
||||
|
||||
if (bReachable) {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Location is reachable"));
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nav Mesh Modifiers
|
||||
|
||||
### Nav Modifier Volume (Block/Allow Areas)
|
||||
|
||||
1. Place Actors > Volumes > Nav Modifier Volume
|
||||
2. Configure Area Class (e.g., NavArea_Null to block, NavArea_LowHeight for crouching)
|
||||
|
||||
---
|
||||
|
||||
## Custom Nav Areas
|
||||
|
||||
### Create Custom Nav Area
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class UNavArea_Jump : public UNavArea {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UNavArea_Jump() {
|
||||
DefaultCost = 10.0f; // Higher cost = AI avoids unless necessary
|
||||
FixedAreaEnteringCost = 100.0f; // One-time cost to enter
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Use Custom Nav Area
|
||||
|
||||
```cpp
|
||||
// Assign to Nav Modifier Volume or geometry
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nav Mesh Generation
|
||||
|
||||
### Rebuild Nav Mesh at Runtime
|
||||
|
||||
```cpp
|
||||
UNavigationSystemV1* NavSys = UNavigationSystemV1::GetCurrent(GetWorld());
|
||||
NavSys->Build(); // Rebuild entire NavMesh
|
||||
```
|
||||
|
||||
### Dynamic Nav Mesh (Moving Obstacles)
|
||||
|
||||
```cpp
|
||||
// Enable: Project Settings > Navigation System > Runtime Generation = Dynamic
|
||||
|
||||
// Mark actor as dynamic obstacle:
|
||||
UStaticMeshComponent* Mesh = /* Get mesh */;
|
||||
Mesh->SetCanEverAffectNavigation(true);
|
||||
Mesh->bDynamicObstacle = true;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nav Links (Off-Mesh Connections)
|
||||
|
||||
### Nav Link Proxy (Jump, Teleport)
|
||||
|
||||
1. Place Actors > Navigation > Nav Link Proxy
|
||||
2. Set up start and end points
|
||||
3. Configure:
|
||||
- **Direction**: One-way or bidirectional
|
||||
- **Smart Link**: Animate character during traversal
|
||||
|
||||
---
|
||||
|
||||
## Crowd Management
|
||||
|
||||
### Detour Crowd (Avoid Overlapping)
|
||||
|
||||
```cpp
|
||||
// Enable: Character Movement Component > Avoidance Enabled = true
|
||||
|
||||
// Configure avoidance group and flags
|
||||
UCharacterMovementComponent* MoveComp = GetCharacterMovement();
|
||||
MoveComp->SetAvoidanceGroup(1);
|
||||
MoveComp->SetGroupsToAvoid(1);
|
||||
MoveComp->SetAvoidanceEnabled(true);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
### Nav Mesh Optimization
|
||||
|
||||
```cpp
|
||||
// Reduce tile size for large worlds:
|
||||
// Project Settings > Navigation System > Cell Size = 19 (default)
|
||||
|
||||
// Use Navigation Invokers for dynamic generation:
|
||||
// Only generate NavMesh around players/important actors
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Visualize Nav Mesh
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// show navigation - Toggle NavMesh visualization
|
||||
// p - Toggle NavMesh (editor viewport)
|
||||
|
||||
// Draw debug path:
|
||||
if (NavPath) {
|
||||
for (int i = 0; i < NavPath->GetPathPoints().Num() - 1; i++) {
|
||||
DrawDebugLine(GetWorld(), NavPath->GetPathPoints()[i], NavPath->GetPathPoints()[i + 1], FColor::Green, false, 5.0f, 0, 5.0f);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Patrol Between Waypoints
|
||||
|
||||
```cpp
|
||||
UPROPERTY(EditAnywhere, Category = "AI")
|
||||
TArray<AActor*> PatrolPoints;
|
||||
|
||||
int32 CurrentPatrolIndex = 0;
|
||||
|
||||
void OnMoveCompleted(FAIRequestID RequestID, EPathFollowingResult::Type Result) {
|
||||
if (Result == EPathFollowingResult::Success) {
|
||||
// Move to next waypoint
|
||||
CurrentPatrolIndex = (CurrentPatrolIndex + 1) % PatrolPoints.Num();
|
||||
MoveToActor(PatrolPoints[CurrentPatrolIndex]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Chase Player
|
||||
|
||||
```cpp
|
||||
void Tick(float DeltaTime) {
|
||||
Super::Tick(DeltaTime);
|
||||
|
||||
AAIController* AIController = Cast<AAIController>(GetController());
|
||||
APawn* PlayerPawn = GetWorld()->GetFirstPlayerController()->GetPawn();
|
||||
|
||||
if (AIController && PlayerPawn) {
|
||||
float Distance = FVector::Dist(GetActorLocation(), PlayerPawn->GetActorLocation());
|
||||
|
||||
if (Distance < 1000.0f) {
|
||||
// Chase player
|
||||
AIController->MoveToActor(PlayerPawn, 100.0f);
|
||||
} else {
|
||||
// Stop chasing
|
||||
AIController->StopMovement();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/navigation-system-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/ai-in-unreal-engine/
|
||||
409
docs/engine-reference/unreal/modules/networking.md
Normal file
409
docs/engine-reference/unreal/modules/networking.md
Normal file
@@ -0,0 +1,409 @@
|
||||
# Unreal Engine 5.7 — Networking Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** UE 5.7 networking improvements
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
UE 5.7 networking:
|
||||
- **Client-Server Architecture**: Server-authoritative (RECOMMENDED)
|
||||
- **Replication**: Automatic state synchronization
|
||||
- **RPCs (Remote Procedure Calls)**: Call functions across network
|
||||
- **Relevancy**: Optimize bandwidth by only replicating relevant actors
|
||||
|
||||
---
|
||||
|
||||
## Basic Multiplayer Setup
|
||||
|
||||
### Enable Replication on Actor
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class AMyActor : public AActor {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AMyActor() {
|
||||
// ✅ Enable replication
|
||||
bReplicates = true;
|
||||
bAlwaysRelevant = true; // Always replicate to all clients
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Network Role Checks
|
||||
|
||||
```cpp
|
||||
// Check role
|
||||
if (HasAuthority()) {
|
||||
// Running on server
|
||||
}
|
||||
|
||||
if (GetLocalRole() == ROLE_AutonomousProxy) {
|
||||
// This is the owning client (local player)
|
||||
}
|
||||
|
||||
if (GetRemoteRole() == ROLE_SimulatedProxy) {
|
||||
// This is a remote client (other players)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Replicated Variables
|
||||
|
||||
### Basic Replication
|
||||
|
||||
```cpp
|
||||
UPROPERTY(Replicated)
|
||||
int32 Health;
|
||||
|
||||
UPROPERTY(Replicated)
|
||||
FVector Position;
|
||||
|
||||
// ✅ Implement GetLifetimeReplicatedProps
|
||||
void AMyActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const {
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
|
||||
DOREPLIFETIME(AMyActor, Health);
|
||||
DOREPLIFETIME(AMyActor, Position);
|
||||
}
|
||||
```
|
||||
|
||||
### Conditional Replication
|
||||
|
||||
```cpp
|
||||
// Only replicate to owner
|
||||
DOREPLIFETIME_CONDITION(AMyCharacter, Ammo, COND_OwnerOnly);
|
||||
|
||||
// Skip owner (replicate to everyone else)
|
||||
DOREPLIFETIME_CONDITION(AMyCharacter, TeamID, COND_SkipOwner);
|
||||
|
||||
// Only when changed
|
||||
DOREPLIFETIME_CONDITION(AMyCharacter, Score, COND_InitialOnly);
|
||||
```
|
||||
|
||||
### RepNotify (Callback on Replication)
|
||||
|
||||
```cpp
|
||||
UPROPERTY(ReplicatedUsing=OnRep_Health)
|
||||
int32 Health;
|
||||
|
||||
UFUNCTION()
|
||||
void OnRep_Health() {
|
||||
// Called on clients when Health changes
|
||||
UpdateHealthUI();
|
||||
}
|
||||
|
||||
// Implement GetLifetimeReplicatedProps (same as above)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## RPCs (Remote Procedure Calls)
|
||||
|
||||
### Server RPC (Client → Server)
|
||||
|
||||
```cpp
|
||||
// Client calls, server executes
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_TakeDamage(int32 Damage);
|
||||
|
||||
void AMyCharacter::Server_TakeDamage_Implementation(int32 Damage) {
|
||||
// Runs on server only
|
||||
Health -= Damage;
|
||||
|
||||
if (Health <= 0) {
|
||||
Server_Die();
|
||||
}
|
||||
}
|
||||
|
||||
bool AMyCharacter::Server_TakeDamage_Validate(int32 Damage) {
|
||||
// Validate input (anti-cheat)
|
||||
return Damage >= 0 && Damage <= 100;
|
||||
}
|
||||
```
|
||||
|
||||
### Client RPC (Server → Client)
|
||||
|
||||
```cpp
|
||||
// Server calls, client executes
|
||||
UFUNCTION(Client, Reliable)
|
||||
void Client_ShowDeathScreen();
|
||||
|
||||
void AMyCharacter::Client_ShowDeathScreen_Implementation() {
|
||||
// Runs on client only
|
||||
ShowDeathUI();
|
||||
}
|
||||
```
|
||||
|
||||
### Multicast RPC (Server → All Clients)
|
||||
|
||||
```cpp
|
||||
// Server calls, all clients execute
|
||||
UFUNCTION(NetMulticast, Reliable)
|
||||
void Multicast_PlayExplosion(FVector Location);
|
||||
|
||||
void AMyActor::Multicast_PlayExplosion_Implementation(FVector Location) {
|
||||
// Runs on server and all clients
|
||||
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ExplosionEffect, Location);
|
||||
}
|
||||
```
|
||||
|
||||
### RPC Reliability
|
||||
|
||||
```cpp
|
||||
// Reliable: Guaranteed delivery (important events)
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_FireWeapon();
|
||||
|
||||
// Unreliable: Best-effort delivery (frequent updates, position sync)
|
||||
UFUNCTION(Server, Unreliable)
|
||||
void Server_UpdateAim(FRotator AimRotation);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Server-Authoritative Pattern (RECOMMENDED)
|
||||
|
||||
### Movement Example
|
||||
|
||||
```cpp
|
||||
class AMyCharacter : public ACharacter {
|
||||
UPROPERTY(Replicated)
|
||||
FVector ServerPosition;
|
||||
|
||||
void Tick(float DeltaTime) override {
|
||||
Super::Tick(DeltaTime);
|
||||
|
||||
if (GetLocalRole() == ROLE_AutonomousProxy) {
|
||||
// Client: Send input to server
|
||||
FVector Input = GetMovementInput();
|
||||
Server_Move(Input);
|
||||
|
||||
// Client-side prediction (move locally)
|
||||
AddMovementInput(Input);
|
||||
}
|
||||
|
||||
if (HasAuthority()) {
|
||||
// Server: Authoritative position
|
||||
ServerPosition = GetActorLocation();
|
||||
} else {
|
||||
// Client: Interpolate toward server position
|
||||
FVector NewPos = FMath::VInterpTo(GetActorLocation(), ServerPosition, DeltaTime, 5.0f);
|
||||
SetActorLocation(NewPos);
|
||||
}
|
||||
}
|
||||
|
||||
UFUNCTION(Server, Unreliable)
|
||||
void Server_Move(FVector Input);
|
||||
|
||||
void Server_Move_Implementation(FVector Input) {
|
||||
// Server validates and applies movement
|
||||
AddMovementInput(Input);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Network Relevancy (Bandwidth Optimization)
|
||||
|
||||
### Custom Relevancy
|
||||
|
||||
```cpp
|
||||
bool AMyActor::IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget, const FVector& SrcLocation) const {
|
||||
// Only replicate if within range
|
||||
float Distance = FVector::Dist(SrcLocation, GetActorLocation());
|
||||
return Distance < 5000.0f;
|
||||
}
|
||||
```
|
||||
|
||||
### Always Relevant Actors
|
||||
|
||||
```cpp
|
||||
AMyActor() {
|
||||
bAlwaysRelevant = true; // Replicate to all clients (e.g., GameState, PlayerController)
|
||||
bOnlyRelevantToOwner = true; // Only replicate to owner (e.g., PlayerController)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Ownership
|
||||
|
||||
### Set Owner
|
||||
|
||||
```cpp
|
||||
// Assign owner (important for RPCs and relevancy)
|
||||
MyActor->SetOwner(OwningPlayerController);
|
||||
```
|
||||
|
||||
### Check Owner
|
||||
|
||||
```cpp
|
||||
if (GetOwner() == PlayerController) {
|
||||
// This actor is owned by this player
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Game Mode & Game State
|
||||
|
||||
### Game Mode (Server Only)
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class AMyGameMode : public AGameMode {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Game mode only exists on server
|
||||
// Use for server-side logic (spawning, scoring, rules)
|
||||
};
|
||||
```
|
||||
|
||||
### Game State (Replicated to All Clients)
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class AMyGameState : public AGameState {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// ✅ Replicate game state to all clients
|
||||
UPROPERTY(Replicated)
|
||||
int32 RedTeamScore;
|
||||
|
||||
UPROPERTY(Replicated)
|
||||
int32 BlueTeamScore;
|
||||
|
||||
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override {
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
DOREPLIFETIME(AMyGameState, RedTeamScore);
|
||||
DOREPLIFETIME(AMyGameState, BlueTeamScore);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Player Controller & Player State
|
||||
|
||||
### Player Controller (One per Player)
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class AMyPlayerController : public APlayerController {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Exists on server and owning client
|
||||
// Use for player-specific logic, input handling
|
||||
};
|
||||
```
|
||||
|
||||
### Player State (Replicated Player Info)
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class AMyPlayerState : public APlayerState {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(Replicated)
|
||||
int32 Kills;
|
||||
|
||||
UPROPERTY(Replicated)
|
||||
int32 Deaths;
|
||||
|
||||
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override {
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
DOREPLIFETIME(AMyPlayerState, Kills);
|
||||
DOREPLIFETIME(AMyPlayerState, Deaths);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sessions & Matchmaking
|
||||
|
||||
### Create Session
|
||||
|
||||
```cpp
|
||||
#include "OnlineSubsystem.h"
|
||||
#include "OnlineSessionSettings.h"
|
||||
|
||||
void CreateSession() {
|
||||
IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get();
|
||||
IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();
|
||||
|
||||
TSharedPtr<FOnlineSessionSettings> SessionSettings = MakeShareable(new FOnlineSessionSettings());
|
||||
SessionSettings->bIsLANMatch = false;
|
||||
SessionSettings->NumPublicConnections = 4;
|
||||
SessionSettings->bShouldAdvertise = true;
|
||||
|
||||
Sessions->CreateSession(0, FName("MySession"), *SessionSettings);
|
||||
}
|
||||
```
|
||||
|
||||
### Find Sessions
|
||||
|
||||
```cpp
|
||||
void FindSessions() {
|
||||
IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get();
|
||||
IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();
|
||||
|
||||
TSharedRef<FOnlineSessionSearch> SearchSettings = MakeShareable(new FOnlineSessionSearch());
|
||||
SearchSettings->bIsLanQuery = false;
|
||||
SearchSettings->MaxSearchResults = 20;
|
||||
|
||||
Sessions->FindSessions(0, SearchSettings);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
### Reduce Bandwidth
|
||||
|
||||
```cpp
|
||||
// Use unreliable RPCs for frequent updates
|
||||
UFUNCTION(Server, Unreliable)
|
||||
void Server_UpdatePosition(FVector Pos);
|
||||
|
||||
// Conditional replication (only replicate to relevant clients)
|
||||
DOREPLIFETIME_CONDITION(AMyActor, Health, COND_OwnerOnly);
|
||||
|
||||
// Limit replication frequency
|
||||
SetReplicationFrequency(10.0f); // Update 10 times per second (default 100)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Network Debugging
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// stat net - Show network stats
|
||||
// stat netplayerupdate - Show player update stats
|
||||
// NetEmulation PktLoss=10 - Simulate 10% packet loss
|
||||
// NetEmulation PktLag=100 - Simulate 100ms latency
|
||||
|
||||
// Draw debug for replication:
|
||||
UE_LOG(LogNet, Warning, TEXT("Replicating Health: %d"), Health);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/networking-and-multiplayer-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/actor-replication-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/rpcs-in-unreal-engine/
|
||||
283
docs/engine-reference/unreal/modules/physics.md
Normal file
283
docs/engine-reference/unreal/modules/physics.md
Normal file
@@ -0,0 +1,283 @@
|
||||
# Unreal Engine 5.7 — Physics Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** UE 5.7 Chaos Physics improvements
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
UE 5 uses **Chaos Physics** (replaced PhysX in UE 4):
|
||||
- Better performance
|
||||
- Destruction support
|
||||
- Vehicle physics improvements
|
||||
|
||||
---
|
||||
|
||||
## Rigid Body Physics
|
||||
|
||||
### Enable Physics on Static Mesh
|
||||
|
||||
```cpp
|
||||
UStaticMeshComponent* MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
|
||||
MeshComp->SetSimulatePhysics(true);
|
||||
MeshComp->SetEnableGravity(true);
|
||||
MeshComp->SetMassOverrideInKg(NAME_None, 50.0f); // 50 kg
|
||||
```
|
||||
|
||||
### Apply Forces
|
||||
|
||||
```cpp
|
||||
// Apply impulse (instant velocity change)
|
||||
MeshComp->AddImpulse(FVector(0, 0, 1000), NAME_None, true);
|
||||
|
||||
// Apply force (continuous)
|
||||
MeshComp->AddForce(FVector(0, 0, 500));
|
||||
|
||||
// Apply torque (rotation)
|
||||
MeshComp->AddTorqueInRadians(FVector(0, 0, 100));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Collision
|
||||
|
||||
### Collision Channels
|
||||
|
||||
```cpp
|
||||
// Project Settings > Engine > Collision
|
||||
// Define custom collision channels and responses
|
||||
|
||||
// Set collision in C++
|
||||
MeshComp->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
|
||||
MeshComp->SetCollisionObjectType(ECollisionChannel::ECC_Pawn);
|
||||
MeshComp->SetCollisionResponseToAllChannels(ECR_Block);
|
||||
MeshComp->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);
|
||||
```
|
||||
|
||||
### Collision Events
|
||||
|
||||
```cpp
|
||||
// Enable collision events
|
||||
MeshComp->SetNotifyRigidBodyCollision(true);
|
||||
|
||||
// Bind to OnComponentHit
|
||||
MeshComp->OnComponentHit.AddDynamic(this, &AMyActor::OnHit);
|
||||
|
||||
UFUNCTION()
|
||||
void AMyActor::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor,
|
||||
UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Hit %s"), *OtherActor->GetName());
|
||||
}
|
||||
```
|
||||
|
||||
### Overlap Events
|
||||
|
||||
```cpp
|
||||
// Enable overlap events
|
||||
MeshComp->SetGenerateOverlapEvents(true);
|
||||
|
||||
// Bind to OnComponentBeginOverlap
|
||||
MeshComp->OnComponentBeginOverlap.AddDynamic(this, &AMyActor::OnOverlapBegin);
|
||||
|
||||
UFUNCTION()
|
||||
void AMyActor::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
|
||||
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Overlapped %s"), *OtherActor->GetName());
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Raycasting (Line Traces)
|
||||
|
||||
### Single Line Trace
|
||||
|
||||
```cpp
|
||||
FHitResult HitResult;
|
||||
FVector Start = GetActorLocation();
|
||||
FVector End = Start + GetActorForwardVector() * 1000.0f;
|
||||
|
||||
FCollisionQueryParams QueryParams;
|
||||
QueryParams.AddIgnoredActor(this);
|
||||
|
||||
// Perform trace
|
||||
bool bHit = GetWorld()->LineTraceSingleByChannel(
|
||||
HitResult,
|
||||
Start,
|
||||
End,
|
||||
ECC_Visibility,
|
||||
QueryParams
|
||||
);
|
||||
|
||||
if (bHit) {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Hit: %s"), *HitResult.GetActor()->GetName());
|
||||
DrawDebugLine(GetWorld(), Start, HitResult.Location, FColor::Red, false, 2.0f);
|
||||
}
|
||||
```
|
||||
|
||||
### Multi Line Trace
|
||||
|
||||
```cpp
|
||||
TArray<FHitResult> HitResults;
|
||||
bool bHit = GetWorld()->LineTraceMultiByChannel(
|
||||
HitResults,
|
||||
Start,
|
||||
End,
|
||||
ECC_Visibility,
|
||||
QueryParams
|
||||
);
|
||||
|
||||
for (const FHitResult& Hit : HitResults) {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Hit: %s"), *Hit.GetActor()->GetName());
|
||||
}
|
||||
```
|
||||
|
||||
### Sweep (Thick Trace)
|
||||
|
||||
```cpp
|
||||
FHitResult HitResult;
|
||||
FCollisionShape Sphere = FCollisionShape::MakeSphere(50.0f);
|
||||
|
||||
bool bHit = GetWorld()->SweepSingleByChannel(
|
||||
HitResult,
|
||||
Start,
|
||||
End,
|
||||
FQuat::Identity,
|
||||
ECC_Visibility,
|
||||
Sphere,
|
||||
QueryParams
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Character Movement
|
||||
|
||||
### Character Movement Component
|
||||
|
||||
```cpp
|
||||
// Built into ACharacter class
|
||||
UCharacterMovementComponent* MoveComp = GetCharacterMovement();
|
||||
|
||||
// Configure movement
|
||||
MoveComp->MaxWalkSpeed = 600.0f;
|
||||
MoveComp->JumpZVelocity = 600.0f;
|
||||
MoveComp->AirControl = 0.2f;
|
||||
MoveComp->GravityScale = 1.0f;
|
||||
MoveComp->bOrientRotationToMovement = true;
|
||||
```
|
||||
|
||||
### Add Movement Input
|
||||
|
||||
```cpp
|
||||
// In Character class
|
||||
void AMyCharacter::MoveForward(float Value) {
|
||||
if (Value != 0.0f) {
|
||||
AddMovementInput(GetActorForwardVector(), Value);
|
||||
}
|
||||
}
|
||||
|
||||
void AMyCharacter::MoveRight(float Value) {
|
||||
if (Value != 0.0f) {
|
||||
AddMovementInput(GetActorRightVector(), Value);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Physical Materials
|
||||
|
||||
### Create Physical Material
|
||||
|
||||
1. Content Browser > Right Click > Physics > Physical Material
|
||||
2. Configure properties:
|
||||
- Friction: 0.0 - 1.0
|
||||
- Restitution (bounciness): 0.0 - 1.0
|
||||
|
||||
### Assign Physical Material
|
||||
|
||||
```cpp
|
||||
// In static mesh editor: Physics > Phys Material Override
|
||||
// Or in C++:
|
||||
MeshComp->SetPhysMaterialOverride(PhysicalMaterial);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Constraints (Physics Joints)
|
||||
|
||||
### Physics Constraint Component
|
||||
|
||||
```cpp
|
||||
UPhysicsConstraintComponent* Constraint = CreateDefaultSubobject<UPhysicsConstraintComponent>(TEXT("Constraint"));
|
||||
Constraint->SetConstrainedComponents(ComponentA, NAME_None, ComponentB, NAME_None);
|
||||
|
||||
// Configure constraint
|
||||
Constraint->SetLinearXLimit(ELinearConstraintMotion::LCM_Limited, 100.0f);
|
||||
Constraint->SetLinearYLimit(ELinearConstraintMotion::LCM_Locked, 0.0f);
|
||||
Constraint->SetLinearZLimit(ELinearConstraintMotion::LCM_Free, 0.0f);
|
||||
|
||||
Constraint->SetAngularSwing1Limit(EAngularConstraintMotion::ACM_Limited, 45.0f);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Destruction (Chaos Destruction)
|
||||
|
||||
### Enable Chaos Destruction
|
||||
|
||||
```cpp
|
||||
// Plugin: Enable "Chaos" plugin
|
||||
// Create Geometry Collection asset for destructible objects
|
||||
```
|
||||
|
||||
### Destroy Geometry Collection
|
||||
|
||||
```cpp
|
||||
// Fracture mesh in Chaos editor
|
||||
// In game, apply damage:
|
||||
UGeometryCollectionComponent* GeoComp = /* Get component */;
|
||||
GeoComp->ApplyPhysicsField(/* Field parameters */);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
### Physics Optimization
|
||||
|
||||
```cpp
|
||||
// Simplify collision shapes (use simple primitives)
|
||||
MeshComp->SetCollisionEnabled(ECollisionEnabled::NoCollision); // Disable when not needed
|
||||
|
||||
// Use Physics Asset for skeletal meshes (simplified collision)
|
||||
// Don't simulate physics for distant objects
|
||||
|
||||
// Reduce physics substeps:
|
||||
// Project Settings > Engine > Physics > Max Substep Delta Time
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Physics Debug Visualization
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// show collision - Show collision shapes
|
||||
// p.Chaos.DebugDraw.Enabled 1 - Show Chaos debug
|
||||
// pxvis collision - Visualize collision
|
||||
|
||||
// Draw debug shapes:
|
||||
DrawDebugSphere(GetWorld(), Location, Radius, 12, FColor::Green, false, 2.0f);
|
||||
DrawDebugBox(GetWorld(), Location, Extent, FColor::Red, false, 2.0f);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/physics-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/chaos-physics-overview-in-unreal-engine/
|
||||
297
docs/engine-reference/unreal/modules/rendering.md
Normal file
297
docs/engine-reference/unreal/modules/rendering.md
Normal file
@@ -0,0 +1,297 @@
|
||||
# Unreal Engine 5.7 — Rendering Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** UE 5.7 has Megalights, production-ready Substrate, and Lumen improvements
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
UE 5.7 rendering stack:
|
||||
- **Lumen**: Real-time global illumination (default)
|
||||
- **Nanite**: Virtualized geometry for millions of triangles
|
||||
- **Megalights**: Support for millions of dynamic lights (NEW in 5.5+)
|
||||
- **Substrate**: Production-ready modular material system (NEW in 5.7)
|
||||
|
||||
---
|
||||
|
||||
## Lumen (Global Illumination)
|
||||
|
||||
### Enable Lumen
|
||||
|
||||
```cpp
|
||||
// Project Settings > Engine > Rendering > Dynamic Global Illumination Method = Lumen
|
||||
// Real-time GI, no lightmap baking needed
|
||||
```
|
||||
|
||||
### Lumen Quality Settings
|
||||
|
||||
```ini
|
||||
; DefaultEngine.ini
|
||||
[/Script/Engine.RendererSettings]
|
||||
r.Lumen.DiffuseColorBoost=1.0
|
||||
r.Lumen.ScreenProbeGather.RadianceCache.NumFramesToKeepCached=2
|
||||
```
|
||||
|
||||
### Lumen in C++
|
||||
|
||||
```cpp
|
||||
// Check if Lumen is enabled
|
||||
bool bIsLumenEnabled = IConsoleManager::Get().FindConsoleVariable(TEXT("r.DynamicGlobalIlluminationMethod"))->GetInt() == 1;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nanite (Virtualized Geometry)
|
||||
|
||||
### Enable Nanite on Static Mesh
|
||||
|
||||
1. Static Mesh Editor
|
||||
2. Details > Nanite Settings > Enable Nanite Support
|
||||
3. Save mesh (auto-builds Nanite data)
|
||||
|
||||
### Nanite in C++
|
||||
|
||||
```cpp
|
||||
// Spawn Nanite mesh
|
||||
UStaticMeshComponent* MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
|
||||
MeshComp->SetStaticMesh(NaniteMesh); // Automatically uses Nanite if enabled
|
||||
```
|
||||
|
||||
### Nanite Limitations
|
||||
- No vertex animation (skeletal meshes)
|
||||
- No world position offset (WPO) in materials
|
||||
- Best for static, high-poly geometry
|
||||
|
||||
---
|
||||
|
||||
## Megalights (UE 5.5+)
|
||||
|
||||
### Enable Megalights
|
||||
|
||||
```cpp
|
||||
// Project Settings > Engine > Rendering > Megalights = Enabled
|
||||
// Supports millions of dynamic lights with minimal performance cost
|
||||
```
|
||||
|
||||
### Megalights Usage
|
||||
|
||||
```cpp
|
||||
// Add point lights as usual
|
||||
UPointLightComponent* Light = CreateDefaultSubobject<UPointLightComponent>(TEXT("Light"));
|
||||
Light->SetIntensity(5000.0f);
|
||||
Light->SetAttenuationRadius(500.0f);
|
||||
|
||||
// Megalights automatically handles thousands/millions of these
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Substrate Materials (Production-Ready in 5.7)
|
||||
|
||||
### Enable Substrate
|
||||
|
||||
```cpp
|
||||
// Project Settings > Engine > Substrate > Enable Substrate
|
||||
// Restart editor
|
||||
```
|
||||
|
||||
### Substrate Material Nodes
|
||||
- **Substrate Slab**: Physical material layer (diffuse, specular, etc.)
|
||||
- **Substrate Blend**: Blend multiple layers
|
||||
- **Substrate Thin Film**: Iridescence, soap bubbles
|
||||
- **Substrate Hair**: Hair-specific shading
|
||||
|
||||
### Example Substrate Material Graph
|
||||
|
||||
```
|
||||
Substrate Slab (Diffuse)
|
||||
└─ Base Color: Texture Sample
|
||||
└─ Roughness: Constant (0.5)
|
||||
└─ Metallic: Constant (0.0)
|
||||
└─ Connect to Material Output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Materials (C++ API)
|
||||
|
||||
### Dynamic Material Instances
|
||||
|
||||
```cpp
|
||||
// Create dynamic material instance
|
||||
UMaterialInstanceDynamic* DynMat = UMaterialInstanceDynamic::Create(BaseMaterial, this);
|
||||
|
||||
// Set parameters
|
||||
DynMat->SetVectorParameterValue(TEXT("BaseColor"), FLinearColor::Red);
|
||||
DynMat->SetScalarParameterValue(TEXT("Metallic"), 0.8f);
|
||||
DynMat->SetTextureParameterValue(TEXT("DiffuseTexture"), MyTexture);
|
||||
|
||||
// Apply to mesh
|
||||
MeshComp->SetMaterial(0, DynMat);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Post-Processing
|
||||
|
||||
### Post-Process Volume
|
||||
|
||||
```cpp
|
||||
// Add to level
|
||||
APostProcessVolume* PPV = GetWorld()->SpawnActor<APostProcessVolume>();
|
||||
PPV->bUnbound = true; // Affect entire world
|
||||
|
||||
// Configure settings
|
||||
PPV->Settings.bOverride_MotionBlurAmount = true;
|
||||
PPV->Settings.MotionBlurAmount = 0.5f;
|
||||
|
||||
PPV->Settings.bOverride_BloomIntensity = true;
|
||||
PPV->Settings.BloomIntensity = 1.0f;
|
||||
```
|
||||
|
||||
### Post-Process in C++
|
||||
|
||||
```cpp
|
||||
// Access camera post-process settings
|
||||
APlayerController* PC = GetWorld()->GetFirstPlayerController();
|
||||
if (APlayerCameraManager* CamManager = PC->PlayerCameraManager) {
|
||||
CamManager->PostProcessBlendWeight = 1.0f;
|
||||
CamManager->PostProcessSettings.BloomIntensity = 2.0f;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Lighting
|
||||
|
||||
### Directional Light (Sun)
|
||||
|
||||
```cpp
|
||||
ADirectionalLight* Sun = GetWorld()->SpawnActor<ADirectionalLight>();
|
||||
Sun->SetActorRotation(FRotator(-45.f, 0.f, 0.f));
|
||||
Sun->GetLightComponent()->SetIntensity(10.0f);
|
||||
Sun->GetLightComponent()->bCastShadows = true;
|
||||
```
|
||||
|
||||
### Point Light
|
||||
|
||||
```cpp
|
||||
APointLight* Light = GetWorld()->SpawnActor<APointLight>();
|
||||
Light->SetActorLocation(FVector(0, 0, 200));
|
||||
Light->GetPointLightComponent()->SetIntensity(5000.0f);
|
||||
Light->GetPointLightComponent()->SetAttenuationRadius(1000.0f);
|
||||
Light->GetPointLightComponent()->SetLightColor(FLinearColor::Red);
|
||||
```
|
||||
|
||||
### Spot Light
|
||||
|
||||
```cpp
|
||||
ASpotLight* Spotlight = GetWorld()->SpawnActor<ASpotLight>();
|
||||
Spotlight->GetSpotLightComponent()->SetInnerConeAngle(20.0f);
|
||||
Spotlight->GetSpotLightComponent()->SetOuterConeAngle(40.0f);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Render Targets (Render to Texture)
|
||||
|
||||
### Create Render Target
|
||||
|
||||
```cpp
|
||||
// Create render target asset (2D texture)
|
||||
UTextureRenderTarget2D* RenderTarget = NewObject<UTextureRenderTarget2D>();
|
||||
RenderTarget->InitAutoFormat(512, 512); // 512x512 resolution
|
||||
RenderTarget->UpdateResourceImmediate();
|
||||
|
||||
// Render scene to texture
|
||||
UKismetRenderingLibrary::DrawMaterialToRenderTarget(
|
||||
GetWorld(),
|
||||
RenderTarget,
|
||||
MaterialToDraw
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Custom Render Passes (Advanced)
|
||||
|
||||
### Render Dependency Graph (RDG)
|
||||
|
||||
```cpp
|
||||
// UE5 uses Render Dependency Graph for custom rendering
|
||||
// Example: Custom post-process pass
|
||||
|
||||
#include "RenderGraphBuilder.h"
|
||||
|
||||
void RenderCustomPass(FRDGBuilder& GraphBuilder, const FViewInfo& View) {
|
||||
FRDGTextureRef SceneColor = /* Get scene color texture */;
|
||||
|
||||
// Define pass parameters
|
||||
struct FPassParameters {
|
||||
FRDGTextureRef InputTexture;
|
||||
};
|
||||
|
||||
FPassParameters* PassParams = GraphBuilder.AllocParameters<FPassParameters>();
|
||||
PassParams->InputTexture = SceneColor;
|
||||
|
||||
// Add render pass
|
||||
GraphBuilder.AddPass(
|
||||
RDG_EVENT_NAME("CustomPass"),
|
||||
PassParams,
|
||||
ERDGPassFlags::Raster,
|
||||
[](FRHICommandList& RHICmdList, const FPassParameters* Params) {
|
||||
// Render commands
|
||||
}
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance
|
||||
|
||||
### Render Stats
|
||||
|
||||
```cpp
|
||||
// Console commands for profiling:
|
||||
// stat fps - Show FPS
|
||||
// stat unit - Show frame time breakdown
|
||||
// stat gpu - Show GPU timings
|
||||
// profilegpu - Detailed GPU profile
|
||||
```
|
||||
|
||||
### Scalability Settings
|
||||
|
||||
```cpp
|
||||
// Get current scalability settings
|
||||
UGameUserSettings* Settings = UGameUserSettings::GetGameUserSettings();
|
||||
int32 ViewDistanceQuality = Settings->GetViewDistanceQuality(); // 0-4
|
||||
|
||||
// Set scalability
|
||||
Settings->SetViewDistanceQuality(3); // High
|
||||
Settings->SetShadowQuality(2); // Medium
|
||||
Settings->ApplySettings(false);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Visualize Render Features
|
||||
|
||||
```
|
||||
Console commands:
|
||||
- r.Lumen.Visualize 1 - Show Lumen debug
|
||||
- r.Nanite.Visualize 1 - Show Nanite triangles
|
||||
- viewmode wireframe - Wireframe mode
|
||||
- viewmode unlit - Disable lighting
|
||||
- show collision - Show collision meshes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/lumen-global-illumination-and-reflections-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/nanite-virtualized-geometry-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/substrate-materials-in-unreal-engine/
|
||||
353
docs/engine-reference/unreal/modules/ui.md
Normal file
353
docs/engine-reference/unreal/modules/ui.md
Normal file
@@ -0,0 +1,353 @@
|
||||
# Unreal Engine 5.7 — UI Module Reference
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Knowledge Gap:** UE 5.7 UMG and CommonUI improvements
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
UE 5.7 UI systems:
|
||||
- **UMG (Unreal Motion Graphics)**: Visual widget-based UI (RECOMMENDED)
|
||||
- **CommonUI**: Cross-platform input-aware UI framework (console/PC)
|
||||
- **Slate**: Low-level C++ UI (engine/editor UI)
|
||||
|
||||
---
|
||||
|
||||
## UMG (Unreal Motion Graphics)
|
||||
|
||||
### Create Widget Blueprint
|
||||
|
||||
1. Content Browser > User Interface > Widget Blueprint
|
||||
2. Open Widget Designer
|
||||
3. Drag widgets from Palette: Button, Text, Image, ProgressBar, etc.
|
||||
|
||||
---
|
||||
|
||||
## Basic UMG Setup in C++
|
||||
|
||||
### Create and Display Widget
|
||||
|
||||
```cpp
|
||||
#include "Blueprint/UserWidget.h"
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "UI")
|
||||
TSubclassOf<UUserWidget> HealthBarWidgetClass;
|
||||
|
||||
void AMyCharacter::BeginPlay() {
|
||||
Super::BeginPlay();
|
||||
|
||||
// Create widget
|
||||
UUserWidget* HealthBarWidget = CreateWidget<UUserWidget>(GetWorld(), HealthBarWidgetClass);
|
||||
|
||||
// Add to viewport
|
||||
HealthBarWidget->AddToViewport();
|
||||
}
|
||||
```
|
||||
|
||||
### Remove Widget
|
||||
|
||||
```cpp
|
||||
HealthBarWidget->RemoveFromParent();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Access Widget Elements from C++
|
||||
|
||||
### Bind to Widget Elements
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class UMyHealthWidget : public UUserWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// ✅ Bind to widget elements (must match names in Widget Blueprint)
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UTextBlock> HealthText;
|
||||
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UProgressBar> HealthBar;
|
||||
|
||||
void UpdateHealth(int32 CurrentHealth, int32 MaxHealth) {
|
||||
HealthText->SetText(FText::FromString(FString::Printf(TEXT("%d / %d"), CurrentHealth, MaxHealth)));
|
||||
HealthBar->SetPercent((float)CurrentHealth / MaxHealth);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common UMG Widgets
|
||||
|
||||
### Text Block
|
||||
|
||||
```cpp
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UTextBlock> ScoreText;
|
||||
|
||||
ScoreText->SetText(FText::FromString(TEXT("Score: 100")));
|
||||
ScoreText->SetColorAndOpacity(FLinearColor::Green);
|
||||
```
|
||||
|
||||
### Button
|
||||
|
||||
```cpp
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UButton> PlayButton;
|
||||
|
||||
void NativeConstruct() override {
|
||||
Super::NativeConstruct();
|
||||
|
||||
// Bind button click
|
||||
PlayButton->OnClicked.AddDynamic(this, &UMyMenuWidget::OnPlayClicked);
|
||||
}
|
||||
|
||||
UFUNCTION()
|
||||
void OnPlayClicked() {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Play clicked"));
|
||||
}
|
||||
```
|
||||
|
||||
### Image
|
||||
|
||||
```cpp
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UImage> PlayerAvatar;
|
||||
|
||||
PlayerAvatar->SetBrushFromTexture(AvatarTexture);
|
||||
PlayerAvatar->SetColorAndOpacity(FLinearColor::White);
|
||||
```
|
||||
|
||||
### Progress Bar
|
||||
|
||||
```cpp
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UProgressBar> HealthBar;
|
||||
|
||||
HealthBar->SetPercent(0.75f); // 75%
|
||||
HealthBar->SetFillColorAndOpacity(FLinearColor::Red);
|
||||
```
|
||||
|
||||
### Slider
|
||||
|
||||
```cpp
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<USlider> VolumeSlider;
|
||||
|
||||
void NativeConstruct() override {
|
||||
Super::NativeConstruct();
|
||||
VolumeSlider->OnValueChanged.AddDynamic(this, &UMyWidget::OnVolumeChanged);
|
||||
}
|
||||
|
||||
UFUNCTION()
|
||||
void OnVolumeChanged(float Value) {
|
||||
// Value is 0.0 - 1.0
|
||||
UE_LOG(LogTemp, Warning, TEXT("Volume: %f"), Value);
|
||||
}
|
||||
```
|
||||
|
||||
### EditableTextBox (Input Field)
|
||||
|
||||
```cpp
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UEditableTextBox> PlayerNameInput;
|
||||
|
||||
void NativeConstruct() override {
|
||||
Super::NativeConstruct();
|
||||
PlayerNameInput->OnTextChanged.AddDynamic(this, &UMyWidget::OnNameChanged);
|
||||
}
|
||||
|
||||
UFUNCTION()
|
||||
void OnNameChanged(const FText& Text) {
|
||||
FString PlayerName = Text.ToString();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## UMG Animations
|
||||
|
||||
### Play Animation
|
||||
|
||||
```cpp
|
||||
UPROPERTY(Transient, meta = (BindWidgetAnim))
|
||||
TObjectPtr<UWidgetAnimation> FadeInAnimation;
|
||||
|
||||
void ShowUI() {
|
||||
PlayAnimation(FadeInAnimation);
|
||||
}
|
||||
```
|
||||
|
||||
### Stop Animation
|
||||
|
||||
```cpp
|
||||
StopAnimation(FadeInAnimation);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Canvas Panel (Layout)
|
||||
|
||||
### Canvas Panel (Absolute Positioning)
|
||||
|
||||
```cpp
|
||||
// Use in Widget Blueprint for absolute positioning
|
||||
// Anchor widgets to corners/edges for responsive UI
|
||||
```
|
||||
|
||||
### Vertical Box (Stack Vertically)
|
||||
|
||||
```cpp
|
||||
// Auto-stacks children vertically
|
||||
```
|
||||
|
||||
### Horizontal Box (Stack Horizontally)
|
||||
|
||||
```cpp
|
||||
// Auto-stacks children horizontally
|
||||
```
|
||||
|
||||
### Grid Panel (Grid Layout)
|
||||
|
||||
```cpp
|
||||
// Arranges children in a grid
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## World Space UI (3D UI)
|
||||
|
||||
### Widget Component (3D UI in World)
|
||||
|
||||
```cpp
|
||||
#include "Components/WidgetComponent.h"
|
||||
|
||||
UWidgetComponent* HealthBarWidget = CreateDefaultSubobject<UWidgetComponent>(TEXT("HealthBar"));
|
||||
HealthBarWidget->SetupAttachment(RootComponent);
|
||||
HealthBarWidget->SetWidgetClass(HealthBarWidgetClass);
|
||||
HealthBarWidget->SetWidgetSpace(EWidgetSpace::World); // 3D world space
|
||||
HealthBarWidget->SetDrawSize(FVector2D(200, 50));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input Handling in UMG
|
||||
|
||||
### Override Keyboard Input
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class UMyWidget : public UUserWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual FReply NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) override {
|
||||
if (InKeyEvent.GetKey() == EKeys::Escape) {
|
||||
// Handle Escape key
|
||||
CloseMenu();
|
||||
return FReply::Handled();
|
||||
}
|
||||
return Super::NativeOnKeyDown(InGeometry, InKeyEvent);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CommonUI (Cross-Platform Input)
|
||||
|
||||
### Enable CommonUI Plugin
|
||||
|
||||
```cpp
|
||||
// Enable: Edit > Plugins > CommonUI
|
||||
// Restart editor
|
||||
```
|
||||
|
||||
### Use CommonUI Widgets
|
||||
|
||||
```cpp
|
||||
// CommonUI widgets:
|
||||
// - CommonActivatableWidget: Base for screens/menus
|
||||
// - CommonButtonBase: Input-aware button (gamepad + mouse)
|
||||
// - CommonTextBlock: Text with styling
|
||||
```
|
||||
|
||||
### CommonActivatableWidget Example
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class UMyMenuWidget : public UCommonActivatableWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual void NativeOnActivated() override {
|
||||
Super::NativeOnActivated();
|
||||
// Menu activated (shown)
|
||||
}
|
||||
|
||||
virtual void NativeOnDeactivated() override {
|
||||
Super::NativeOnDeactivated();
|
||||
// Menu deactivated (hidden)
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## HUD Class (Alternative to UMG)
|
||||
|
||||
### Create HUD
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class AMyHUD : public AHUD {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual void DrawHUD() override {
|
||||
Super::DrawHUD();
|
||||
|
||||
// Draw text
|
||||
DrawText(TEXT("Score: 100"), FLinearColor::White, 50, 50);
|
||||
|
||||
// Draw texture
|
||||
DrawTexture(CrosshairTexture, Canvas->SizeX / 2, Canvas->SizeY / 2, 32, 32);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
### Optimize UMG
|
||||
|
||||
```cpp
|
||||
// Invalidation boxes: Only redraw when content changes
|
||||
// Add "Invalidation Box" widget to Widget Blueprint
|
||||
|
||||
// Disable tick if not needed
|
||||
bIsFocusable = false;
|
||||
SetVisibility(ESlateVisibility::Collapsed); // Collapsed = not rendered
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### UI Debug Commands
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// widget.debug - Show widget hierarchy
|
||||
// Slate.ShowDebugOutlines 1 - Show widget bounds
|
||||
// stat slate - Show Slate performance
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/umg-ui-designer-for-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/commonui-plugin-for-advanced-user-interfaces-in-unreal-engine/
|
||||
389
docs/engine-reference/unreal/plugins/common-ui.md
Normal file
389
docs/engine-reference/unreal/plugins/common-ui.md
Normal file
@@ -0,0 +1,389 @@
|
||||
# Unreal Engine 5.7 — CommonUI Plugin
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Status:** Production-Ready
|
||||
**Plugin:** `CommonUI` (built-in, enable in Plugins)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**CommonUI** is a cross-platform UI framework that automatically handles input routing
|
||||
for gamepad, mouse, and touch. It's designed for games that need to work seamlessly
|
||||
across PC, console, and mobile platforms with minimal platform-specific code.
|
||||
|
||||
**Use CommonUI for:**
|
||||
- Multi-platform games (console + PC)
|
||||
- Automatic gamepad/mouse/touch input routing
|
||||
- Input-agnostic UI (same UI works with any input method)
|
||||
- Widget focus and navigation
|
||||
- Action bars and input hints
|
||||
|
||||
**DON'T use CommonUI for:**
|
||||
- PC-only games with mouse-only UI (standard UMG is simpler)
|
||||
- Simple UI with no navigation requirements
|
||||
|
||||
---
|
||||
|
||||
## Key Differences from Standard UMG
|
||||
|
||||
| Feature | Standard UMG | CommonUI |
|
||||
|---------|--------------|----------|
|
||||
| **Input Handling** | Manual per widget | Automatic routing |
|
||||
| **Focus Management** | Basic | Advanced navigation |
|
||||
| **Platform Switching** | Manual detection | Automatic |
|
||||
| **Input Prompts** | Hardcode icons | Dynamic per platform |
|
||||
| **Screen Stack** | Manual | Built-in activatable widgets |
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Enable Plugin
|
||||
|
||||
`Edit > Plugins > CommonUI > Enabled > Restart`
|
||||
|
||||
### 2. Configure Project Settings
|
||||
|
||||
`Project Settings > Plugins > CommonUI`:
|
||||
- **Default Input Type**: Gamepad (or auto-detect)
|
||||
- **Platform-Specific Settings**: Configure input icons per platform
|
||||
|
||||
### 3. Create Common Input Settings Asset
|
||||
|
||||
1. Content Browser > Input > Common Input Settings
|
||||
2. Configure input data per platform:
|
||||
- Default Gamepad Data
|
||||
- Default Mouse & Keyboard Data
|
||||
- Default Touch Data
|
||||
|
||||
---
|
||||
|
||||
## Core Widgets
|
||||
|
||||
### CommonActivatableWidget (Screen Management)
|
||||
|
||||
Base class for screens/menus that can be activated/deactivated.
|
||||
|
||||
```cpp
|
||||
#include "CommonActivatableWidget.h"
|
||||
|
||||
UCLASS()
|
||||
class UMyMenuWidget : public UCommonActivatableWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
virtual void NativeOnActivated() override {
|
||||
Super::NativeOnActivated();
|
||||
// Menu is now visible and focused
|
||||
UE_LOG(LogTemp, Warning, TEXT("Menu activated"));
|
||||
}
|
||||
|
||||
virtual void NativeOnDeactivated() override {
|
||||
Super::NativeOnDeactivated();
|
||||
// Menu is now hidden
|
||||
UE_LOG(LogTemp, Warning, TEXT("Menu deactivated"));
|
||||
}
|
||||
|
||||
virtual UWidget* NativeGetDesiredFocusTarget() const override {
|
||||
// Return widget that should receive focus (e.g., first button)
|
||||
return PlayButton;
|
||||
}
|
||||
|
||||
private:
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonButtonBase> PlayButton;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### CommonButtonBase (Input-Aware Button)
|
||||
|
||||
Replaces standard UMG Button. Automatically handles gamepad/mouse/keyboard input.
|
||||
|
||||
```cpp
|
||||
#include "CommonButtonBase.h"
|
||||
|
||||
UCLASS()
|
||||
class UMyMenuWidget : public UCommonActivatableWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonButtonBase> PlayButton;
|
||||
|
||||
virtual void NativeConstruct() override {
|
||||
Super::NativeConstruct();
|
||||
|
||||
// Bind button click (works with any input method)
|
||||
PlayButton->OnClicked().AddUObject(this, &UMyMenuWidget::OnPlayClicked);
|
||||
|
||||
// Set button text
|
||||
PlayButton->SetButtonText(FText::FromString(TEXT("Play")));
|
||||
}
|
||||
|
||||
void OnPlayClicked() {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Play clicked"));
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### CommonTextBlock (Styled Text)
|
||||
|
||||
Text widget with CommonUI styling support.
|
||||
|
||||
```cpp
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonTextBlock> TitleText;
|
||||
|
||||
TitleText->SetText(FText::FromString(TEXT("Main Menu")));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### CommonActionWidget (Input Prompts)
|
||||
|
||||
Displays input prompts (e.g., "Press A to Continue", automatically shows correct button icon).
|
||||
|
||||
```cpp
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonActionWidget> ConfirmActionWidget;
|
||||
|
||||
// Bind to input action
|
||||
ConfirmActionWidget->SetInputAction(ConfirmInputActionData);
|
||||
// Automatically shows correct icon (A on Xbox, X on PlayStation, Enter on PC)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Widget Stack (Screen Management)
|
||||
|
||||
### CommonActivatableWidgetStack
|
||||
|
||||
Manages a stack of screens (e.g., Main Menu → Settings → Controls).
|
||||
|
||||
```cpp
|
||||
#include "Widgets/CommonActivatableWidgetContainer.h"
|
||||
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonActivatableWidgetStack> WidgetStack;
|
||||
|
||||
// Push new screen onto stack
|
||||
void ShowSettingsMenu() {
|
||||
WidgetStack->AddWidget(USettingsMenuWidget::StaticClass());
|
||||
}
|
||||
|
||||
// Pop current screen (go back)
|
||||
void GoBack() {
|
||||
WidgetStack->DeactivateWidget();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input Actions (CommonUI Style)
|
||||
|
||||
### Define Input Actions
|
||||
|
||||
Create **Common Input Action Data Table**:
|
||||
1. Content Browser > Miscellaneous > Data Table
|
||||
2. Row Structure: `CommonInputActionDataBase`
|
||||
3. Add rows for actions (Confirm, Cancel, Navigate, etc.)
|
||||
|
||||
Example row:
|
||||
- **Action Name**: Confirm
|
||||
- **Default Input**: Gamepad Face Button Bottom (A/Cross)
|
||||
- **Alternate Inputs**: Enter (keyboard), Left Mouse Button
|
||||
|
||||
---
|
||||
|
||||
### Bind Input Actions in Widget
|
||||
|
||||
```cpp
|
||||
#include "Input/CommonUIActionRouterBase.h"
|
||||
|
||||
UCLASS()
|
||||
class UMyWidget : public UCommonActivatableWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
virtual void NativeOnActivated() override {
|
||||
Super::NativeOnActivated();
|
||||
|
||||
// Bind input action
|
||||
FBindUIActionArgs BindArgs(ConfirmInputAction, FSimpleDelegate::CreateUObject(this, &UMyWidget::OnConfirm));
|
||||
BindArgs.bDisplayInActionBar = true; // Show in action bar
|
||||
RegisterUIActionBinding(BindArgs);
|
||||
}
|
||||
|
||||
void OnConfirm() {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Confirmed"));
|
||||
}
|
||||
|
||||
private:
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||
FDataTableRowHandle ConfirmInputAction;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Focus & Navigation
|
||||
|
||||
### Automatic Gamepad Navigation
|
||||
|
||||
CommonUI automatically handles gamepad navigation (D-Pad/Stick to move between buttons).
|
||||
|
||||
```cpp
|
||||
// In Widget Blueprint:
|
||||
// - Widgets are automatically navigable if they inherit from CommonButton/CommonUserWidget
|
||||
// - Focus order is determined by widget hierarchy and layout
|
||||
```
|
||||
|
||||
### Custom Focus Navigation
|
||||
|
||||
```cpp
|
||||
// Override focus navigation
|
||||
virtual UWidget* NativeGetDesiredFocusTarget() const override {
|
||||
return FirstButton; // Return widget that should receive focus
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input Mode (Game vs UI)
|
||||
|
||||
### Switch Input Mode
|
||||
|
||||
```cpp
|
||||
#include "CommonUIExtensions.h"
|
||||
|
||||
// Switch to UI-only mode (pause game, show cursor)
|
||||
UCommonUIExtensions::PushStreamedGameplayUIInputConfig(this, FrontendInputConfig);
|
||||
|
||||
// Return to game mode (hide cursor, resume gameplay)
|
||||
UCommonUIExtensions::PopInputConfig(this);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Platform-Specific Input Icons
|
||||
|
||||
### Configure Input Icons
|
||||
|
||||
1. Create **Common Input Base Controller Data** asset for each platform:
|
||||
- Gamepad (Xbox, PlayStation, Switch)
|
||||
- Mouse & Keyboard
|
||||
- Touch
|
||||
|
||||
2. Assign platform-specific icons:
|
||||
- Gamepad Face Button Bottom: `A` (Xbox), `Cross` (PlayStation)
|
||||
- Confirm Key: `Enter` icon
|
||||
|
||||
3. Assign to **Common Input Settings** asset
|
||||
|
||||
### Automatically Display Correct Icons
|
||||
|
||||
```cpp
|
||||
// CommonActionWidget automatically shows correct icon for current platform
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonActionWidget> JumpActionWidget;
|
||||
|
||||
JumpActionWidget->SetInputAction(JumpInputActionData);
|
||||
// Shows "A" on Xbox, "Cross" on PlayStation, "Space" on PC
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Main Menu with Navigation
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class UMainMenuWidget : public UCommonActivatableWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonButtonBase> PlayButton;
|
||||
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonButtonBase> SettingsButton;
|
||||
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonButtonBase> QuitButton;
|
||||
|
||||
virtual void NativeConstruct() override {
|
||||
Super::NativeConstruct();
|
||||
|
||||
PlayButton->OnClicked().AddUObject(this, &UMainMenuWidget::OnPlayClicked);
|
||||
SettingsButton->OnClicked().AddUObject(this, &UMainMenuWidget::OnSettingsClicked);
|
||||
QuitButton->OnClicked().AddUObject(this, &UMainMenuWidget::OnQuitClicked);
|
||||
}
|
||||
|
||||
virtual UWidget* NativeGetDesiredFocusTarget() const override {
|
||||
return PlayButton; // Focus "Play" button when menu opens
|
||||
}
|
||||
|
||||
void OnPlayClicked() { /* Start game */ }
|
||||
void OnSettingsClicked() { /* Open settings */ }
|
||||
void OnQuitClicked() { /* Quit game */ }
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Pause Menu with Back Action
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class UPauseMenuWidget : public UCommonActivatableWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||
FDataTableRowHandle BackInputAction; // Assign "Cancel" action in Blueprint
|
||||
|
||||
virtual void NativeOnActivated() override {
|
||||
Super::NativeOnActivated();
|
||||
|
||||
// Bind "Back" input (B/Circle/Escape)
|
||||
FBindUIActionArgs BindArgs(BackInputAction, FSimpleDelegate::CreateUObject(this, &UPauseMenuWidget::OnBack));
|
||||
RegisterUIActionBinding(BindArgs);
|
||||
}
|
||||
|
||||
void OnBack() {
|
||||
DeactivateWidget(); // Close pause menu
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
- Use **CommonActivatableWidgetStack** for screen management (automatically handles activation/deactivation)
|
||||
- Avoid creating/destroying widgets every frame (reuse widgets)
|
||||
- Use **Lazy Widgets** for complex menus (only create when needed)
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### CommonUI Debug Commands
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// CommonUI.DumpActivatableTree - Show active widget hierarchy
|
||||
// CommonUI.DumpActionBindings - Show registered input actions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/commonui-plugin-for-advanced-user-interfaces-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/commonui-quickstart-guide-for-unreal-engine/
|
||||
386
docs/engine-reference/unreal/plugins/gameplay-ability-system.md
Normal file
386
docs/engine-reference/unreal/plugins/gameplay-ability-system.md
Normal file
@@ -0,0 +1,386 @@
|
||||
# Unreal Engine 5.7 — Gameplay Ability System (GAS)
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Status:** Production-Ready
|
||||
**Plugin:** `GameplayAbilities` (built-in, enable in Plugins)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Gameplay Ability System (GAS)** is a modular framework for building abilities, attributes,
|
||||
effects, and gameplay mechanics. It's the standard for RPGs, MOBAs, shooters with abilities,
|
||||
and any game with complex ability systems.
|
||||
|
||||
**Use GAS for:**
|
||||
- Character abilities (spells, skills, attacks)
|
||||
- Attributes (health, mana, stamina, stats)
|
||||
- Buffs/debuffs (temporary effects)
|
||||
- Cooldowns and costs
|
||||
- Damage calculation
|
||||
- Multiplayer-ready ability replication
|
||||
|
||||
---
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### 1. **Ability System Component** (ASC)
|
||||
- The main component that owns abilities, attributes, and effects
|
||||
- Added to Characters or PlayerStates
|
||||
|
||||
### 2. **Gameplay Abilities**
|
||||
- Individual skills/actions (fireball, heal, dash, etc.)
|
||||
- Activated, committed (cost/cooldown), and can be cancelled
|
||||
|
||||
### 3. **Attributes & Attribute Sets**
|
||||
- Stats that can be modified (Health, Mana, Stamina, Strength, etc.)
|
||||
- Stored in Attribute Sets
|
||||
|
||||
### 4. **Gameplay Effects**
|
||||
- Modify attributes (damage, healing, buffs, debuffs)
|
||||
- Can be instant, duration-based, or infinite
|
||||
|
||||
### 5. **Gameplay Tags**
|
||||
- Hierarchical tags for ability logic (e.g., `Ability.Attack.Melee`, `Status.Stunned`)
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Enable Plugin
|
||||
|
||||
`Edit > Plugins > Gameplay Abilities > Enabled > Restart`
|
||||
|
||||
### 2. Add Ability System Component
|
||||
|
||||
```cpp
|
||||
#include "AbilitySystemComponent.h"
|
||||
#include "AttributeSet.h"
|
||||
|
||||
UCLASS()
|
||||
class AMyCharacter : public ACharacter {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AMyCharacter() {
|
||||
// Create ASC
|
||||
AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystem"));
|
||||
AbilitySystemComponent->SetIsReplicated(true);
|
||||
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);
|
||||
|
||||
// Create Attribute Set
|
||||
AttributeSet = CreateDefaultSubobject<UMyAttributeSet>(TEXT("AttributeSet"));
|
||||
}
|
||||
|
||||
protected:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Abilities")
|
||||
TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<const UAttributeSet> AttributeSet;
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Initialize ASC (Important for Multiplayer)
|
||||
|
||||
```cpp
|
||||
void AMyCharacter::PossessedBy(AController* NewController) {
|
||||
Super::PossessedBy(NewController);
|
||||
|
||||
// Server: Initialize ASC
|
||||
if (AbilitySystemComponent) {
|
||||
AbilitySystemComponent->InitAbilityActorInfo(this, this);
|
||||
GiveDefaultAbilities();
|
||||
}
|
||||
}
|
||||
|
||||
void AMyCharacter::OnRep_PlayerState() {
|
||||
Super::OnRep_PlayerState();
|
||||
|
||||
// Client: Initialize ASC
|
||||
if (AbilitySystemComponent) {
|
||||
AbilitySystemComponent->InitAbilityActorInfo(this, this);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Attributes & Attribute Sets
|
||||
|
||||
### Create Attribute Set
|
||||
|
||||
```cpp
|
||||
#include "AttributeSet.h"
|
||||
#include "AbilitySystemComponent.h"
|
||||
|
||||
UCLASS()
|
||||
class UMyAttributeSet : public UAttributeSet {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UMyAttributeSet();
|
||||
|
||||
// Health
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Attributes", ReplicatedUsing = OnRep_Health)
|
||||
FGameplayAttributeData Health;
|
||||
ATTRIBUTE_ACCESSORS(UMyAttributeSet, Health)
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Attributes", ReplicatedUsing = OnRep_MaxHealth)
|
||||
FGameplayAttributeData MaxHealth;
|
||||
ATTRIBUTE_ACCESSORS(UMyAttributeSet, MaxHealth)
|
||||
|
||||
// Mana
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Attributes", ReplicatedUsing = OnRep_Mana)
|
||||
FGameplayAttributeData Mana;
|
||||
ATTRIBUTE_ACCESSORS(UMyAttributeSet, Mana)
|
||||
|
||||
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||
|
||||
protected:
|
||||
UFUNCTION()
|
||||
virtual void OnRep_Health(const FGameplayAttributeData& OldHealth);
|
||||
|
||||
UFUNCTION()
|
||||
virtual void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth);
|
||||
|
||||
UFUNCTION()
|
||||
virtual void OnRep_Mana(const FGameplayAttributeData& OldMana);
|
||||
};
|
||||
```
|
||||
|
||||
### Implement Attribute Set
|
||||
|
||||
```cpp
|
||||
#include "Net/UnrealNetwork.h"
|
||||
|
||||
UMyAttributeSet::UMyAttributeSet() {
|
||||
// Default values
|
||||
Health = 100.0f;
|
||||
MaxHealth = 100.0f;
|
||||
Mana = 50.0f;
|
||||
}
|
||||
|
||||
void UMyAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const {
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
|
||||
DOREPLIFETIME_CONDITION_NOTIFY(UMyAttributeSet, Health, COND_None, REPNOTIFY_Always);
|
||||
DOREPLIFETIME_CONDITION_NOTIFY(UMyAttributeSet, MaxHealth, COND_None, REPNOTIFY_Always);
|
||||
DOREPLIFETIME_CONDITION_NOTIFY(UMyAttributeSet, Mana, COND_None, REPNOTIFY_Always);
|
||||
}
|
||||
|
||||
void UMyAttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth) {
|
||||
GAMEPLAYATTRIBUTE_REPNOTIFY(UMyAttributeSet, Health, OldHealth);
|
||||
}
|
||||
|
||||
// Implement other OnRep functions similarly...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Gameplay Abilities
|
||||
|
||||
### Create Gameplay Ability
|
||||
|
||||
```cpp
|
||||
#include "Abilities/GameplayAbility.h"
|
||||
|
||||
UCLASS()
|
||||
class UGA_Fireball : public UGameplayAbility {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGA_Fireball() {
|
||||
// Ability config
|
||||
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
|
||||
NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::ServerInitiated;
|
||||
|
||||
// Tags
|
||||
AbilityTags.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Attack.Fireball")));
|
||||
}
|
||||
|
||||
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
|
||||
const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override {
|
||||
|
||||
if (!CommitAbility(Handle, ActorInfo, ActivationInfo)) {
|
||||
// Failed to commit (not enough mana, on cooldown, etc.)
|
||||
EndAbility(Handle, ActorInfo, ActivationInfo, true, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Spawn fireball projectile
|
||||
SpawnFireball();
|
||||
|
||||
// End ability
|
||||
EndAbility(Handle, ActorInfo, ActivationInfo, true, false);
|
||||
}
|
||||
|
||||
void SpawnFireball() {
|
||||
// Spawn fireball logic
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Grant Abilities to Character
|
||||
|
||||
```cpp
|
||||
void AMyCharacter::GiveDefaultAbilities() {
|
||||
if (!HasAuthority() || !AbilitySystemComponent) return;
|
||||
|
||||
// Grant abilities
|
||||
AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(UGA_Fireball::StaticClass(), 1, INDEX_NONE, this));
|
||||
AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(UGA_Heal::StaticClass(), 1, INDEX_NONE, this));
|
||||
}
|
||||
```
|
||||
|
||||
### Activate Ability
|
||||
|
||||
```cpp
|
||||
// Activate by class
|
||||
AbilitySystemComponent->TryActivateAbilityByClass(UGA_Fireball::StaticClass());
|
||||
|
||||
// Activate by tag
|
||||
FGameplayTagContainer TagContainer;
|
||||
TagContainer.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Attack.Fireball")));
|
||||
AbilitySystemComponent->TryActivateAbilitiesByTag(TagContainer);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Gameplay Effects
|
||||
|
||||
### Create Gameplay Effect (Damage)
|
||||
|
||||
```cpp
|
||||
// Create Blueprint: Content Browser > Gameplay > Gameplay Effect
|
||||
|
||||
// OR in C++:
|
||||
UCLASS()
|
||||
class UGE_Damage : public UGameplayEffect {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGE_Damage() {
|
||||
// Instant damage
|
||||
DurationPolicy = EGameplayEffectDurationType::Instant;
|
||||
|
||||
// Modifier: Reduce Health
|
||||
FGameplayModifierInfo ModifierInfo;
|
||||
ModifierInfo.Attribute = UMyAttributeSet::GetHealthAttribute();
|
||||
ModifierInfo.ModifierOp = EGameplayModOp::Additive;
|
||||
ModifierInfo.ModifierMagnitude = FScalableFloat(-25.0f); // -25 health
|
||||
|
||||
Modifiers.Add(ModifierInfo);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Apply Gameplay Effect
|
||||
|
||||
```cpp
|
||||
// Apply damage to target
|
||||
if (UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Target)) {
|
||||
FGameplayEffectContextHandle EffectContext = AbilitySystemComponent->MakeEffectContext();
|
||||
EffectContext.AddSourceObject(this);
|
||||
|
||||
FGameplayEffectSpecHandle SpecHandle = AbilitySystemComponent->MakeOutgoingSpec(
|
||||
UGE_Damage::StaticClass(), 1, EffectContext);
|
||||
|
||||
if (SpecHandle.IsValid()) {
|
||||
AbilitySystemComponent->ApplyGameplayEffectSpecToTarget(*SpecHandle.Data.Get(), TargetASC);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Gameplay Tags
|
||||
|
||||
### Define Tags
|
||||
|
||||
`Project Settings > Project > Gameplay Tags > Gameplay Tag List`
|
||||
|
||||
Example hierarchy:
|
||||
```
|
||||
Ability
|
||||
├─ Ability.Attack
|
||||
│ ├─ Ability.Attack.Melee
|
||||
│ └─ Ability.Attack.Ranged
|
||||
├─ Ability.Defend
|
||||
└─ Ability.Utility
|
||||
|
||||
Status
|
||||
├─ Status.Stunned
|
||||
├─ Status.Invulnerable
|
||||
└─ Status.Silenced
|
||||
```
|
||||
|
||||
### Use Tags in Abilities
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class UGA_MeleeAttack : public UGameplayAbility {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGA_MeleeAttack() {
|
||||
// This ability has these tags
|
||||
AbilityTags.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Attack.Melee")));
|
||||
|
||||
// Block these tags while active
|
||||
BlockAbilitiesWithTag.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Attack")));
|
||||
|
||||
// Cancel these abilities when activated
|
||||
CancelAbilitiesWithTag.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Defend")));
|
||||
|
||||
// Can't activate if target has these tags
|
||||
ActivationBlockedTags.AddTag(FGameplayTag::RequestGameplayTag(FName("Status.Stunned")));
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cooldowns & Costs
|
||||
|
||||
### Add Cooldown
|
||||
|
||||
```cpp
|
||||
// In Ability Blueprint or C++:
|
||||
// Create Gameplay Effect with Duration = Cooldown time
|
||||
// Assign to Ability > Cooldown Gameplay Effect Class
|
||||
```
|
||||
|
||||
### Add Cost (Mana)
|
||||
|
||||
```cpp
|
||||
// Create Gameplay Effect that reduces Mana
|
||||
// Assign to Ability > Cost Gameplay Effect Class
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Get Current Attribute Value
|
||||
|
||||
```cpp
|
||||
float CurrentHealth = AbilitySystemComponent->GetNumericAttribute(UMyAttributeSet::GetHealthAttribute());
|
||||
```
|
||||
|
||||
### Listen for Attribute Changes
|
||||
|
||||
```cpp
|
||||
AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(UMyAttributeSet::GetHealthAttribute())
|
||||
.AddUObject(this, &AMyCharacter::OnHealthChanged);
|
||||
|
||||
void AMyCharacter::OnHealthChanged(const FOnAttributeChangeData& Data) {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Health: %f"), Data.NewValue);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/gameplay-ability-system-for-unreal-engine/
|
||||
- https://github.com/tranek/GASDocumentation (community guide)
|
||||
321
docs/engine-reference/unreal/plugins/gameplay-camera-system.md
Normal file
321
docs/engine-reference/unreal/plugins/gameplay-camera-system.md
Normal file
@@ -0,0 +1,321 @@
|
||||
# Unreal Engine 5.7 — Gameplay Camera System
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Status:** ⚠️ Experimental (introduced in UE 5.5)
|
||||
**Plugin:** `GameplayCameras` (built-in, enable in Plugins)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Gameplay Camera System** is a modular camera management framework introduced in UE 5.5.
|
||||
It replaces traditional camera setups with a flexible, node-based system that handles
|
||||
camera modes, blending, and context-aware camera behavior.
|
||||
|
||||
**Use Gameplay Cameras for:**
|
||||
- Dynamic camera behavior (3rd person, aiming, vehicles, cinematic)
|
||||
- Context-aware camera switching (combat, exploration, dialogue)
|
||||
- Smooth camera blending between modes
|
||||
- Procedural camera motion (camera shake, lag, offset)
|
||||
|
||||
**⚠️ Warning:** This plugin is experimental in UE 5.5-5.7. Expect API changes in future versions.
|
||||
|
||||
---
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### 1. **Camera Rig**
|
||||
- Defines camera configuration (position, rotation, FOV, etc.)
|
||||
- Modular node graph (similar to Material Editor)
|
||||
|
||||
### 2. **Camera Director**
|
||||
- Manages which camera rig is active
|
||||
- Handles blending between camera rigs
|
||||
|
||||
### 3. **Camera Nodes**
|
||||
- Building blocks for camera behavior:
|
||||
- **Position Nodes**: Orbit, Follow, Fixed Position
|
||||
- **Rotation Nodes**: Look At, Match Actor Rotation
|
||||
- **Modifiers**: Camera Shake, Lag, Offset
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Enable Plugin
|
||||
|
||||
`Edit > Plugins > Gameplay Cameras > Enabled > Restart`
|
||||
|
||||
### 2. Add Camera Component
|
||||
|
||||
```cpp
|
||||
#include "GameplayCameras/Public/GameplayCameraComponent.h"
|
||||
|
||||
UCLASS()
|
||||
class AMyCharacter : public ACharacter {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AMyCharacter() {
|
||||
// Create camera component
|
||||
CameraComponent = CreateDefaultSubobject<UGameplayCameraComponent>(TEXT("GameplayCamera"));
|
||||
CameraComponent->SetupAttachment(RootComponent);
|
||||
}
|
||||
|
||||
protected:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
|
||||
TObjectPtr<UGameplayCameraComponent> CameraComponent;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Create Camera Rig
|
||||
|
||||
### 1. Create Camera Rig Asset
|
||||
|
||||
1. Content Browser > Gameplay > Gameplay Camera Rig
|
||||
2. Open Camera Rig Editor (node-based graph)
|
||||
|
||||
### 2. Build Camera Rig (Example: Third Person)
|
||||
|
||||
**Node Setup:**
|
||||
```
|
||||
Actor Position (Character)
|
||||
↓
|
||||
Orbit Node (Orbit around character)
|
||||
↓
|
||||
Offset Node (Shoulder offset)
|
||||
↓
|
||||
Look At Node (Look at character)
|
||||
↓
|
||||
Camera Output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Camera Nodes
|
||||
|
||||
### Position Nodes
|
||||
|
||||
#### Orbit Node (Third Person)
|
||||
- Orbits around target actor
|
||||
- Configure:
|
||||
- **Orbit Distance**: Distance from target (e.g., 300 units)
|
||||
- **Pitch Range**: Min/Max pitch angles
|
||||
- **Yaw Range**: Min/Max yaw angles
|
||||
|
||||
#### Follow Node (Smooth Follow)
|
||||
- Follows target with lag
|
||||
- Configure:
|
||||
- **Lag Speed**: How quickly camera catches up
|
||||
- **Offset**: Fixed offset from target
|
||||
|
||||
#### Fixed Position Node
|
||||
- Static camera position in world space
|
||||
|
||||
---
|
||||
|
||||
### Rotation Nodes
|
||||
|
||||
#### Look At Node
|
||||
- Points camera at target
|
||||
- Configure:
|
||||
- **Target**: Actor or component to look at
|
||||
- **Offset**: Look-at offset (e.g., aim at head instead of feet)
|
||||
|
||||
#### Match Actor Rotation
|
||||
- Matches target actor's rotation
|
||||
- Useful for first-person or vehicle cameras
|
||||
|
||||
---
|
||||
|
||||
### Modifier Nodes
|
||||
|
||||
#### Camera Shake
|
||||
- Adds procedural shake (e.g., footsteps, explosions)
|
||||
- Configure:
|
||||
- **Shake Pattern**: Perlin noise, sine wave, custom
|
||||
- **Amplitude**: Shake strength
|
||||
|
||||
#### Camera Lag
|
||||
- Smooth dampening of camera movement
|
||||
- Configure:
|
||||
- **Lag Speed**: Damping factor (0 = instant, higher = more lag)
|
||||
|
||||
#### Offset Node
|
||||
- Static offset from calculated position
|
||||
- Useful for shoulder camera offset
|
||||
|
||||
---
|
||||
|
||||
## Camera Director (Switching Between Rigs)
|
||||
|
||||
### Assign Camera Rig
|
||||
|
||||
```cpp
|
||||
#include "GameplayCameras/Public/GameplayCameraComponent.h"
|
||||
|
||||
void AMyCharacter::SetCameraMode(UGameplayCameraRig* NewRig) {
|
||||
if (CameraComponent) {
|
||||
CameraComponent->SetCameraRig(NewRig);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Blend Between Camera Rigs
|
||||
|
||||
```cpp
|
||||
// Blend to aiming camera over 0.5 seconds
|
||||
CameraComponent->BlendToCameraRig(AimingCameraRig, 0.5f);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Example: Third Person + Aiming
|
||||
|
||||
### 1. Create Two Camera Rigs
|
||||
|
||||
**Third Person Rig:**
|
||||
```
|
||||
Actor Position → Orbit (distance: 300) → Look At → Output
|
||||
```
|
||||
|
||||
**Aiming Rig:**
|
||||
```
|
||||
Actor Position → Orbit (distance: 150) → Offset (shoulder) → Look At → Output
|
||||
```
|
||||
|
||||
### 2. Switch on Aim
|
||||
|
||||
```cpp
|
||||
UPROPERTY(EditAnywhere, Category = "Camera")
|
||||
TObjectPtr<UGameplayCameraRig> ThirdPersonRig;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Camera")
|
||||
TObjectPtr<UGameplayCameraRig> AimingRig;
|
||||
|
||||
void StartAiming() {
|
||||
CameraComponent->BlendToCameraRig(AimingRig, 0.3f); // Blend over 0.3s
|
||||
}
|
||||
|
||||
void StopAiming() {
|
||||
CameraComponent->BlendToCameraRig(ThirdPersonRig, 0.3f);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Over-the-Shoulder Camera
|
||||
|
||||
```
|
||||
Actor Position
|
||||
↓
|
||||
Orbit Node (distance: 250, yaw offset: 30°)
|
||||
↓
|
||||
Offset Node (X: 0, Y: 50, Z: 50) // Shoulder offset
|
||||
↓
|
||||
Look At Node (target: Character head)
|
||||
↓
|
||||
Output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Vehicle Camera
|
||||
|
||||
```
|
||||
Vehicle Position
|
||||
↓
|
||||
Follow Node (lag: 0.2)
|
||||
↓
|
||||
Offset Node (behind vehicle: X: -400, Z: 150)
|
||||
↓
|
||||
Look At Node (target: Vehicle)
|
||||
↓
|
||||
Output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### First Person Camera
|
||||
|
||||
```
|
||||
Character Head Socket
|
||||
↓
|
||||
Match Actor Rotation
|
||||
↓
|
||||
Output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Camera Shake
|
||||
|
||||
### Trigger Camera Shake
|
||||
|
||||
```cpp
|
||||
#include "GameplayCameras/Public/GameplayCameraShake.h"
|
||||
|
||||
void TriggerExplosionShake() {
|
||||
if (APlayerController* PC = GetWorld()->GetFirstPlayerController()) {
|
||||
if (UGameplayCameraComponent* CameraComp = PC->FindComponentByClass<UGameplayCameraComponent>()) {
|
||||
CameraComp->PlayCameraShake(ExplosionShakeClass, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
- Limit camera shake frequency (don't trigger every frame)
|
||||
- Use camera lag sparingly (expensive for high lag values)
|
||||
- Cache camera rig references (don't search every frame)
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Camera Debug Visualization
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// GameplayCameras.Debug 1 - Show active camera rig info
|
||||
// showdebug camera - Show camera debug info
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration from Legacy Cameras
|
||||
|
||||
### Old Spring Arm + Camera Component
|
||||
|
||||
```cpp
|
||||
// ❌ OLD: Spring Arm Component
|
||||
USpringArmComponent* SpringArm;
|
||||
UCameraComponent* Camera;
|
||||
|
||||
// ✅ NEW: Gameplay Camera Component
|
||||
UGameplayCameraComponent* CameraComponent;
|
||||
// Build orbit + look-at rig in Camera Rig asset
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Limitations (Experimental Status)
|
||||
|
||||
- **API Instability**: Expect breaking changes in UE 5.8+
|
||||
- **Limited Documentation**: Official docs still evolving
|
||||
- **Blueprint Support**: Primarily C++ focused (Blueprint support improving)
|
||||
- **Production Risk**: Test thoroughly before shipping
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/gameplay-cameras-in-unreal-engine/
|
||||
- UE 5.5+ Release Notes
|
||||
- **Note:** This system is experimental. Always check latest official docs for API changes.
|
||||
356
docs/engine-reference/unreal/plugins/pcg.md
Normal file
356
docs/engine-reference/unreal/plugins/pcg.md
Normal file
@@ -0,0 +1,356 @@
|
||||
# Unreal Engine 5.7 — PCG (Procedural Content Generation)
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Status:** Production-Ready (as of UE 5.7)
|
||||
**Plugin:** `PCG` (built-in, enable in Plugins)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Procedural Content Generation (PCG)** is Unreal's node-based framework for generating
|
||||
procedural content at massive scale. It's designed for populating large open worlds with
|
||||
foliage, rocks, props, buildings, and other environmental detail.
|
||||
|
||||
**Use PCG for:**
|
||||
- Procedural foliage placement (trees, grass, rocks)
|
||||
- Biome-based environment generation
|
||||
- Road/path generation
|
||||
- Building/structure placement
|
||||
- World detail population (props, clutter)
|
||||
|
||||
**DON'T use PCG for:**
|
||||
- Gameplay logic (use Blueprints/C++)
|
||||
- One-off manual placement (use editor tools)
|
||||
|
||||
**⚠️ Note:** PCG was experimental in UE 5.0-5.6, became production-ready in UE 5.7.
|
||||
|
||||
---
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### 1. **PCG Graph**
|
||||
- Node-based graph (similar to Material Editor)
|
||||
- Defines generation rules
|
||||
|
||||
### 2. **PCG Component**
|
||||
- Placed in level, executes PCG Graph
|
||||
- Generates content in defined volume
|
||||
|
||||
### 3. **PCG Data**
|
||||
- Point data (positions, rotations, scales)
|
||||
- Spline data (paths, roads, rivers)
|
||||
- Volume data (density, biome masks)
|
||||
|
||||
### 4. **Nodes**
|
||||
- **Samplers**: Generate points (Grid, Poisson, Surface)
|
||||
- **Filters**: Remove points based on rules (Density, Tag, Bounds)
|
||||
- **Modifiers**: Transform points (Offset, Rotate, Scale)
|
||||
- **Spawners**: Instantiate meshes/actors at points
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Enable Plugin
|
||||
|
||||
`Edit > Plugins > PCG > Enabled > Restart`
|
||||
|
||||
### 2. Create PCG Volume
|
||||
|
||||
1. Place Actors > Volumes > PCG Volume
|
||||
2. Scale volume to desired generation area
|
||||
|
||||
### 3. Create PCG Graph
|
||||
|
||||
1. Content Browser > PCG > PCG Graph
|
||||
2. Open PCG Graph Editor
|
||||
|
||||
---
|
||||
|
||||
## Basic Workflow
|
||||
|
||||
### Example: Forest Generation
|
||||
|
||||
#### 1. Create PCG Graph
|
||||
|
||||
**Node Setup:**
|
||||
```
|
||||
Input (Volume)
|
||||
↓
|
||||
Surface Sampler (sample volume surface, points per m²: 0.5)
|
||||
↓
|
||||
Density Filter (use texture mask or noise)
|
||||
↓
|
||||
Static Mesh Spawner (tree meshes)
|
||||
↓
|
||||
Output
|
||||
```
|
||||
|
||||
#### 2. Assign Graph to Volume
|
||||
|
||||
1. Select PCG Volume
|
||||
2. Details Panel > PCG Component > Graph = Your PCG Graph
|
||||
3. Click "Generate" button
|
||||
|
||||
---
|
||||
|
||||
## Key Node Types
|
||||
|
||||
### Samplers (Point Generation)
|
||||
|
||||
#### Grid Sampler
|
||||
- Regular grid of points
|
||||
- Configure:
|
||||
- **Grid Size**: Distance between points
|
||||
- **Offset**: Random offset per point
|
||||
|
||||
#### Poisson Disk Sampler
|
||||
- Random points with minimum distance
|
||||
- Configure:
|
||||
- **Points Per m²**: Density
|
||||
- **Min Distance**: Spacing between points
|
||||
|
||||
#### Surface Sampler
|
||||
- Points on mesh surfaces or landscape
|
||||
- Configure:
|
||||
- **Points Per m²**: Density
|
||||
- **Surface Only**: Only surface, not volume
|
||||
|
||||
---
|
||||
|
||||
### Filters (Point Removal)
|
||||
|
||||
#### Density Filter
|
||||
- Remove points based on density value
|
||||
- Input: Texture or noise
|
||||
- Use for: Biome masks, clearings, paths
|
||||
|
||||
#### Tag Filter
|
||||
- Filter points by tag
|
||||
- Use for: Conditional spawning
|
||||
|
||||
#### Bounds Filter
|
||||
- Keep only points within bounds
|
||||
- Use for: Limiting generation to specific areas
|
||||
|
||||
---
|
||||
|
||||
### Modifiers (Point Transformation)
|
||||
|
||||
#### Rotate
|
||||
- Randomize point rotation
|
||||
- Configure:
|
||||
- **Min/Max Rotation**: Rotation range per axis
|
||||
|
||||
#### Scale
|
||||
- Randomize point scale
|
||||
- Configure:
|
||||
- **Min/Max Scale**: Scale range
|
||||
|
||||
#### Project to Ground
|
||||
- Snap points to landscape surface
|
||||
|
||||
---
|
||||
|
||||
### Spawners (Mesh/Actor Instantiation)
|
||||
|
||||
#### Static Mesh Spawner
|
||||
- Spawn static meshes at points
|
||||
- Configure:
|
||||
- **Mesh List**: Array of meshes (random selection)
|
||||
- **Culling Distance**: LOD/culling settings
|
||||
|
||||
#### Actor Spawner
|
||||
- Spawn Blueprint actors at points
|
||||
- Use for: Gameplay actors, interactive objects
|
||||
|
||||
---
|
||||
|
||||
## Data Sources
|
||||
|
||||
### Landscape
|
||||
- Use landscape as input for sampling
|
||||
- Automatically projects to landscape height
|
||||
|
||||
### Splines
|
||||
- Generate content along splines (roads, rivers, paths)
|
||||
- Example: Trees along path
|
||||
|
||||
### Textures
|
||||
- Use textures as density masks
|
||||
- Paint biomes, clearings, areas
|
||||
|
||||
---
|
||||
|
||||
## Biome Example (Mixed Forest)
|
||||
|
||||
### Graph Setup
|
||||
|
||||
```
|
||||
Input (Landscape)
|
||||
↓
|
||||
Surface Sampler (density: 1.0)
|
||||
↓
|
||||
┌─────────────────┬─────────────────┐
|
||||
│ Tree Biome │ Rock Biome │
|
||||
│ (density > 0.5) │ (density < 0.5) │
|
||||
├─────────────────┼─────────────────┤
|
||||
│ Tree Spawner │ Rock Spawner │
|
||||
└─────────────────┴─────────────────┘
|
||||
↓
|
||||
Merge
|
||||
↓
|
||||
Output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Spline-Based Generation (Road with Trees)
|
||||
|
||||
### 1. Create PCG Graph
|
||||
|
||||
```
|
||||
Spline Input
|
||||
↓
|
||||
Spline Sampler (sample along spline)
|
||||
↓
|
||||
Offset (offset from spline path)
|
||||
↓
|
||||
Tree Spawner
|
||||
↓
|
||||
Output
|
||||
```
|
||||
|
||||
### 2. Add Spline Component to PCG Volume
|
||||
|
||||
1. PCG Volume > Add Component > Spline
|
||||
2. Draw spline path
|
||||
3. PCG Graph reads spline data
|
||||
|
||||
---
|
||||
|
||||
## Runtime Generation
|
||||
|
||||
### Trigger Generation from C++
|
||||
|
||||
```cpp
|
||||
#include "PCGComponent.h"
|
||||
|
||||
UPCGComponent* PCGComp = /* Get PCG Component */;
|
||||
PCGComp->Generate(); // Execute PCG graph
|
||||
```
|
||||
|
||||
### Stream Generation (Large Worlds)
|
||||
|
||||
- PCG automatically streams with World Partition
|
||||
- Only generates content in loaded cells
|
||||
|
||||
---
|
||||
|
||||
## Performance
|
||||
|
||||
### Optimization Tips
|
||||
|
||||
- Use **culling distance** on spawned meshes (LOD)
|
||||
- Limit **density** (fewer points = better performance)
|
||||
- Use **Hierarchical Instanced Static Meshes (HISM)** for repeated meshes
|
||||
- Enable **streaming** for large worlds
|
||||
|
||||
### Debug Performance
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// pcg.graph.debug 1 - Show PCG debug info
|
||||
// stat pcg - Show PCG performance stats
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Forest with Clearings
|
||||
|
||||
```
|
||||
Surface Sampler
|
||||
↓
|
||||
Density Filter (noise texture with clearings)
|
||||
↓
|
||||
Tree Spawner (pine, oak, birch)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Rocks on Steep Slopes
|
||||
|
||||
```
|
||||
Landscape Input
|
||||
↓
|
||||
Surface Sampler
|
||||
↓
|
||||
Slope Filter (angle > 30°)
|
||||
↓
|
||||
Rock Spawner
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Props Along Road
|
||||
|
||||
```
|
||||
Spline Input (road spline)
|
||||
↓
|
||||
Spline Sampler
|
||||
↓
|
||||
Offset (side of road)
|
||||
↓
|
||||
Street Light Spawner
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### PCG Debug Visualization
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// pcg.debug.display 1 - Show points and generation bounds
|
||||
// pcg.debug.colormode points - Color-code points
|
||||
```
|
||||
|
||||
### Graph Debugging
|
||||
|
||||
- PCG Graph Editor > Debug > Show Debug Points
|
||||
- Visualize points at each node in the graph
|
||||
|
||||
---
|
||||
|
||||
## Migration from UE 5.6 (Experimental) to 5.7 (Production)
|
||||
|
||||
### API Changes
|
||||
|
||||
```cpp
|
||||
// ❌ OLD (5.6 experimental API):
|
||||
// Some nodes renamed, API unstable
|
||||
|
||||
// ✅ NEW (5.7 production API):
|
||||
// Stable node types, documented API
|
||||
```
|
||||
|
||||
**Migration:** Rebuild PCG graphs using stable 5.7 nodes. Test thoroughly.
|
||||
|
||||
---
|
||||
|
||||
## Limitations
|
||||
|
||||
- **Not for gameplay logic**: Use Blueprints/C++ for game rules
|
||||
- **Large graphs can be slow**: Optimize with filters and density reduction
|
||||
- **Runtime generation overhead**: Pre-generate when possible
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/procedural-content-generation-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/pcg-quick-start-in-unreal-engine/
|
||||
- UE 5.7 Release Notes (PCG Production-Ready announcement)
|
||||
Reference in New Issue
Block a user