@musashishao/agent-kit 1.8.1 → 1.9.0
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/.agent/agents/ai-architect.md +39 -0
- package/.agent/agents/cloud-engineer.md +39 -0
- package/.agent/agents/game-asset-curator.md +317 -0
- package/.agent/agents/game-developer.md +190 -89
- package/.agent/agents/game-narrative-designer.md +310 -0
- package/.agent/agents/game-qa-agent.md +441 -0
- package/.agent/agents/marketing-specialist.md +41 -0
- package/.agent/agents/penetration-tester.md +15 -1
- package/.agent/rules/CODEX.md +26 -2
- package/.agent/rules/GEMINI.md +7 -5
- package/.agent/rules/REFERENCE.md +92 -2
- package/.agent/scripts/ak_cli.py +1 -1
- package/.agent/scripts/localize_workflows.py +54 -0
- package/.agent/scripts/memory_manager.py +24 -1
- package/.agent/skills/3d-web-experience/SKILL.md +386 -0
- package/.agent/skills/DEPENDENCIES.md +54 -0
- package/.agent/skills/ab-test-setup/SKILL.md +77 -0
- package/.agent/skills/active-directory-attacks/SKILL.md +59 -0
- package/.agent/skills/agent-evaluation/SKILL.md +430 -0
- package/.agent/skills/agent-memory-systems/SKILL.md +426 -0
- package/.agent/skills/agent-tool-builder/SKILL.md +139 -0
- package/.agent/skills/ai-agents-architect/SKILL.md +115 -0
- package/.agent/skills/ai-product/SKILL.md +86 -0
- package/.agent/skills/ai-wrapper-product/SKILL.md +90 -0
- package/.agent/skills/analytics-tracking/SKILL.md +88 -0
- package/.agent/skills/api-fuzzing-bug-bounty/SKILL.md +66 -0
- package/.agent/skills/app-store-optimization/SKILL.md +66 -0
- package/.agent/skills/autonomous-agent-patterns/SKILL.md +414 -0
- package/.agent/skills/aws-penetration-testing/SKILL.md +50 -0
- package/.agent/skills/aws-serverless/SKILL.md +327 -0
- package/.agent/skills/azure-functions/SKILL.md +340 -0
- package/.agent/skills/broken-authentication/SKILL.md +53 -0
- package/.agent/skills/browser-automation/SKILL.md +408 -0
- package/.agent/skills/browser-extension-builder/SKILL.md +422 -0
- package/.agent/skills/bullmq-specialist/SKILL.md +424 -0
- package/.agent/skills/bun-development/SKILL.md +386 -0
- package/.agent/skills/burp-suite-testing/SKILL.md +60 -0
- package/.agent/skills/clerk-auth/SKILL.md +432 -0
- package/.agent/skills/cloud-penetration-testing/SKILL.md +51 -0
- package/.agent/skills/copywriting/SKILL.md +66 -0
- package/.agent/skills/crewai/SKILL.md +470 -0
- package/.agent/skills/discord-bot-architect/SKILL.md +447 -0
- package/.agent/skills/email-sequence/SKILL.md +73 -0
- package/.agent/skills/ethical-hacking-methodology/SKILL.md +67 -0
- package/.agent/skills/firebase/SKILL.md +377 -0
- package/.agent/skills/game-development/godot-expert/SKILL.md +462 -0
- package/.agent/skills/game-development/npc-ai-integration/SKILL.md +110 -0
- package/.agent/skills/game-development/procedural-generation/SKILL.md +168 -0
- package/.agent/skills/game-development/unity-integration/SKILL.md +358 -0
- package/.agent/skills/game-development/webgpu-shading/SKILL.md +209 -0
- package/.agent/skills/gcp-cloud-run/SKILL.md +358 -0
- package/.agent/skills/graphql/SKILL.md +492 -0
- package/.agent/skills/idor-testing/SKILL.md +64 -0
- package/.agent/skills/inngest/SKILL.md +128 -0
- package/.agent/skills/langfuse/SKILL.md +415 -0
- package/.agent/skills/langgraph/SKILL.md +360 -0
- package/.agent/skills/launch-strategy/SKILL.md +68 -0
- package/.agent/skills/linux-privilege-escalation/SKILL.md +62 -0
- package/.agent/skills/llm-app-patterns/SKILL.md +367 -0
- package/.agent/skills/marketing-ideas/SKILL.md +66 -0
- package/.agent/skills/metasploit-framework/SKILL.md +60 -0
- package/.agent/skills/micro-saas-launcher/SKILL.md +93 -0
- package/.agent/skills/neon-postgres/SKILL.md +339 -0
- package/.agent/skills/paid-ads/SKILL.md +64 -0
- package/.agent/skills/supabase-integration/SKILL.md +411 -0
- package/.agent/workflows/ai-agent.md +36 -0
- package/.agent/workflows/autofix.md +1 -0
- package/.agent/workflows/brainstorm.md +1 -0
- package/.agent/workflows/context.md +1 -0
- package/.agent/workflows/create.md +1 -0
- package/.agent/workflows/dashboard.md +1 -0
- package/.agent/workflows/debug.md +1 -0
- package/.agent/workflows/deploy.md +1 -0
- package/.agent/workflows/enhance.md +1 -0
- package/.agent/workflows/game-prototype.md +154 -0
- package/.agent/workflows/marketing.md +37 -0
- package/.agent/workflows/next.md +1 -0
- package/.agent/workflows/orchestrate.md +1 -0
- package/.agent/workflows/pentest.md +37 -0
- package/.agent/workflows/plan.md +1 -0
- package/.agent/workflows/preview.md +2 -1
- package/.agent/workflows/quality.md +1 -0
- package/.agent/workflows/saas.md +36 -0
- package/.agent/workflows/spec.md +1 -0
- package/.agent/workflows/status.md +1 -0
- package/.agent/workflows/test.md +1 -0
- package/.agent/workflows/ui-ux-pro-max.md +1 -0
- package/README.md +52 -24
- package/bin/cli.js +68 -3
- package/docs/CHANGELOG_AI_INFRA.md +30 -0
- package/docs/MIGRATION_GUIDE_V1.9.md +55 -0
- package/package.json +1 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: procedural-generation
|
|
3
|
+
description: Procedural content generation for games. Algorithms for dungeons, terrain, items, and narratives.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Grep
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Procedural Generation Skill
|
|
8
|
+
|
|
9
|
+
> Creating infinite content through algorithms.
|
|
10
|
+
|
|
11
|
+
## When to Use
|
|
12
|
+
|
|
13
|
+
- Generating dungeons, levels, or terrain
|
|
14
|
+
- Creating random items, loot, or enemies
|
|
15
|
+
- Building procedural narratives
|
|
16
|
+
- Implementing roguelike mechanics
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Algorithm Selection
|
|
21
|
+
|
|
22
|
+
| Algorithm | Best For | Complexity |
|
|
23
|
+
|-----------|----------|------------|
|
|
24
|
+
| **Perlin/Simplex Noise** | Terrain, textures | Low |
|
|
25
|
+
| **BSP (Binary Space)** | Room-based dungeons | Medium |
|
|
26
|
+
| **Cellular Automata** | Cave systems | Low |
|
|
27
|
+
| **WFC** | Tile-based levels | High |
|
|
28
|
+
| **L-Systems** | Plants, fractals | Medium |
|
|
29
|
+
| **Markov Chains** | Names, text, music | Low |
|
|
30
|
+
| **Grammar-Based** | Quests, dialogue | Medium |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Dungeon Generation (BSP)
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
class BSPDungeon:
|
|
38
|
+
def __init__(self, width, height, min_room=6):
|
|
39
|
+
self.width = width
|
|
40
|
+
self.height = height
|
|
41
|
+
self.min_room = min_room
|
|
42
|
+
self.rooms = []
|
|
43
|
+
|
|
44
|
+
def generate(self):
|
|
45
|
+
root = {"x": 0, "y": 0, "w": self.width, "h": self.height}
|
|
46
|
+
self._split(root)
|
|
47
|
+
self._create_rooms(root)
|
|
48
|
+
self._connect_rooms()
|
|
49
|
+
return self.rooms
|
|
50
|
+
|
|
51
|
+
def _split(self, node, depth=0):
|
|
52
|
+
if depth > 4 or node["w"] < self.min_room * 2:
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
if random.random() > 0.5: # Horizontal
|
|
56
|
+
split = random.randint(self.min_room, node["h"] - self.min_room)
|
|
57
|
+
node["left"] = {"x": node["x"], "y": node["y"], "w": node["w"], "h": split}
|
|
58
|
+
node["right"] = {"x": node["x"], "y": node["y"] + split, "w": node["w"], "h": node["h"] - split}
|
|
59
|
+
else: # Vertical
|
|
60
|
+
split = random.randint(self.min_room, node["w"] - self.min_room)
|
|
61
|
+
node["left"] = {"x": node["x"], "y": node["y"], "w": split, "h": node["h"]}
|
|
62
|
+
node["right"] = {"x": node["x"] + split, "y": node["y"], "w": node["w"] - split, "h": node["h"]}
|
|
63
|
+
|
|
64
|
+
self._split(node.get("left"), depth + 1)
|
|
65
|
+
self._split(node.get("right"), depth + 1)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Terrain Generation (Noise)
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
import noise
|
|
74
|
+
|
|
75
|
+
def generate_heightmap(width, height, scale=100, octaves=6):
|
|
76
|
+
heightmap = []
|
|
77
|
+
for y in range(height):
|
|
78
|
+
row = []
|
|
79
|
+
for x in range(width):
|
|
80
|
+
value = noise.pnoise2(
|
|
81
|
+
x / scale, y / scale,
|
|
82
|
+
octaves=octaves,
|
|
83
|
+
persistence=0.5,
|
|
84
|
+
lacunarity=2.0
|
|
85
|
+
)
|
|
86
|
+
row.append((value + 1) / 2) # Normalize to 0-1
|
|
87
|
+
heightmap.append(row)
|
|
88
|
+
return heightmap
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Item Generation (Weighted Random)
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
ITEM_TEMPLATES = {
|
|
97
|
+
"weapon": {
|
|
98
|
+
"prefixes": ["Rusty", "Sharp", "Ancient", "Cursed"],
|
|
99
|
+
"bases": ["Sword", "Axe", "Dagger", "Spear"],
|
|
100
|
+
"suffixes": ["of Fire", "of Ice", "of Speed", "of Power"]
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
def generate_item(item_type, rarity):
|
|
105
|
+
template = ITEM_TEMPLATES[item_type]
|
|
106
|
+
|
|
107
|
+
name_parts = [random.choice(template["bases"])]
|
|
108
|
+
|
|
109
|
+
if rarity >= 2:
|
|
110
|
+
name_parts.insert(0, random.choice(template["prefixes"]))
|
|
111
|
+
if rarity >= 3:
|
|
112
|
+
name_parts.append(random.choice(template["suffixes"]))
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
"name": " ".join(name_parts),
|
|
116
|
+
"damage": 10 + rarity * 5 + random.randint(0, 10),
|
|
117
|
+
"rarity": rarity
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Wave Function Collapse (Concept)
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
Constraints → Propagation → Collapse → Repeat
|
|
127
|
+
|
|
128
|
+
1. Start with superposition (all tiles possible everywhere)
|
|
129
|
+
2. Pick cell with lowest entropy (fewest options)
|
|
130
|
+
3. Collapse to single tile (weighted random)
|
|
131
|
+
4. Propagate constraints to neighbors
|
|
132
|
+
5. Repeat until all cells collapsed or contradiction
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Seeds & Reproducibility
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
def generate_world(seed: int):
|
|
141
|
+
random.seed(seed)
|
|
142
|
+
np.random.seed(seed)
|
|
143
|
+
|
|
144
|
+
# All RNG calls now deterministic
|
|
145
|
+
terrain = generate_terrain()
|
|
146
|
+
dungeons = generate_dungeons()
|
|
147
|
+
items = generate_items()
|
|
148
|
+
|
|
149
|
+
return World(terrain, dungeons, items, seed=seed)
|
|
150
|
+
|
|
151
|
+
# Same seed = same world
|
|
152
|
+
world1 = generate_world(12345)
|
|
153
|
+
world2 = generate_world(12345)
|
|
154
|
+
assert world1 == world2
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Anti-Patterns
|
|
160
|
+
|
|
161
|
+
| ❌ Don't | ✅ Do |
|
|
162
|
+
|----------|-------|
|
|
163
|
+
| Pure random | Seed-based reproducibility |
|
|
164
|
+
| Generate at runtime | Pre-generate or cache |
|
|
165
|
+
| No validation | Playtest generated content |
|
|
166
|
+
| Ignore edge cases | Handle impossible states |
|
|
167
|
+
|
|
168
|
+
> **Remember:** Procedural generation creates possibility space. Design constraints create meaning.
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: unity-integration
|
|
3
|
+
description: Unity Engine expert skill covering C# scripting, DOTS/ECS, Unity 6 features, XR development, and AI integration with ML-Agents and Sentis. Use when developing games with Unity.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Grep, WebSearch
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Unity Integration Skill
|
|
8
|
+
|
|
9
|
+
> Expert-level Unity development patterns for Unity 6 (2025+).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## When to Use This Skill
|
|
14
|
+
|
|
15
|
+
- Building games with Unity Engine
|
|
16
|
+
- Implementing Unity-specific patterns (C#, MonoBehaviour, DOTS)
|
|
17
|
+
- Optimizing Unity performance
|
|
18
|
+
- Integrating AI with ML-Agents or Sentis
|
|
19
|
+
- Developing XR experiences with Unity XR
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Unity 6 Key Features (2025)
|
|
24
|
+
|
|
25
|
+
| Feature | Description | Use When |
|
|
26
|
+
|---------|-------------|----------|
|
|
27
|
+
| **GPU Resident Drawer** | Automatic GPU instancing | Large open worlds |
|
|
28
|
+
| **Multiplayer Center** | Netcode setup wizard | Multiplayer games |
|
|
29
|
+
| **Sentis** | On-device AI inference | ML in production |
|
|
30
|
+
| **Adaptive Probe Volumes** | Dynamic GI for open worlds | Large outdoor scenes |
|
|
31
|
+
| **DOTS Entities 1.0** | Stable ECS | Performance-critical |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Architecture Patterns
|
|
36
|
+
|
|
37
|
+
### 1. MonoBehaviour vs DOTS Decision
|
|
38
|
+
|
|
39
|
+
| Factor | MonoBehaviour | DOTS/ECS |
|
|
40
|
+
|--------|---------------|----------|
|
|
41
|
+
| **Entity Count** | < 1000 | > 1000 |
|
|
42
|
+
| **Team Experience** | Any | Advanced |
|
|
43
|
+
| **Development Speed** | Fast | Slower |
|
|
44
|
+
| **Performance** | Good | Excellent |
|
|
45
|
+
| **Debugging** | Easy | Complex |
|
|
46
|
+
|
|
47
|
+
**Recommendation**: Start with MonoBehaviour. Migrate to DOTS only when profiler shows need.
|
|
48
|
+
|
|
49
|
+
### 2. Recommended Project Structure
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
Assets/
|
|
53
|
+
├── _Project/ # Your game code
|
|
54
|
+
│ ├── Scripts/
|
|
55
|
+
│ │ ├── Core/ # Singletons, managers
|
|
56
|
+
│ │ ├── Gameplay/ # Game-specific logic
|
|
57
|
+
│ │ ├── UI/ # UI controllers
|
|
58
|
+
│ │ └── Utils/ # Helper classes
|
|
59
|
+
│ ├── Prefabs/
|
|
60
|
+
│ ├── Scenes/
|
|
61
|
+
│ └── ScriptableObjects/
|
|
62
|
+
├── Art/ # Art assets
|
|
63
|
+
├── Audio/ # Audio assets
|
|
64
|
+
├── Plugins/ # Third-party
|
|
65
|
+
└── Resources/ # Runtime-loaded (use sparingly)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 3. Dependency Injection Pattern
|
|
69
|
+
|
|
70
|
+
```csharp
|
|
71
|
+
// Instead of FindObjectOfType or Singletons, use explicit injection
|
|
72
|
+
public class PlayerController : MonoBehaviour
|
|
73
|
+
{
|
|
74
|
+
[SerializeField] private GameManager _gameManager;
|
|
75
|
+
[SerializeField] private AudioManager _audioManager;
|
|
76
|
+
|
|
77
|
+
// Dependencies are visible in Inspector
|
|
78
|
+
// Testable and mockable
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## C# Best Practices for Unity
|
|
85
|
+
|
|
86
|
+
### 1. Avoid Allocations in Update
|
|
87
|
+
|
|
88
|
+
```csharp
|
|
89
|
+
// ❌ BAD - Allocates every frame
|
|
90
|
+
void Update()
|
|
91
|
+
{
|
|
92
|
+
var enemies = FindObjectsOfType<Enemy>();
|
|
93
|
+
string debug = $"Enemies: {enemies.Length}";
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ✅ GOOD - Cache and reuse
|
|
97
|
+
private Enemy[] _enemyCache = new Enemy[100];
|
|
98
|
+
private StringBuilder _sb = new StringBuilder();
|
|
99
|
+
|
|
100
|
+
void Update()
|
|
101
|
+
{
|
|
102
|
+
int count = Physics.OverlapSphereNonAlloc(pos, radius, _enemyCache);
|
|
103
|
+
_sb.Clear();
|
|
104
|
+
_sb.Append("Enemies: ").Append(count);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### 2. Object Pooling
|
|
109
|
+
|
|
110
|
+
```csharp
|
|
111
|
+
public class BulletPool : MonoBehaviour
|
|
112
|
+
{
|
|
113
|
+
[SerializeField] private GameObject _bulletPrefab;
|
|
114
|
+
[SerializeField] private int _poolSize = 100;
|
|
115
|
+
|
|
116
|
+
private Queue<GameObject> _pool = new Queue<GameObject>();
|
|
117
|
+
|
|
118
|
+
void Awake()
|
|
119
|
+
{
|
|
120
|
+
for (int i = 0; i < _poolSize; i++)
|
|
121
|
+
{
|
|
122
|
+
var bullet = Instantiate(_bulletPrefab);
|
|
123
|
+
bullet.SetActive(false);
|
|
124
|
+
_pool.Enqueue(bullet);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public GameObject Get()
|
|
129
|
+
{
|
|
130
|
+
if (_pool.Count == 0) return Instantiate(_bulletPrefab);
|
|
131
|
+
var bullet = _pool.Dequeue();
|
|
132
|
+
bullet.SetActive(true);
|
|
133
|
+
return bullet;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
public void Return(GameObject bullet)
|
|
137
|
+
{
|
|
138
|
+
bullet.SetActive(false);
|
|
139
|
+
_pool.Enqueue(bullet);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 3. Event System (Zero Allocation)
|
|
145
|
+
|
|
146
|
+
```csharp
|
|
147
|
+
// Define events with Action instead of UnityEvent for perf-critical paths
|
|
148
|
+
public static class GameEvents
|
|
149
|
+
{
|
|
150
|
+
public static event Action<int> OnScoreChanged;
|
|
151
|
+
public static event Action OnPlayerDied;
|
|
152
|
+
|
|
153
|
+
public static void ScoreChanged(int newScore) => OnScoreChanged?.Invoke(newScore);
|
|
154
|
+
public static void PlayerDied() => OnPlayerDied?.Invoke();
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Unity ML-Agents Integration
|
|
161
|
+
|
|
162
|
+
### Setup
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Install ML-Agents
|
|
166
|
+
pip install mlagents
|
|
167
|
+
|
|
168
|
+
# In Unity Package Manager, add:
|
|
169
|
+
# com.unity.ml-agents
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Basic Agent
|
|
173
|
+
|
|
174
|
+
```csharp
|
|
175
|
+
using Unity.MLAgents;
|
|
176
|
+
using Unity.MLAgents.Sensors;
|
|
177
|
+
using Unity.MLAgents.Actuators;
|
|
178
|
+
|
|
179
|
+
public class PlayerAgent : Agent
|
|
180
|
+
{
|
|
181
|
+
[SerializeField] private float _moveSpeed = 5f;
|
|
182
|
+
|
|
183
|
+
public override void CollectObservations(VectorSensor sensor)
|
|
184
|
+
{
|
|
185
|
+
sensor.AddObservation(transform.localPosition);
|
|
186
|
+
sensor.AddObservation(_target.localPosition);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
public override void OnActionReceived(ActionBuffers actions)
|
|
190
|
+
{
|
|
191
|
+
float moveX = actions.ContinuousActions[0];
|
|
192
|
+
float moveZ = actions.ContinuousActions[1];
|
|
193
|
+
|
|
194
|
+
transform.localPosition += new Vector3(moveX, 0, moveZ) * _moveSpeed * Time.deltaTime;
|
|
195
|
+
|
|
196
|
+
// Reward shaping
|
|
197
|
+
float distanceToTarget = Vector3.Distance(transform.localPosition, _target.localPosition);
|
|
198
|
+
AddReward(-distanceToTarget * 0.001f);
|
|
199
|
+
|
|
200
|
+
if (distanceToTarget < 1.5f)
|
|
201
|
+
{
|
|
202
|
+
AddReward(1.0f);
|
|
203
|
+
EndEpisode();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
public override void Heuristic(in ActionBuffers actionsOut)
|
|
208
|
+
{
|
|
209
|
+
// Human control for testing
|
|
210
|
+
var continuousActions = actionsOut.ContinuousActions;
|
|
211
|
+
continuousActions[0] = Input.GetAxis("Horizontal");
|
|
212
|
+
continuousActions[1] = Input.GetAxis("Vertical");
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Unity Sentis (On-Device AI)
|
|
220
|
+
|
|
221
|
+
### Loading and Running ONNX Model
|
|
222
|
+
|
|
223
|
+
```csharp
|
|
224
|
+
using Unity.Sentis;
|
|
225
|
+
|
|
226
|
+
public class AIController : MonoBehaviour
|
|
227
|
+
{
|
|
228
|
+
[SerializeField] private ModelAsset _modelAsset;
|
|
229
|
+
|
|
230
|
+
private Model _model;
|
|
231
|
+
private IWorker _worker;
|
|
232
|
+
|
|
233
|
+
void Start()
|
|
234
|
+
{
|
|
235
|
+
_model = ModelLoader.Load(_modelAsset);
|
|
236
|
+
_worker = WorkerFactory.CreateWorker(BackendType.GPUCompute, _model);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
public float[] Predict(float[] input)
|
|
240
|
+
{
|
|
241
|
+
using var inputTensor = new TensorFloat(new TensorShape(1, input.Length), input);
|
|
242
|
+
_worker.Execute(inputTensor);
|
|
243
|
+
|
|
244
|
+
var outputTensor = _worker.PeekOutput() as TensorFloat;
|
|
245
|
+
outputTensor.MakeReadable();
|
|
246
|
+
|
|
247
|
+
return outputTensor.ToReadOnlyArray();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
void OnDestroy()
|
|
251
|
+
{
|
|
252
|
+
_worker?.Dispose();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Performance Optimization
|
|
260
|
+
|
|
261
|
+
### Profiler Checklist
|
|
262
|
+
|
|
263
|
+
| Metric | Target | Tool |
|
|
264
|
+
|--------|--------|------|
|
|
265
|
+
| Frame Time | < 16.67ms (60fps) | Profiler |
|
|
266
|
+
| GC Allocations | 0 in gameplay | Profiler > GC Alloc |
|
|
267
|
+
| Draw Calls | < 200 mobile, < 2000 PC | Frame Debugger |
|
|
268
|
+
| SetPass Calls | < 100 mobile | Frame Debugger |
|
|
269
|
+
| Physics Time | < 3ms | Physics Debugger |
|
|
270
|
+
|
|
271
|
+
### Quick Wins
|
|
272
|
+
|
|
273
|
+
```csharp
|
|
274
|
+
// 1. Cache GetComponent
|
|
275
|
+
private Rigidbody _rb;
|
|
276
|
+
void Awake() => _rb = GetComponent<Rigidbody>();
|
|
277
|
+
|
|
278
|
+
// 2. Use CompareTag instead of ==
|
|
279
|
+
if (other.CompareTag("Enemy")) // NOT other.tag == "Enemy"
|
|
280
|
+
|
|
281
|
+
// 3. Avoid LINQ in Update
|
|
282
|
+
// ❌ enemies.Where(e => e.IsAlive).ToList()
|
|
283
|
+
// ✅ Manual loop with cached list
|
|
284
|
+
|
|
285
|
+
// 4. Use NonAlloc physics
|
|
286
|
+
Physics.RaycastNonAlloc(ray, _hitBuffer, maxDistance);
|
|
287
|
+
Physics.OverlapSphereNonAlloc(pos, radius, _colliderBuffer);
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## XR Development (Unity XR)
|
|
293
|
+
|
|
294
|
+
### Setup XR Interaction Toolkit
|
|
295
|
+
|
|
296
|
+
```csharp
|
|
297
|
+
// XR Rig setup in code
|
|
298
|
+
using UnityEngine.XR.Interaction.Toolkit;
|
|
299
|
+
|
|
300
|
+
public class XRSetup : MonoBehaviour
|
|
301
|
+
{
|
|
302
|
+
[SerializeField] private XRController _leftController;
|
|
303
|
+
[SerializeField] private XRController _rightController;
|
|
304
|
+
|
|
305
|
+
void Start()
|
|
306
|
+
{
|
|
307
|
+
// Bind inputs
|
|
308
|
+
_rightController.selectAction.action.performed += OnGrab;
|
|
309
|
+
_leftController.activateAction.action.performed += OnActivate;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
private void OnGrab(InputAction.CallbackContext ctx)
|
|
313
|
+
{
|
|
314
|
+
// Handle grab input
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### VR Performance Targets
|
|
320
|
+
|
|
321
|
+
| Metric | Quest 2/3 | PC VR |
|
|
322
|
+
|--------|-----------|-------|
|
|
323
|
+
| FPS | 72-90 | 90 |
|
|
324
|
+
| Draw Calls | < 100 | < 300 |
|
|
325
|
+
| Triangles | < 500K | < 2M |
|
|
326
|
+
| Texture Memory | < 1GB | < 4GB |
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Anti-Patterns
|
|
331
|
+
|
|
332
|
+
| ❌ Don't | ✅ Do |
|
|
333
|
+
|----------|-------|
|
|
334
|
+
| `FindObjectOfType` in Update | Cache in Awake |
|
|
335
|
+
| `Resources.Load` at runtime | Addressables |
|
|
336
|
+
| String comparisons for tags | `CompareTag()` |
|
|
337
|
+
| `foreach` with LINQ | `for` loop |
|
|
338
|
+
| Create materials at runtime | Shared materials |
|
|
339
|
+
| Instantiate in hot path | Object pooling |
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## Quick Reference Commands
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
# Build from command line
|
|
347
|
+
Unity -quit -batchmode -projectPath . -buildTarget StandaloneWindows64 -buildOutput build.exe
|
|
348
|
+
|
|
349
|
+
# Run tests
|
|
350
|
+
Unity -runTests -testPlatform playmode -testResults results.xml
|
|
351
|
+
|
|
352
|
+
# Import package
|
|
353
|
+
Unity -importPackage package.unitypackage
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
> **Remember:** Unity is a tool, not the game. Profile before optimizing, prototype before polishing.
|