@ericrisco/rsc 0.1.34 → 0.1.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -2
- package/manifest.json +241 -2
- package/package.json +1 -1
- package/scripts/lib/domains.js +1 -0
- package/scripts/lib/recommend.js +4 -0
- package/skills/agent-eval/SKILL.md +1 -1
- package/skills/analyze/SKILL.md +1 -1
- package/skills/brand-voice/SKILL.md +1 -1
- package/skills/brand-voice/references/voice-guide-template.md +14 -0
- package/skills/building-agents/SKILL.md +2 -2
- package/skills/competitor-watch/SKILL.md +9 -4
- package/skills/competitor-watch/references/tracker-schema.md +19 -0
- package/skills/constitution/references/constitution-template.md +10 -0
- package/skills/content-engine/SKILL.md +1 -1
- package/skills/content-engine/references/brief-and-pipeline.md +15 -1
- package/skills/course-builder/references/grounding-and-scoping.md +23 -0
- package/skills/course-storytelling/references/learner-grounding.md +22 -2
- package/skills/decision-records/SKILL.md +14 -1
- package/skills/decision-records/references/templates.md +20 -0
- package/skills/design/references/brand-grounding.md +11 -1
- package/skills/game-design/SKILL.md +170 -0
- package/skills/game-design/evals/README.md +13 -0
- package/skills/game-design/evals/cases.yaml +47 -0
- package/skills/game-design/references/mechanics-and-loops.md +78 -0
- package/skills/game-design/references/playtesting-and-scope.md +58 -0
- package/skills/game-design/references/progression-and-economy.md +70 -0
- package/skills/game-storytelling/SKILL.md +159 -0
- package/skills/game-storytelling/evals/README.md +28 -0
- package/skills/game-storytelling/evals/cases.yaml +51 -0
- package/skills/game-storytelling/references/branching-and-state.md +134 -0
- package/skills/game-storytelling/references/dialogue-tools.md +117 -0
- package/skills/game-storytelling/references/environmental-storytelling.md +71 -0
- package/skills/gamedev-multiplayer/SKILL.md +250 -0
- package/skills/gamedev-multiplayer/evals/README.md +12 -0
- package/skills/gamedev-multiplayer/evals/cases.yaml +44 -0
- package/skills/gamedev-multiplayer/references/godot-high-level-multiplayer.md +133 -0
- package/skills/gamedev-multiplayer/references/prediction-and-latency.md +104 -0
- package/skills/gamedev-multiplayer/references/unity-and-unreal-netcode.md +166 -0
- package/skills/gamedev-pathing/SKILL.md +242 -0
- package/skills/gamedev-pathing/evals/README.md +14 -0
- package/skills/gamedev-pathing/evals/cases.yaml +49 -0
- package/skills/gamedev-pathing/references/navmesh-workflow.md +110 -0
- package/skills/gamedev-pathing/references/search-algorithms.md +135 -0
- package/skills/gamedev-pathing/references/steering-and-avoidance.md +120 -0
- package/skills/gamedev-physics/SKILL.md +225 -0
- package/skills/gamedev-physics/evals/README.md +12 -0
- package/skills/gamedev-physics/evals/cases.yaml +54 -0
- package/skills/gamedev-physics/references/character-controllers.md +120 -0
- package/skills/gamedev-physics/references/determinism-and-queries.md +124 -0
- package/skills/gamedev-physics/references/layers-and-masks.md +115 -0
- package/skills/gamedev-shaders/SKILL.md +252 -0
- package/skills/gamedev-shaders/evals/README.md +14 -0
- package/skills/gamedev-shaders/evals/cases.yaml +45 -0
- package/skills/gamedev-shaders/references/effect-recipes.md +205 -0
- package/skills/gamedev-shaders/references/godot-shading-language.md +133 -0
- package/skills/gamedev-shaders/references/unity-and-unreal-shaders.md +169 -0
- package/skills/gamedev-shipping/SKILL.md +236 -0
- package/skills/gamedev-shipping/evals/README.md +9 -0
- package/skills/gamedev-shipping/evals/cases.yaml +55 -0
- package/skills/gamedev-shipping/references/mobile-and-desktop.md +127 -0
- package/skills/gamedev-shipping/references/stores-and-ci.md +162 -0
- package/skills/gamedev-shipping/references/web-export-headers.md +140 -0
- package/skills/godot/SKILL.md +319 -0
- package/skills/godot/evals/README.md +13 -0
- package/skills/godot/evals/cases.yaml +50 -0
- package/skills/godot/references/export-and-testing.md +102 -0
- package/skills/godot/references/gdscript-style.md +84 -0
- package/skills/godot/references/godot3-to-4-traps.md +89 -0
- package/skills/godot/references/nodes-scenes-resources.md +109 -0
- package/skills/harness/SKILL.md +3 -3
- package/skills/harness/references/daily-curation-automation.md +8 -6
- package/skills/harness/references/obsidian-scaffolding.md +16 -9
- package/skills/harness/references/wiki-article-template.md +31 -14
- package/skills/harness/references/wiki-index-template.md +7 -3
- package/skills/harness/references/wiki-protocol.md +120 -54
- package/skills/harness/references/wiki-worklog-template.md +5 -1
- package/skills/instagram-api/SKILL.md +8 -1
- package/skills/instagram-api/references/insights-metrics.md +8 -1
- package/skills/knowledge-ops/SKILL.md +9 -9
- package/skills/knowledge-ops/evals/cases.yaml +1 -1
- package/skills/knowledge-ops/references/gardening-playbook.md +18 -8
- package/skills/level-design/SKILL.md +175 -0
- package/skills/level-design/evals/README.md +35 -0
- package/skills/level-design/evals/cases.yaml +58 -0
- package/skills/level-design/references/blockout-to-art.md +118 -0
- package/skills/level-design/references/guidance-and-readability.md +152 -0
- package/skills/level-design/references/pacing-and-encounters.md +142 -0
- package/skills/linkedin-api/SKILL.md +10 -1
- package/skills/linkedin-strategy/SKILL.md +12 -0
- package/skills/linkedin-strategy/references/wiki-records.md +27 -1
- package/skills/marketing/references/brand-grounding.md +22 -2
- package/skills/medium-strategy/SKILL.md +12 -0
- package/skills/medium-strategy/references/wiki-records.md +39 -1
- package/skills/medium-writing/SKILL.md +19 -0
- package/skills/plan/references/plan-template.md +12 -1
- package/skills/roast-me/tools/adapters/__pycache__/__init__.cpython-312.pyc +0 -0
- package/skills/roast-me/tools/adapters/__pycache__/base.cpython-312.pyc +0 -0
- package/skills/roast-me/tools/adapters/__pycache__/claude.cpython-312.pyc +0 -0
- package/skills/roast-me/tools/adapters/__pycache__/codex.cpython-312.pyc +0 -0
- package/skills/roast-me/tools/adapters/__pycache__/gemini.cpython-312.pyc +0 -0
- package/skills/roast-me/tools/adapters/__pycache__/registry.cpython-312.pyc +0 -0
- package/skills/shortform-packaging/SKILL.md +7 -2
- package/skills/shortform-packaging/references/package-templates.md +13 -2
- package/skills/shortform-strategy/SKILL.md +30 -6
- package/skills/shortform-strategy/references/learning-loop-template.md +9 -1
- package/skills/specify/references/spec-template.md +12 -1
- package/skills/tiktok-api/SKILL.md +6 -2
- package/skills/tiktok-api/references/wiki-schema.md +38 -4
- package/skills/unity/SKILL.md +282 -0
- package/skills/unity/evals/README.md +8 -0
- package/skills/unity/evals/cases.yaml +43 -0
- package/skills/unity/references/build-and-platforms.md +65 -0
- package/skills/unity/references/input-system.md +102 -0
- package/skills/unity/references/lifecycle-deep-dive.md +75 -0
- package/skills/unreal/SKILL.md +270 -0
- package/skills/unreal/evals/README.md +12 -0
- package/skills/unreal/evals/cases.yaml +45 -0
- package/skills/unreal/references/blueprint-cpp-parity.md +109 -0
- package/skills/unreal/references/gameplay-framework.md +95 -0
- package/skills/unreal/references/packaging.md +83 -0
- package/skills/verify/SKILL.md +11 -1
- package/skills/youtube-api/SKILL.md +7 -2
- package/skills/youtube-api/references/wiki-schema.md +25 -4
- package/skills/youtube-packaging/SKILL.md +10 -2
- package/skills/youtube-packaging/references/description-and-chapters.md +70 -2
- package/skills/youtube-strategy/SKILL.md +9 -2
- package/skills/youtube-strategy/references/wiki-records.md +39 -6
- package/skills/youtube-strategy/scripts/verify.sh +4 -0
- package/skills/youtube-thumbnails/SKILL.md +10 -5
- package/skills/youtube-thumbnails/references/experiment-log-format.md +28 -2
|
@@ -24,8 +24,19 @@ from colliding and lets a sibling grep `tiktok-*` for just this account.
|
|
|
24
24
|
|
|
25
25
|
## Account snapshot entry (one file per pull)
|
|
26
26
|
|
|
27
|
+
Frontmatter is **OKF v0.1 conformant**: a non-empty `type` is the only hard
|
|
28
|
+
requirement; `title`/`tags`/`timestamp` are the recommended OKF surface. The
|
|
29
|
+
domain keys (`date`, `range`, `account`, `platform`, `source`, `provisional`) are
|
|
30
|
+
preserved verbatim — siblings parse them, and OKF tolerates arbitrary extra keys.
|
|
31
|
+
`date` is the snapshot's reporting day; `timestamp` is the ISO 8601 moment the file
|
|
32
|
+
was written. Keep both.
|
|
33
|
+
|
|
27
34
|
```markdown
|
|
28
35
|
---
|
|
36
|
+
type: shortform-metrics
|
|
37
|
+
title: TikTok account snapshot — 2026-06-02
|
|
38
|
+
tags: [tiktok, metrics, snapshot]
|
|
39
|
+
timestamp: 2026-06-02T09:00:00Z
|
|
29
40
|
date: 2026-06-02
|
|
30
41
|
range: 2026-05-26..2026-06-01
|
|
31
42
|
account: <open_id>
|
|
@@ -50,11 +61,23 @@ completion +3.1pts after the tighter cold-open; FYP share up 5pts.
|
|
|
50
61
|
|
|
51
62
|
Newest entry on top, so a glance shows the latest. Each pull **prepends** a block —
|
|
52
63
|
this is where the 24–48h settling becomes visible (the same video's
|
|
53
|
-
`full_video_watched_rate` will drift between pulls).
|
|
64
|
+
`full_video_watched_rate` will drift between pulls). This is an OKF append-log:
|
|
65
|
+
the frontmatter header is written once and stays immutable; new dated blocks are
|
|
66
|
+
prepended **above** older ones (newest-first), past blocks are never edited, and
|
|
67
|
+
dates are ISO 8601.
|
|
54
68
|
|
|
55
69
|
```markdown
|
|
70
|
+
---
|
|
71
|
+
type: shortform-record
|
|
72
|
+
title: tiktok-7399 — "cold open hook test"
|
|
73
|
+
tags: [tiktok, video-log]
|
|
74
|
+
timestamp: 2026-06-02T09:00:00Z
|
|
75
|
+
video_id: "7399..."
|
|
76
|
+
platform: tiktok
|
|
77
|
+
posted: 2026-05-28
|
|
78
|
+
duration: 21s
|
|
79
|
+
---
|
|
56
80
|
# tiktok-7399... — "cold open hook test"
|
|
57
|
-
posted: 2026-05-28 | duration: 21s
|
|
58
81
|
|
|
59
82
|
## 2026-06-02 (final-ish)
|
|
60
83
|
views 52,140 | completion 28.4% | avg_watched 6.1s | FYP 71%
|
|
@@ -63,13 +86,18 @@ views 52,140 | completion 28.4% | avg_watched 6.1s | FYP 71%
|
|
|
63
86
|
views 18,900 | completion 24.1% | avg_watched 5.3s | FYP 64%
|
|
64
87
|
```
|
|
65
88
|
|
|
89
|
+
On each prepend, bump the header `timestamp` to the new pull's ISO moment; never
|
|
90
|
+
edit a past dated block.
|
|
91
|
+
|
|
66
92
|
## index.md
|
|
67
93
|
|
|
68
|
-
A thin pointer, not a data dump
|
|
94
|
+
A thin pointer, not a data dump. As an OKF **reserved** file it carries **no
|
|
95
|
+
frontmatter**, and its cross-references are standard markdown links (never
|
|
96
|
+
wikilinks), so an OKF consumer can follow them straight to the snapshot files:
|
|
69
97
|
|
|
70
98
|
```markdown
|
|
71
99
|
# shortform wiki — index
|
|
72
|
-
- tiktok: latest snapshot → tiktok-account-2026-06-02.md
|
|
100
|
+
- tiktok: latest snapshot → [tiktok-account-2026-06-02.md](./tiktok-account-2026-06-02.md)
|
|
73
101
|
- open questions:
|
|
74
102
|
- is the cold-open change holding completion above 27%? (watch next 2 pulls)
|
|
75
103
|
```
|
|
@@ -83,3 +111,9 @@ A thin pointer, not a data dump:
|
|
|
83
111
|
- **Namespace by platform.** `tiktok-` prefix on every file so IG/YouTube pulls coexist.
|
|
84
112
|
- **Numbers only, no interpretation.** "What changed" is a factual delta line, not a
|
|
85
113
|
recommendation — what to *do* about it belongs to `shortform-strategy`.
|
|
114
|
+
- **OKF v0.1 conformant.** Every snapshot and per-video file carries YAML frontmatter
|
|
115
|
+
with a non-empty `type` (`shortform-metrics` / `shortform-record`) plus the OKF
|
|
116
|
+
`title`/`tags`/`timestamp` surface; domain keys like `date` are kept additively. The
|
|
117
|
+
reserved `index.md` carries no frontmatter. All cross-references are standard markdown
|
|
118
|
+
links — never `[[wikilinks]]` — so the `shortform/` tree is a portable OKF bundle the
|
|
119
|
+
siblings (and any OKF consumer) read without translation.
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: unity
|
|
3
|
+
description: "Use when writing, reviewing, or structuring Unity game code in C# for current Unity 6 LTS (6000.x) — GameObjects and Transform hierarchy, MonoBehaviour lifecycle, prefabs and prefab variants, ScriptableObjects for data, scenes and additive loading, the new Input System, coroutines vs async/await/Awaitable, Addressables, and build/player settings for 2D and 3D. Triggers: 'my Unity script', 'Awake vs Start', 'why is my physics jittery', MonoBehaviour .cs files, 'set up the new Input System', 'ScriptableObject config', 'load a scene additively', 'Instantiate a prefab', 'convert Input.GetAxis to the new system', 'build for Android/WebGL', 'por qué no se llama mi Start', 'com carrego una escena en additiu'. NOT Godot/GDScript (that is godot); NOT Unreal/Blueprint/C++ engine work (that is unreal); NOT the netcode wire protocol itself (that is gamedev-multiplayer)."
|
|
4
|
+
tags: [unity, csharp, game-dev, monobehaviour, input-system]
|
|
5
|
+
recommends: [gamedev-multiplayer, gamedev-physics, gamedev-shaders, gamedev-pathing, gamedev-shipping, godot, unreal]
|
|
6
|
+
profiles: [full]
|
|
7
|
+
origin: risco
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Unity + C# (Unity 6 LTS)
|
|
11
|
+
|
|
12
|
+
> Idiomatic C# for the current Unity engine — 2D and 3D. Owns engine-side patterns (components,
|
|
13
|
+
> lifecycle, prefabs, scenes, data, input, async, builds). Not Godot (`godot`) or Unreal (`unreal`);
|
|
14
|
+
> stops at the netcode wire (`gamedev-multiplayer`).
|
|
15
|
+
|
|
16
|
+
## Version contract — read first
|
|
17
|
+
|
|
18
|
+
**Target: Unity 6 LTS, versioned `6000.x`.** Current LTS at authoring is **Unity 6.3 LTS (`6000.3`)**
|
|
19
|
+
(supported to Dec 2027); **Unity 6.0 LTS (`6000.0`)** to Oct 2026. Unity 6 dropped the year-based names
|
|
20
|
+
(2020/2021/2022 LTS) for the `6000.x` scheme. Confirm the project version in
|
|
21
|
+
`ProjectSettings/ProjectVersion.txt` before assuming an API exists.
|
|
22
|
+
|
|
23
|
+
**Ban-list — never emit these; use the modern replacement:**
|
|
24
|
+
|
|
25
|
+
| Deprecated / removed | Use instead |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| `Input.GetAxis` / `GetKey` / `GetButton` (legacy Input Manager) | **new Input System** (`com.unity.inputsystem`): `InputActionAsset` / `InputAction` / `PlayerInput` — §6 |
|
|
28
|
+
| `UnityEngine.Networking` (UNet), `NetworkServer`/`NetworkClient`, its `NetworkBehaviour` | **removed** since 2022.2. → **Netcode for GameObjects** (`com.unity.netcode.gameobjects`) + `gamedev-multiplayer` |
|
|
29
|
+
| `Resources.Load(...)` for game content | **Addressables** (`com.unity.addressables`) — §8 |
|
|
30
|
+
| `FindObjectOfType<T>()` / `FindObjectsOfType<T>()` | `FindFirstObjectByType<T>()` / `FindAnyObjectByType<T>()` / `FindObjectsByType<T>(FindObjectsSortMode.None)` (old ones obsolete since 2023.1) |
|
|
31
|
+
| `WWW` | `UnityWebRequest` |
|
|
32
|
+
| `OnGUI` / IMGUI for runtime game UI | **UI Toolkit** (runtime) or uGUI; keep IMGUI for editor tools only |
|
|
33
|
+
| Setting `transform.position` on a `Rigidbody` in `Update` | `Rigidbody.MovePosition/MoveRotation` in `FixedUpdate` — §4 |
|
|
34
|
+
| `GameObject.Find`/`FindWithTag` by string in `Update` | cache the ref in `Awake`, or `[SerializeField]` it |
|
|
35
|
+
|
|
36
|
+
Prefer the new Input System even for single-player prototypes. Keep `Debug.Log` out of hot loops and
|
|
37
|
+
strip it from ships.
|
|
38
|
+
|
|
39
|
+
## 1. GameObject / Component model & Transform hierarchy
|
|
40
|
+
|
|
41
|
+
A **GameObject** is an empty container; behaviour comes from **Components** you attach
|
|
42
|
+
(`Transform`, `Rigidbody`, `MeshRenderer`, and your `MonoBehaviour` scripts). Every GameObject has
|
|
43
|
+
exactly one `Transform` (or `RectTransform` under a Canvas) giving position/rotation/scale.
|
|
44
|
+
|
|
45
|
+
- Get components: `TryGetComponent(out var rb)` (no-alloc, preferred), `GetComponent<T>()`,
|
|
46
|
+
`GetComponentInChildren/InParent<T>()`. Cache in `Awake` — `GetComponent` in `Update` is a perf sink.
|
|
47
|
+
- Hierarchy: `transform.parent`, `transform.SetParent(newParent, worldPositionStays: true)`,
|
|
48
|
+
`transform.childCount`, `foreach (Transform child in transform)`. Child world = parent × local.
|
|
49
|
+
- Same object model for 2D and 3D: 2D uses `Rigidbody2D`/`Collider2D`/`SpriteRenderer`; 3D uses
|
|
50
|
+
`Rigidbody`/`Collider`/`MeshRenderer`. Never mix 2D and 3D physics components on one body.
|
|
51
|
+
|
|
52
|
+
```csharp
|
|
53
|
+
[RequireComponent(typeof(Rigidbody))]
|
|
54
|
+
public sealed class Mover : MonoBehaviour
|
|
55
|
+
{
|
|
56
|
+
Rigidbody _rb;
|
|
57
|
+
void Awake() => _rb = GetComponent<Rigidbody>(); // cache once
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 2. Prefabs & prefab variants; instantiation
|
|
62
|
+
|
|
63
|
+
A **Prefab** is a reusable GameObject template (an asset). A **Prefab Variant** inherits from a base
|
|
64
|
+
prefab and overrides selected properties/children — like subclassing for assets (e.g. `Enemy` base →
|
|
65
|
+
`EnemyFast` variant). Edit the base and variants inherit the change unless they override that value.
|
|
66
|
+
|
|
67
|
+
- Spawn with `Instantiate(prefab, position, rotation, parent)`; it returns the concrete type
|
|
68
|
+
(`var e = Instantiate(_enemyPrefab);` with `[SerializeField] Enemy _enemyPrefab;`). Store the
|
|
69
|
+
serialized reference; do not `Resources.Load` it.
|
|
70
|
+
- Destroy with `Destroy(gameObject)` (end of frame) or `Destroy(obj, delay)`. Never `DestroyImmediate`
|
|
71
|
+
at runtime. For frequently spawned objects (bullets, VFX) **pool** them (`UnityEngine.Pool.ObjectPool<T>`)
|
|
72
|
+
instead of Instantiate/Destroy churn.
|
|
73
|
+
- Editor-only prefab authoring uses `PrefabUtility` (wrap in `#if UNITY_EDITOR`); absent in builds.
|
|
74
|
+
|
|
75
|
+
## 3. Scenes & scene management (additive loading)
|
|
76
|
+
|
|
77
|
+
A **Scene** holds a set of GameObjects. Register scenes in **Build Profiles → Scene List** (Unity 6;
|
|
78
|
+
formerly Build Settings) so they can load by index or name.
|
|
79
|
+
|
|
80
|
+
```csharp
|
|
81
|
+
using UnityEngine.SceneManagement;
|
|
82
|
+
|
|
83
|
+
// Additive: keep the current scene, layer another on top (e.g. UI, a level chunk).
|
|
84
|
+
var op = SceneManager.LoadSceneAsync("Level_02", LoadSceneMode.Additive);
|
|
85
|
+
op.completed += _ => Debug.Log("Level_02 loaded");
|
|
86
|
+
await op; // Unity 6: AsyncOperation is awaitable
|
|
87
|
+
|
|
88
|
+
// Unload just that scene later:
|
|
89
|
+
await SceneManager.UnloadSceneAsync("Level_02");
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- `LoadSceneMode.Single` (default) unloads everything first; `Additive` composes scenes — the basis of
|
|
93
|
+
streaming worlds, persistent manager scenes, and separate UI scenes.
|
|
94
|
+
- `SceneManager.MoveGameObjectToScene` moves an object between loaded scenes; `DontDestroyOnLoad` objects
|
|
95
|
+
survive `Single` loads (use for a bootstrap/services scene). Prefer `LoadSceneAsync` to avoid a hitch.
|
|
96
|
+
|
|
97
|
+
## 4. MonoBehaviour lifecycle
|
|
98
|
+
|
|
99
|
+
Order per frame and where each concern belongs (full ordering in `references/lifecycle-deep-dive.md`):
|
|
100
|
+
|
|
101
|
+
| Method | When | Put here |
|
|
102
|
+
| --- | --- | --- |
|
|
103
|
+
| `Awake` | once, on instantiation (even if disabled) | cache `GetComponent`, self-init, no cross-object refs |
|
|
104
|
+
| `OnEnable` | each time the object/component enables | subscribe to events, register callbacks |
|
|
105
|
+
| `Start` | once, before first `Update`, only if active | cross-object wiring (other objects' `Awake` has run) |
|
|
106
|
+
| `FixedUpdate` | fixed timestep (physics tick), 0..n / frame | **all physics** — `Rigidbody` forces/`MovePosition`, `ApplyForce` |
|
|
107
|
+
| `Update` | every frame | input reads, game logic, timers (scale by `Time.deltaTime`) |
|
|
108
|
+
| `LateUpdate` | every frame, after all `Update` | camera follow, look-at, anything tracking moved objects |
|
|
109
|
+
| `OnDisable` | each disable / before destroy | **unsubscribe** everything subscribed in `OnEnable` |
|
|
110
|
+
| `OnDestroy` | once, on destruction | release native/unmanaged resources, final cleanup |
|
|
111
|
+
|
|
112
|
+
Rules that bite:
|
|
113
|
+
- **Physics goes in `FixedUpdate`**, never `Update`. Reading input in `FixedUpdate` drops events —
|
|
114
|
+
read input in `Update`, cache intent, apply forces in `FixedUpdate`.
|
|
115
|
+
- Frame-rate independence: multiply per-frame movement by `Time.deltaTime` (`Update`) — but
|
|
116
|
+
`FixedUpdate` already runs at a fixed `Time.fixedDeltaTime`.
|
|
117
|
+
- `Awake` runs even on inactive objects; `Start` does not run until the object is active. Cross-object
|
|
118
|
+
references belong in `Start`, not `Awake`.
|
|
119
|
+
- Every `OnEnable` subscription needs a matching `OnDisable` unsubscription or you leak and get
|
|
120
|
+
double-fires after re-enable.
|
|
121
|
+
|
|
122
|
+
## 5. ScriptableObjects for data/config; serialization
|
|
123
|
+
|
|
124
|
+
A **ScriptableObject** is a data asset that lives outside any scene — ideal for config, tuning tables,
|
|
125
|
+
enemy/item definitions, and event channels. One asset is shared by reference (no per-instance copy),
|
|
126
|
+
so it saves memory and lets designers tweak values without touching code.
|
|
127
|
+
|
|
128
|
+
```csharp
|
|
129
|
+
[CreateAssetMenu(fileName = "WeaponDef", menuName = "Game/Weapon Definition")]
|
|
130
|
+
public sealed class WeaponDefinition : ScriptableObject
|
|
131
|
+
{
|
|
132
|
+
[SerializeField] float _damage = 10f;
|
|
133
|
+
[SerializeField] float _fireRate = 2f;
|
|
134
|
+
public float Damage => _damage; // expose read-only
|
|
135
|
+
public float FireRate => _fireRate;
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**`[SerializeField] private` vs `public`:** default to `[SerializeField] private` + a public
|
|
140
|
+
property/method. It shows in the Inspector and survives serialization *without* letting arbitrary code
|
|
141
|
+
mutate the field — encapsulation intact. Use bare `public` only for genuine data bags.
|
|
142
|
+
|
|
143
|
+
**Serialization rules (they trip everyone):**
|
|
144
|
+
- Unity serializes: `public` or `[SerializeField]` fields of supported types (primitives, `string`,
|
|
145
|
+
Unity types, enums, arrays/`List<T>` of those, and `[Serializable]` plain classes/structs).
|
|
146
|
+
- Unity does **not** serialize: properties (use `[field: SerializeField] public float X { get; private set; }`),
|
|
147
|
+
`static`, `readonly`, `const`, `Dictionary<,>` (use two lists or a serializable wrapper), or
|
|
148
|
+
polymorphic references — for interface/abstract fields use `[SerializeReference]`.
|
|
149
|
+
- Do not hold runtime mutable state on a shared ScriptableObject expecting it to reset — it persists in
|
|
150
|
+
the Editor between play sessions. Keep SOs for config; put mutable per-instance state on MonoBehaviours.
|
|
151
|
+
|
|
152
|
+
## 6. Input System (new) — with a legacy contrast
|
|
153
|
+
|
|
154
|
+
The new Input System (`com.unity.inputsystem`) is enabled by default in Unity 6 and is device-agnostic
|
|
155
|
+
and event-driven. Define an **Input Action Asset** with **Action Maps** (e.g. "Player", "UI") and
|
|
156
|
+
**Actions** (e.g. "Move" = Value/`Vector2`, "Jump" = Button). Generate a C# wrapper or use the
|
|
157
|
+
`PlayerInput` component. Full setup, `PlayerInput`, and rebinding in `references/input-system.md`.
|
|
158
|
+
|
|
159
|
+
```csharp
|
|
160
|
+
// New Input System — subscribe to the generated actions (no per-frame polling).
|
|
161
|
+
using UnityEngine.InputSystem;
|
|
162
|
+
|
|
163
|
+
public sealed class PlayerController : MonoBehaviour
|
|
164
|
+
{
|
|
165
|
+
InputSystem_Actions _controls; // generated C# class from the .inputactions asset
|
|
166
|
+
Vector2 _move;
|
|
167
|
+
|
|
168
|
+
void Awake() => _controls = new InputSystem_Actions();
|
|
169
|
+
void OnEnable()
|
|
170
|
+
{
|
|
171
|
+
_controls.Player.Enable();
|
|
172
|
+
_controls.Player.Move.performed += ctx => _move = ctx.ReadValue<Vector2>();
|
|
173
|
+
_controls.Player.Move.canceled += _ => _move = Vector2.zero;
|
|
174
|
+
_controls.Player.Jump.performed += _ => Jump();
|
|
175
|
+
}
|
|
176
|
+
void OnDisable() => _controls.Player.Disable();
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Legacy contrast (do not write this in new code):
|
|
181
|
+
```csharp
|
|
182
|
+
// LEGACY Input Manager — string axes, per-frame polling, device-blind. Avoid.
|
|
183
|
+
float x = Input.GetAxis("Horizontal");
|
|
184
|
+
if (Input.GetButtonDown("Jump")) Jump();
|
|
185
|
+
```
|
|
186
|
+
The new system also polls if you prefer: `_controls.Player.Move.ReadValue<Vector2>()` in `Update`.
|
|
187
|
+
|
|
188
|
+
## 7. Coroutines vs async/await vs Awaitable
|
|
189
|
+
|
|
190
|
+
| Use | Reach for | Why |
|
|
191
|
+
| --- | --- | --- |
|
|
192
|
+
| Frame-sequenced gameplay (timers, tweens, "wait then spawn") | **Coroutine** or **Awaitable** | frame-aware yields; auto-tie to object lifetime |
|
|
193
|
+
| Unity-native async in Unity 6 (default for new async gameplay) | **`Awaitable`** | main-thread, low-alloc (pooled), frame + thread awaits, cancels via `destroyCancellationToken` |
|
|
194
|
+
| True background CPU work / library `Task` APIs | **`async Task` + `await`** | thread pool; but marshal back — Unity APIs are main-thread only |
|
|
195
|
+
|
|
196
|
+
```csharp
|
|
197
|
+
// Coroutine — classic, MonoBehaviour-bound, stops when the object disables/destroys.
|
|
198
|
+
IEnumerator SpawnWave()
|
|
199
|
+
{
|
|
200
|
+
yield return new WaitForSeconds(1f);
|
|
201
|
+
Instantiate(_enemyPrefab);
|
|
202
|
+
}
|
|
203
|
+
void Start() => StartCoroutine(SpawnWave());
|
|
204
|
+
|
|
205
|
+
// Awaitable (Unity 6) — the modern replacement. Cancels automatically on destroy.
|
|
206
|
+
async Awaitable SpawnWaveAsync()
|
|
207
|
+
{
|
|
208
|
+
await Awaitable.WaitForSecondsAsync(1f, destroyCancellationToken);
|
|
209
|
+
await Awaitable.NextFrameAsync(destroyCancellationToken);
|
|
210
|
+
Instantiate(_enemyPrefab);
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Rules:
|
|
215
|
+
- **Coroutines** run only while the MonoBehaviour is enabled; they die silently on disable. No return
|
|
216
|
+
value; exceptions across `yield` are awkward.
|
|
217
|
+
- **`Awaitable`**: never `await` the same instance twice (pooled → undefined behavior). Pass
|
|
218
|
+
`destroyCancellationToken` so it stops when the object is destroyed. Switch threads with
|
|
219
|
+
`Awaitable.BackgroundThreadAsync()` / `Awaitable.MainThreadAsync()`.
|
|
220
|
+
- **`Task`**: does *not* auto-cancel on destroy — thread a `CancellationToken` yourself, and never touch
|
|
221
|
+
Unity API off the main thread (it throws). Prefer `Awaitable` in Unity 6 unless you need `Task`.
|
|
222
|
+
|
|
223
|
+
## 8. Addressables (intro) + the Resources anti-pattern
|
|
224
|
+
|
|
225
|
+
**Addressables** (`com.unity.addressables`) is the modern content-loading system: assets get string
|
|
226
|
+
addresses, load asynchronously, and can ship in the build or from a remote CDN with dependency tracking
|
|
227
|
+
and memory-managed release.
|
|
228
|
+
|
|
229
|
+
```csharp
|
|
230
|
+
using UnityEngine.AddressableAssets;
|
|
231
|
+
|
|
232
|
+
var handle = Addressables.InstantiateAsync("Prefabs/Boss");
|
|
233
|
+
GameObject boss = await handle.Task; // or handle.Completed += ...
|
|
234
|
+
// when done: Addressables.ReleaseInstance(boss); // release to free memory
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**`Resources/` is an anti-pattern for game content:** everything under it is forced into the build,
|
|
238
|
+
loaded synchronously, bloats size/startup, and can't be patched or streamed. Reserve it for tiny
|
|
239
|
+
always-needed defaults; migrate real content to Addressables.
|
|
240
|
+
|
|
241
|
+
## 9. Build settings, platforms & player settings
|
|
242
|
+
|
|
243
|
+
- **Build Profiles** (Unity 6, `File → Build Profiles`) supersede the old Build Settings window: per-platform
|
|
244
|
+
scene list, target platform, and overridable player settings.
|
|
245
|
+
- **Scripting backend:** **IL2CPP** (AOT — required for iOS/consoles/WebGL, faster, harder to reverse)
|
|
246
|
+
vs **Mono** (JIT, Editor/desktop, faster iteration). Set per platform in Player Settings.
|
|
247
|
+
- **Player Settings:** product/company name, bundle identifier, icons, orientation, API compatibility
|
|
248
|
+
level (`.NET Standard 2.1` default), managed stripping. **2D vs 3D** is a template choice, not a
|
|
249
|
+
different build path.
|
|
250
|
+
- WebGL/mobile specifics and the shipping checklist: `references/build-and-platforms.md` + `gamedev-shipping`.
|
|
251
|
+
|
|
252
|
+
## Guardrails / gotchas
|
|
253
|
+
|
|
254
|
+
- `==`/`!= null` on a destroyed `UnityEngine.Object` works (overloaded), but `?.` and cached refs treat
|
|
255
|
+
a destroyed object as non-null. Re-check with `if (obj)` after possible destruction.
|
|
256
|
+
- Don't mix input systems: with `PlayerInput`, don't also `Input.GetKey` — in "New" mode legacy calls throw.
|
|
257
|
+
- One `Rigidbody` per body (child colliders fine); non-uniform scale breaks physics bodies.
|
|
258
|
+
- Coroutines/`InvokeRepeating` stop on `SetActive(false)`; async `Task`s keep running unless cancelled.
|
|
259
|
+
- No allocation (`new`, LINQ, boxing) in `Update`/`FixedUpdate` hot paths.
|
|
260
|
+
|
|
261
|
+
## Related skills
|
|
262
|
+
|
|
263
|
+
- `gamedev-multiplayer` — networking/netcode (Netcode for GameObjects); this skill hands off the wire.
|
|
264
|
+
- `gamedev-physics` — deep physics tuning (joints, solver, determinism) beyond "put it in FixedUpdate".
|
|
265
|
+
- `gamedev-shaders` — Shader Graph / HLSL, URP/HDRP materials and rendering.
|
|
266
|
+
- `gamedev-pathing` — NavMesh, agents, steering, path solving.
|
|
267
|
+
- `gamedev-shipping` — store builds, signing, size budgets, platform certification.
|
|
268
|
+
- `godot` / `unreal` — the other engines; route Godot/GDScript and Unreal/Blueprint/C++ there.
|
|
269
|
+
|
|
270
|
+
## Checklist
|
|
271
|
+
|
|
272
|
+
- [ ] Confirmed the project's Unity version (`ProjectVersion.txt`); no year-based-LTS assumptions.
|
|
273
|
+
- [ ] No banned API emitted (`Input.GetAxis`, `UnityEngine.Networking`, `Resources.Load` for content,
|
|
274
|
+
`FindObjectOfType`, `WWW`, runtime `OnGUI`).
|
|
275
|
+
- [ ] `GetComponent` results cached in `Awake`; no string `Find` in `Update`.
|
|
276
|
+
- [ ] Physics in `FixedUpdate`; input read in `Update`; camera/tracking in `LateUpdate`.
|
|
277
|
+
- [ ] Every `OnEnable` subscription has a matching `OnDisable` unsubscription.
|
|
278
|
+
- [ ] `[SerializeField] private` + property used instead of bare `public` where encapsulation matters.
|
|
279
|
+
- [ ] New Input System used (actions/maps), not legacy polling; systems not mixed.
|
|
280
|
+
- [ ] Async uses `Awaitable` (or coroutine) with `destroyCancellationToken`; no double-await.
|
|
281
|
+
- [ ] Content via Addressables, not `Resources/`.
|
|
282
|
+
- [ ] Scenes registered in Build Profiles; async/additive loading where it avoids a hitch.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# unity evals
|
|
2
|
+
|
|
3
|
+
These cases assert the skill fires on Unity/C# engine work (MonoBehaviour lifecycle, prefabs,
|
|
4
|
+
ScriptableObjects, scenes, the new Input System, coroutines/async/Awaitable, Addressables, builds) and
|
|
5
|
+
that it defers correctly: pathfinding→gamedev-pathing, shaders→gamedev-shaders, netcode→gamedev-multiplayer,
|
|
6
|
+
Godot→godot, Unreal→unreal. Capability cases check current Unity 6 patterns (physics in FixedUpdate with
|
|
7
|
+
Rigidbody.MovePosition, new Input System over Input.GetAxis, Awaitable + destroyCancellationToken, no
|
|
8
|
+
double-await) rather than deprecated APIs.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
skill: unity
|
|
2
|
+
should_trigger:
|
|
3
|
+
- prompt: "My Unity player character teleports and jitters through walls when I move it with the arrow keys. Here's my MonoBehaviour."
|
|
4
|
+
why: "Physics-in-Update / setting transform on a Rigidbody — core lifecycle + FixedUpdate guidance this skill owns."
|
|
5
|
+
- prompt: "What's the difference between Awake and Start in Unity, and where should I grab my other components?"
|
|
6
|
+
why: "Directly the MonoBehaviour lifecycle section (Awake caches, Start does cross-object wiring)."
|
|
7
|
+
- prompt: "Help me convert my old Input.GetAxis(\"Horizontal\") movement to Unity's new Input System with an action map."
|
|
8
|
+
why: "Legacy→new Input System migration; ban-list + §6/input-system reference."
|
|
9
|
+
- prompt: "I want to store all my enemy stats (health, speed, damage) as data assets I can tweak in the Inspector. Best way in Unity?"
|
|
10
|
+
why: "ScriptableObject for data/config + [SerializeField] vs public + serialization rules."
|
|
11
|
+
- prompt: "How do I load a second Unity scene on top of the current one for my UI without unloading the level?"
|
|
12
|
+
why: "Scenes & additive loading (LoadSceneAsync + LoadSceneMode.Additive)."
|
|
13
|
+
- prompt: "Should I use a coroutine, async Task, or Awaitable for a 'wait 2 seconds then spawn' timer in Unity 6?"
|
|
14
|
+
why: "Coroutines vs async/await vs Awaitable decision — §7, including destroyCancellationToken."
|
|
15
|
+
- prompt: "Setting up multiplayer in Unity — I found UNet / UnityEngine.Networking tutorials, do they still work?"
|
|
16
|
+
why: "Version contract: UNet removed → Netcode for GameObjects; routes the wire itself onward but Unity owns the 'it's removed' fact."
|
|
17
|
+
should_not_trigger:
|
|
18
|
+
- prompt: "How do I write a NavMeshAgent that chases the player and avoids obstacles smoothly?"
|
|
19
|
+
route_to: "gamedev-pathing"
|
|
20
|
+
why: "Pathfinding/steering algorithms are the pathing skill; Unity only owns the component wiring."
|
|
21
|
+
- prompt: "Design a Shader Graph for a dissolving-enemy effect with an emissive edge in URP."
|
|
22
|
+
route_to: "gamedev-shaders"
|
|
23
|
+
why: "Shader/material authoring belongs to the shaders skill."
|
|
24
|
+
- prompt: "I'm making a game in Godot 4 with GDScript and my _ready() isn't firing."
|
|
25
|
+
route_to: "godot"
|
|
26
|
+
why: "Godot/GDScript engine — explicitly out of scope; route to godot."
|
|
27
|
+
- prompt: "In Unreal Engine 5 my Blueprint Actor won't replicate movement to clients."
|
|
28
|
+
route_to: "unreal"
|
|
29
|
+
why: "Unreal/Blueprint engine work — route to unreal."
|
|
30
|
+
- prompt: "Write the authoritative server tick and client-side prediction/reconciliation for our netcode."
|
|
31
|
+
route_to: "gamedev-multiplayer"
|
|
32
|
+
why: "Netcode protocol/authority design is the multiplayer skill; Unity stops at 'use Netcode for GameObjects'."
|
|
33
|
+
capability:
|
|
34
|
+
- scenario: "User asks how to move a Rigidbody with input from the new Input System without jitter, in Unity 6."
|
|
35
|
+
must_include:
|
|
36
|
+
- "reads input in Update (caches intent) but applies movement in FixedUpdate"
|
|
37
|
+
- "uses Rigidbody.MovePosition (or AddForce), not setting transform.position on the body"
|
|
38
|
+
- "uses the new Input System (InputAction / action map / ReadValue<Vector2>), not Input.GetAxis"
|
|
39
|
+
- scenario: "User asks whether to use a coroutine or async for a delayed spawn and how to make it stop when the object is destroyed."
|
|
40
|
+
must_include:
|
|
41
|
+
- "recommends Awaitable (or coroutine) over raw Task for Unity gameplay in Unity 6"
|
|
42
|
+
- "passes destroyCancellationToken to the Awaitable so it cancels on destroy"
|
|
43
|
+
- "warns never to await the same Awaitable instance twice (it is pooled)"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Build, platforms & player settings (Unity 6)
|
|
2
|
+
|
|
3
|
+
Reference: Unity Manual "Build Profiles", "Player Settings", "IL2CPP".
|
|
4
|
+
|
|
5
|
+
## Build Profiles (Unity 6) — replaces the old Build Settings window
|
|
6
|
+
|
|
7
|
+
`File → Build Profiles`. A **Build Profile** is a saved, per-platform configuration:
|
|
8
|
+
- **Scene List** — which scenes are included and their build index (index 0 = first/boot scene). Scenes
|
|
9
|
+
not in the list can only be loaded Additively if already present, so register everything you load.
|
|
10
|
+
- **Target platform & architecture** — Windows/macOS/Linux, Android, iOS, WebGL, consoles.
|
|
11
|
+
- **Overrides** — a profile can override Player Settings (e.g. a "Demo" profile with a different bundle id).
|
|
12
|
+
|
|
13
|
+
`Shared Settings` hold the defaults; each profile diffs from them. Build with `Build` or `Build And Run`.
|
|
14
|
+
Headless/CI builds go through `BuildPipeline.BuildPlayer` in an editor script.
|
|
15
|
+
|
|
16
|
+
## Scripting backend: IL2CPP vs Mono
|
|
17
|
+
|
|
18
|
+
`Player Settings → Configuration → Scripting Backend`:
|
|
19
|
+
|
|
20
|
+
| | IL2CPP | Mono |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| How | C# → IL → C++ → native (AOT) | JIT at runtime |
|
|
23
|
+
| Platforms | required for iOS, WebGL, consoles; available desktop/Android | Editor + desktop + Android |
|
|
24
|
+
| Runtime speed | faster | slower |
|
|
25
|
+
| Build time | slower | faster (good for iteration) |
|
|
26
|
+
| Reverse-engineering | harder | easier |
|
|
27
|
+
| Reflection/`dynamic` | AOT limits (no runtime codegen; `System.Reflection.Emit` unsupported) | full |
|
|
28
|
+
|
|
29
|
+
Ship production builds on **IL2CPP**; iterate in the Editor (always Mono/interpreted). IL2CPP + AOT means
|
|
30
|
+
generic code reached only via reflection can be stripped — see managed stripping below.
|
|
31
|
+
|
|
32
|
+
## Player Settings essentials
|
|
33
|
+
|
|
34
|
+
- **Identity**: Company Name, Product Name, **bundle identifier** (`com.company.game` — must match store
|
|
35
|
+
listing), version + build/bundle number.
|
|
36
|
+
- **Icons & splash**, default orientation (mobile), resolution/presentation.
|
|
37
|
+
- **API Compatibility Level**: `.NET Standard 2.1` (default, smaller) vs `.NET Framework` (broader API,
|
|
38
|
+
larger). Prefer Standard unless a dependency needs Framework.
|
|
39
|
+
- **Managed Stripping Level** (`Minimal`/`Low`/`Medium`/`High`): strips unused IL to shrink builds. High
|
|
40
|
+
can strip types only used via reflection/serialization — preserve them with a `link.xml` or
|
|
41
|
+
`[Preserve]`.
|
|
42
|
+
- **Graphics APIs** per platform (Vulkan/Metal/D3D12/GLES3/WebGPU), color space (Linear recommended).
|
|
43
|
+
|
|
44
|
+
## Platform quick-notes
|
|
45
|
+
|
|
46
|
+
- **WebGL**: IL2CPP only; **no multithreading by default** (so `System.Threading`/most `Task`
|
|
47
|
+
parallelism is unavailable — `Awaitable` frame awaits are fine); no synchronous file I/O; build size
|
|
48
|
+
and memory matter; use compression (Brotli/Gzip) + a server that serves the right headers.
|
|
49
|
+
- **Android**: set target/min SDK, choose ARM64 (required for Play Store), build **AAB** for the store
|
|
50
|
+
(APK for sideload). Configure keystore signing.
|
|
51
|
+
- **iOS**: Unity emits an Xcode project; sign & archive in Xcode. IL2CPP + ARM64.
|
|
52
|
+
- **Desktop**: simplest; Mono or IL2CPP.
|
|
53
|
+
|
|
54
|
+
## Rendering pipeline choice (affects builds & shaders)
|
|
55
|
+
|
|
56
|
+
- **URP** (Universal RP) — default for most 2D/3D projects, scales phone→desktop.
|
|
57
|
+
- **HDRP** — high-end desktop/console visuals.
|
|
58
|
+
- **Built-in** — legacy; new projects should pick URP/HDRP.
|
|
59
|
+
|
|
60
|
+
Pipeline choice changes materials and shader authoring — see the `gamedev-shaders` skill.
|
|
61
|
+
|
|
62
|
+
## Handoff
|
|
63
|
+
|
|
64
|
+
Store submission, signing, size budgets, certification, and release ops belong to the `gamedev-shipping`
|
|
65
|
+
skill. This reference stops at producing a correct platform build from the Editor.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Input System (new) — setup, patterns, migration
|
|
2
|
+
|
|
3
|
+
Package: `com.unity.inputsystem`. Enabled by default in Unity 6. Device-agnostic, event-driven,
|
|
4
|
+
supports rebinding, composites, local multiplayer, and touch. Reference: Unity Input System package
|
|
5
|
+
manual.
|
|
6
|
+
|
|
7
|
+
## Project mode
|
|
8
|
+
|
|
9
|
+
`Edit → Project Settings → Player → Active Input Handling`:
|
|
10
|
+
- **Input System Package (New)** — legacy `Input.*` calls throw. Recommended for new projects.
|
|
11
|
+
- **Both** — new + legacy coexist (migration only; avoid mixing per-feature).
|
|
12
|
+
- **Input Manager (Old)** — legacy only. Do not target for new work.
|
|
13
|
+
|
|
14
|
+
Unity 6 also has **Project-wide Actions** (`Edit → Project Settings → Input System Package`): a default
|
|
15
|
+
`InputActionAsset` shared across the whole project, reachable via `InputSystem.actions`.
|
|
16
|
+
|
|
17
|
+
## Anatomy
|
|
18
|
+
|
|
19
|
+
- **Input Action Asset** (`.inputactions`): the container. Enable "Generate C# Class" in its importer to
|
|
20
|
+
get a strongly-typed wrapper (e.g. `InputSystem_Actions`).
|
|
21
|
+
- **Action Map**: a group of actions active together — e.g. "Player", "UI", "Vehicle". Enable/disable
|
|
22
|
+
maps to switch context (`_controls.Player.Disable(); _controls.UI.Enable();`).
|
|
23
|
+
- **Action**: a named input with a **type**:
|
|
24
|
+
- *Value* (continuous, e.g. `Vector2` Move) — `performed` fires on change, `ReadValue<T>()`.
|
|
25
|
+
- *Button* (Jump, Fire) — `started` / `performed` / `canceled` phases.
|
|
26
|
+
- *Pass-Through* (raw device, every event).
|
|
27
|
+
- **Binding**: the physical control → action. **Composite** bindings combine controls, e.g. a "2D Vector"
|
|
28
|
+
composite maps W/A/S/D to a single `Vector2`. **Control schemes** group bindings per device set
|
|
29
|
+
(Keyboard&Mouse, Gamepad).
|
|
30
|
+
|
|
31
|
+
## Three ways to consume input
|
|
32
|
+
|
|
33
|
+
### 1. Generated C# class (recommended for a single player)
|
|
34
|
+
|
|
35
|
+
```csharp
|
|
36
|
+
using UnityEngine.InputSystem;
|
|
37
|
+
|
|
38
|
+
public sealed class PlayerController : MonoBehaviour
|
|
39
|
+
{
|
|
40
|
+
InputSystem_Actions _controls;
|
|
41
|
+
Vector2 _move;
|
|
42
|
+
|
|
43
|
+
void Awake() => _controls = new InputSystem_Actions();
|
|
44
|
+
void OnEnable()
|
|
45
|
+
{
|
|
46
|
+
_controls.Player.Enable();
|
|
47
|
+
_controls.Player.Move.performed += OnMove;
|
|
48
|
+
_controls.Player.Move.canceled += OnMove;
|
|
49
|
+
_controls.Player.Jump.performed += _ => Jump();
|
|
50
|
+
}
|
|
51
|
+
void OnDisable()
|
|
52
|
+
{
|
|
53
|
+
_controls.Player.Move.performed -= OnMove;
|
|
54
|
+
_controls.Player.Move.canceled -= OnMove;
|
|
55
|
+
_controls.Player.Disable();
|
|
56
|
+
}
|
|
57
|
+
void OnDestroy() => _controls.Dispose(); // it owns native resources
|
|
58
|
+
void OnMove(InputAction.CallbackContext ctx) => _move = ctx.ReadValue<Vector2>();
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 2. Polling (when event-driven feels heavy)
|
|
63
|
+
|
|
64
|
+
```csharp
|
|
65
|
+
Vector2 move = _controls.Player.Move.ReadValue<Vector2>();
|
|
66
|
+
bool jumped = _controls.Player.Jump.WasPressedThisFrame(); // edge-triggered, read in Update
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 3. `PlayerInput` component (fastest wiring, local multiplayer)
|
|
70
|
+
|
|
71
|
+
Attach `PlayerInput`, assign the action asset, pick a **Behavior**:
|
|
72
|
+
- *Send Messages* / *Broadcast Messages* — calls `OnMove(InputValue)` etc. by name.
|
|
73
|
+
- *Invoke Unity Events* — wire in the Inspector.
|
|
74
|
+
- *Invoke C# Events* — subscribe in code.
|
|
75
|
+
|
|
76
|
+
For local co-op, `PlayerInputManager` spawns a `PlayerInput` per joined device, isolating each player's
|
|
77
|
+
action instance and pairing devices automatically.
|
|
78
|
+
|
|
79
|
+
## Rebinding at runtime
|
|
80
|
+
|
|
81
|
+
```csharp
|
|
82
|
+
var rebind = _controls.Player.Jump.PerformInteractiveRebinding()
|
|
83
|
+
.WithControlsExcluding("Mouse")
|
|
84
|
+
.OnComplete(op => { op.Dispose(); SaveBindings(); })
|
|
85
|
+
.Start();
|
|
86
|
+
// Persist: string json = _controls.asset.SaveBindingOverridesAsJson();
|
|
87
|
+
// Restore: _controls.asset.LoadBindingOverridesFromJson(json);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Migration from legacy
|
|
91
|
+
|
|
92
|
+
| Legacy | New Input System |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| `Input.GetAxis("Horizontal")` | Move action (Value/`Vector2`) → `ReadValue<Vector2>().x` |
|
|
95
|
+
| `Input.GetButtonDown("Jump")` | Jump action (Button) → `WasPressedThisFrame()` or `performed` |
|
|
96
|
+
| `Input.GetKey(KeyCode.E)` | action bound to `<Keyboard>/e` → `IsPressed()` |
|
|
97
|
+
| `Input.mousePosition` | `Mouse.current.position.ReadValue()` |
|
|
98
|
+
| `Input.GetMouseButtonDown(0)` | `Mouse.current.leftButton.wasPressedThisFrame` |
|
|
99
|
+
| `Input.touchCount` / `Input.GetTouch` | `Touchscreen.current` / Enhanced Touch API |
|
|
100
|
+
|
|
101
|
+
Do not leave `Input.*` polling alongside new-system actions — in "New" mode the legacy calls throw, and
|
|
102
|
+
in "Both" mode you double-handle the same physical input.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# MonoBehaviour lifecycle — deep dive (Unity 6)
|
|
2
|
+
|
|
3
|
+
Full execution order for a `MonoBehaviour`, and the exact reason each callback exists. Reference:
|
|
4
|
+
Unity Manual "Order of execution for event functions".
|
|
5
|
+
|
|
6
|
+
## Initialization (once per object, in this order)
|
|
7
|
+
|
|
8
|
+
1. **`Awake`** — called when the script instance is loaded, **even if the component is disabled**, and
|
|
9
|
+
before any `Start`. Cache `GetComponent`/`TryGetComponent`, allocate internal state. Do NOT reach
|
|
10
|
+
into *other* objects here — their `Awake` may not have run yet.
|
|
11
|
+
2. **`OnEnable`** — every time the object/component becomes enabled (including re-enable). Subscribe to
|
|
12
|
+
C# events, register with managers, enable input actions. Must be mirrored by `OnDisable`.
|
|
13
|
+
3. **`Start`** — once, just before the first `Update`, and **only if the component is active**. Safe
|
|
14
|
+
place for cross-object wiring because every object's `Awake` has already run. If an object is created
|
|
15
|
+
disabled and never enabled, `Start` never runs.
|
|
16
|
+
|
|
17
|
+
Across a scene: all `Awake`s run, then all `OnEnable`s, then all `Start`s — so `Start` is your
|
|
18
|
+
"everyone exists now" hook.
|
|
19
|
+
|
|
20
|
+
## Physics loop (`FixedUpdate`) — 0..n times per frame
|
|
21
|
+
|
|
22
|
+
- Runs on a fixed timestep (`Time.fixedDeltaTime`, default 0.02s = 50 Hz). May run zero times (high FPS)
|
|
23
|
+
or several times (low FPS) per rendered frame.
|
|
24
|
+
- **All `Rigidbody` work goes here:** `AddForce`, `MovePosition`, `MoveRotation`, velocity changes.
|
|
25
|
+
Setting `transform.position` directly on a physics body fights the solver → jitter/tunneling.
|
|
26
|
+
- Do NOT read edge-triggered input here (`WasPressedThisFrame`) — you'll miss events. Read in `Update`,
|
|
27
|
+
store the intent, consume it in `FixedUpdate`.
|
|
28
|
+
- Collision/trigger callbacks (`OnCollisionEnter`, `OnTriggerEnter`, and their `Stay`/`Exit`, plus 2D
|
|
29
|
+
variants) fire from the physics step.
|
|
30
|
+
|
|
31
|
+
## Game logic loop (per frame)
|
|
32
|
+
|
|
33
|
+
4. **`Update`** — once per rendered frame. Input, timers, non-physics movement, state machines.
|
|
34
|
+
Frame-rate independent movement multiplies by `Time.deltaTime`.
|
|
35
|
+
5. **`LateUpdate`** — after every `Update` in the scene has run. Camera follow, look-at, IK, procedural
|
|
36
|
+
bone adjustments — anything that must read the *final* positions of objects that moved this frame.
|
|
37
|
+
|
|
38
|
+
## Rendering-adjacent (advanced)
|
|
39
|
+
|
|
40
|
+
- `OnPreCull`, `OnBecameVisible`/`OnBecameInvisible`, `OnWillRenderObject`, `OnRenderImage` (Built-in RP;
|
|
41
|
+
URP/HDRP use `RenderPipelineManager` callbacks / render features instead).
|
|
42
|
+
- `OnDrawGizmos` / `OnDrawGizmosSelected` — Editor scene-view debug drawing only.
|
|
43
|
+
- `OnGUI` — legacy IMGUI, called multiple times per frame; editor tooling only, never runtime gameplay.
|
|
44
|
+
|
|
45
|
+
## Teardown
|
|
46
|
+
|
|
47
|
+
6. **`OnDisable`** — when the object/component disables (and just before `OnDestroy`). Unsubscribe from
|
|
48
|
+
everything subscribed in `OnEnable`, disable input actions, stop coroutines you own. A missing
|
|
49
|
+
unsubscribe here is the #1 cause of leaks and "handler fired twice after re-enable".
|
|
50
|
+
7. **`OnDestroy`** — once, when the object is destroyed (or scene unloads / app quits). Release native
|
|
51
|
+
handles, dispose `IDisposable`s (`NativeArray`, `InputActionAsset` you `new`ed), final cleanup.
|
|
52
|
+
8. **`OnApplicationQuit`** / `OnApplicationPause` / `OnApplicationFocus` — app-level lifecycle for
|
|
53
|
+
save-on-quit and mobile pause handling.
|
|
54
|
+
|
|
55
|
+
## Coroutine yield timing (where a coroutine resumes)
|
|
56
|
+
|
|
57
|
+
| `yield return` | Resumes |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| `null` | next frame, after `Update` |
|
|
60
|
+
| `new WaitForSeconds(t)` | after `t` scaled seconds (affected by `Time.timeScale`) |
|
|
61
|
+
| `new WaitForSecondsRealtime(t)` | after `t` real seconds (ignores `timeScale`) |
|
|
62
|
+
| `new WaitForFixedUpdate()` | after the next physics step |
|
|
63
|
+
| `new WaitForEndOfFrame()` | after rendering, before present (good for screen capture) |
|
|
64
|
+
| `new WaitUntil(() => cond)` / `WaitWhile(...)` | when the predicate flips |
|
|
65
|
+
| another `IEnumerator` | when the nested coroutine completes |
|
|
66
|
+
|
|
67
|
+
Gotcha: `new WaitForSeconds(t)` allocates every call — cache the instance if you yield it in a loop, or
|
|
68
|
+
switch to `Awaitable.WaitForSecondsAsync`.
|
|
69
|
+
|
|
70
|
+
## Script execution order
|
|
71
|
+
|
|
72
|
+
If object A must initialize before object B, don't rely on scene order — set it in
|
|
73
|
+
`Project Settings → Script Execution Order`, or better, express the dependency explicitly (have B pull
|
|
74
|
+
what it needs in its own `Start`, or use an explicit init call). `[DefaultExecutionOrder(n)]` sets it
|
|
75
|
+
per-class in code.
|