Skip to main content

unity

Expert game development with Unity - engine architecture, C# scripting, DOTS ECS, rendering (URP/HDRP), physics, animation, UI, asset pipeline, multiplayer, and performance.

معلومات المصدر

المستودع
j4flmao/agent-skills
آخر نشاط في المصدر
١٩ سبتمبر ٢٠٢٦ في ٠٣:١٩
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٢٧
التفرعات
١

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
unity
description
Expert game development with Unity - engine architecture, C# scripting, DOTS ECS, rendering (URP/HDRP), physics, animation, UI, asset pipeline, multiplayer, and performance.
# Unity Deep Engineering Guide Unity is a component-based game engine built around GameObjects, MonoBehaviours, and a C# scripting layer. Modern Unity adds Data-Oriented Technology Stack (DOTS/E.C.S.) and two Scriptable Render Pipelines (URP/HDRP). This guide covers how a lead engineer thinks about Unity: architecture, C# performance, data-oriented design, rendering, physics, multiplayer, and profiling. ## 1. Engine Architecture ``` Unity Player/Editor Application (UnityEngine) SceneManager -> load/unload Scenes (additive) GameObject (identity + transform) Component (MonoBehaviour, Renderer, Collider, Animator...) PlayerLoop: (fixed update order, engine-driven) ScriptableRunLoops -> custom systems injected Module systems: Physics (PhysX/Box2D), Audio (FMOD), UI (UGUI/UI Toolkit), Rendering (URP/HDRP/Built-in), Input (new Input System) ``` ### 1.1 The Player Loop & Update Order Within one frame Unity calls systems in a fixed order: ```csharp void Update() // per rendered frame void FixedUpdate() // fixed timestep: physics, network ticks (default 0.02s) void LateUpdate() // camera follow, post-movement ``` Rules: - **Never move Rigidbody in Update()**; move via `FixedUpdate` or use `rb.velocity` only in FixedUpdate. Changing `transform` in Update fights the physics solver. - Camera interpolation in LateUpdate. - Scene load is synchronous unless using `Addressables`/`SceneManager.LoadSceneAsync`. ### 1.2 Multiple Scenes (Additive Loading) - Split levels into persistent + gameplay scenes; stream with `LoadSceneAsync` + `AllowSceneActivation = false` to keep the load from blocking. - Use `SceneManager.MergeScenes` or DontDestroyOnLoad root object. ## 2. GameObject & Component Model ```csharp public class Health : MonoBehaviour { public int maxHp = 100; int current; void OnEnable() { /* add self to manager lists */ } void OnDisable() { /* remove self */ } } ``` ### 2.1 GetComponent Performance `GetComponent<T>()` per frame per object is a hot-path mistake: - Cache component references in `Awake()` once. - Prefer `TryGetComponent`. - `GetComponentsInChildren` only at load or on structural change. - Hot update loops use **managers** (single static list of registered components), not per-object `Find`. ### 2.2 FindObjectOfType / GameObject.Find These are O(n) with allocations. They MUST not run on the per-frame path. For singletons, register in `Awake`, destroy in `OnDestroy`: ```csharp public static GameManager I; // global accessor void Awake() { I = this; } void OnDestroy() { if (I == this) I = null; } ``` ## 3. The DOTS / ECS Stack Unity DOTS replaces MonoBehaviours with archetype-based ECS: ```csharp // Component - plain struct, no MonoBehaviour public struct Velocity : IComponentData { public float3 Value; } // System [BurstCompile] partial struct MoveSystem : ISystem { [BurstCompile] public void OnUpdate(ref SystemState state) { foreach (var (transform, v) in SystemAPI.Query<RefRW<LocalTransform>, RefRO<Velocity>>()) { transform.ValueRW.Position += v.ValueRO.Value * SystemAPI.Time.DeltaTime; } } } ``` - Entities stored in archetypes (SoA per component) → cache-friendly. - `Burst` + `Jobs` compiles to native SIMD-optimized code. - SubScene baking: author GameObject scenes → baked entities at build. ### When to use DOTS vs classic GameObjects | Need | Path | |------|------| | 1000s of agents, bullets, particles | DOTS/ECS + Burst + Jobs | | Rapid prototyping / small games | Classic GameObject/MonoBehaviours | | UI, gameplay narrative, inventory | Classic (UGUI) | | Massive open world streaming | DOTS SubScene streaming | ## 4. Rendering Pipelines ### 4.1 Choose the Pipeline | Pipeline | Use | |----------|-----| | Built-in | Legacy, quick prototypes, simple mobile games | | **URP** | Default for most new projects (PC+mobile), SRP Batcher optimal | | **HDRP** | Film-grade lighting: deferred, ray tracing, volumetrics, high-end PC/console | | `ScriptableRenderer` (custom) | You own pass ordering; use with `RenderGraph` | ### 4.2 URP vs HDRP in practice - URP: forward rendering, 2D lights, SRP batcher, simplified. - HDRP: deferred, clustered lighting, volumetric fog, SSR, RT reflections (DXR). - Both are `ScriptableRenderPipeline`; they run in the `Rendering.Update` player-loop phase. ### 4.3 Draw Call Reduction 1. **Enable SRP Batcher** (URP/HDRP property `UseSRPBatcher`) — batches dynamic shadows+lit objects with compatible materials. 2. **GPU instancing**: `Graphics.DrawMeshInstanced` for repeated meshes (grass, crowds, particles). 3. **Static batching**: mark static → combined at build. 4. **Addressables + SDF 2D**: not draw-call related, but stream textures to control bandwidth. 5. Minimize material variants (`KeywordEnum`, `MaterialPropertyBlock` for per-object color). 6. Bake lighting (Lightmapping) instead of dynamic. ### 4.4 Shader Lab & Shader Graph - Shader Graph (node-based) is preferred for artists; expose exposed properties only. - Hand-written shaders: write in HLSL; SRP uses `HLSLPROGRAM` blocks and `#pragma target` 3.0+. - Watch out: Unity editor implicit `#pragma multi_compile _ _ALPHATEST_ON`; use `#pragma shader_feature_local` to avoid variants. ## 5. Physics - Unity uses **PhysX** (3D) and **Box2D** (2D). - Fixed timestep at 0.02s (50Hz); fast small objects tunnel → use `Physics.Burst`/`Physics.Solver` or a dedicated CCD sensor. - Sleeping: overlapping static triggers should disable colliders (`isTrigger = true`) to avoid touches every frame. - Layers & matrix matter: `Physics.IgnoreLayerCollision(playerLayer, enemyLayer, true)` reduces contact generation. - `Physics.SyncTransforms()` forces syncing; avoid calling per-frame. ## 6. Animation & Timing - **Animator** state machine with transitions; avoid heavy tree layers per object. - `Time.deltaTime` may be 0 on pause; use `Time.unscaledDeltaTime` for UI. - Animation events are editor-time; use `OnAnimationEvent` or `AnimationEvent` binding. - For 100s of animating characters prefer playables or `AnimationUpdateMode` fixed with simple lerps. ## 7. UI (UGUI / UI Toolkit / IMGUI) - **UGUI** (Canvas): fine for HUD; keep panels/Canvas to 1-2, enable `Vertex Buffer` reuse, disable raycast on static. - **UI Toolkit** (new): UXML/USS, better for menus and editor tooling; runtime since 2023. - **IMGUI**: editor windows and debugging only, not runtime UI. - Rule: no layout rebuild per frame; cache `RectTransform`s, minify `GraphicRaycaster` blockers. ## 8. Asset Pipeline ### 8.1 Addressables Addressables = load by key, async, memory-managed: ```csharp Addressables.LoadAssetAsync<GameObject>("enemies/wolf").Completed += h => { var go = Instantiate(h.Result); go.AddComponent<DeferredUnload>(); }; Addressables.Release(handle); ``` - Use `AssetReference` fields instead of hardcoded strings. - Set `addressables` remote catalog for updates. - Remember: `Instantiate(referencedObject)` body must be released too. ### 8.2 Streaming & Background Loading - Texture streaming (`Texture2D.streamingEnabled`) or Addressables load in `OnTriggerEnter`. - Audio: `AudioClip.Create` streaming for ambience. - Never `Resources.Load` in Update; use `Resources.LoadAll` once. ## 9. Multiplayer (Netcode for GameObjects / Netcode Transport / UnityTransport) - Authoritative: server owns state; clients send inputs; interpolate snapshot positions. - `[ServerRpc]` from client to server; `[ClientRpc]` from server to clients. - Sim tick = fixed timestep; physics simulation server-side only; clients render interpolated states. - Use `NetworkVariable<T>` — beware of per-frame `NetworkVariable` writes (delta encode, avoid 60/s floats). - Prediction: `PredictedPlayer` pattern with client-side `NetworkTransform` interpolation. ## 10. Performance Rules (Lead Level) 1. **Profile first**: Unity Profiler + Burst metrics; GPU profiler (RenderDoc, GPUView). 2. `ExecuteInEditMode` scripts only where needed; keep editor-only work in `#if UNITY_EDITOR`. 3. Avoid `transform.position` in a loop (accessing Transform is cheap-ish, but allocations from `Find`/`GetComponentsInChildren` are not). 4. Garbage: minimize per-frame allocations; cache arrays; use `NativeArray`/`NativeList` in jobs. 5. Broke update: use `FixedUpdate` only for physics; game logic in `Update`. 6. Root motion vs scripted movement: profile `Animator` cost. 7. Hidden cost: `Camera.main` cached; avoid in Update. ### 10.1 Frame Budget Table Template | System | Budget (ms) @ 60fps | |--------|---------------------| | Simulation (Update) | 2.0 | | Physics (Fixed) | 2.0 | | Animation | 2.0 | | AI / NavMesh | 1.5 | | Rendering (CPU submit) | 3.0 | | Rendering (GPU) | 8.3–14.0 | | UI | 1.0 | | Netcode | 1.0 | | Misc / Driver | 2.0 | Total must fit in 16.6ms (or 1000/refresh). ## 11. Project Structure Convention ``` Assets/ Scripts/ # namespaces by system Scenes/ Prefabs/ Addressables/ # addressable groups Materials/ Textures/ Audio/ _BuildTools/ # editor scripts, CI .gitignore: Library/ Temp/ Logs/ UserSettings/ ``` Use `.asmdef` (assembly definition) per folder to speed up compile times and control references. ## 12. Anti-Patterns | Anti-pattern | Consequence | Fix | |--------------|-------------|-----| | `FindObjectOfType` in Update | GC spikes, slow | cache in Awake | | Rigidbody move in Update | physics jitter | FixedUpdate + rb.Move | | Per-frame allocations (strings) | GC pauses | string builders, pooling | | Resources.Load in loop | load spikes | Addressables + cache | | One Canvas for everything | layout rebuild | split by update frequency | | Scripts in Editor without serialization | lost state | `[SerializedField]` | | Not using .asmdef | long compile | per-system asmdefs | | Physics without layer matrix | wasted contacts | `IgnoreLayerCollision` | ## 13. When to NOT Use Unity - Native console/PC-only huge world with full control → custom engine + Vulkan (see `skills/game/game-development/vulkan/SKILL.md`). - Web "tiny" canvas game → Engines like Phaser or vanilla canvas might be lighter. - Deep customization of renderer required beyond URP/HDRP budget → engine-level control required. - For ECS patterns independent of engine, see `skills/game/game-engine/ecs-pattern/SKILL.md`. ## 14. References - `skills/game/game-development/unity-csharp/SKILL.md` — Unity C# scripting and DOTS internals - `skills/game/game-engine/ecs-pattern/references/unity-dots-in-practice.md` — DOTS in real projects - `skills/game/game-engine/patterns/references/game-loop-and-timestep.md` — update timing patterns - `skills/game/multiplayer-netcode/SKILL.md` — netcode patterns & prediction - `skills/game/game-development/physics-engine/SKILL.md` — physics internals used by engines
عرض على GitHub