添加 claude code game studios 到项目

This commit is contained in:
panw
2026-05-15 14:52:29 +08:00
parent dff559462d
commit a16fe4bff7
415 changed files with 78609 additions and 0 deletions

View 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

View 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

View 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