Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
The English summary is being prepared. Showing the original description.
Use when writing or restructuring Unity C# code - assembly definitions and dependency direction, small components with cached references, ScriptableObjects for data and events, DI instead of singletons, Input System, Addressables, serialization safety and Unity 6 API changes.
The English summary is being prepared. Showing the original description.
Review the instructions the agent will receive before you install.
Unity makes it easy to put everything in one MonoBehaviour that finds its collaborators with FindObjectOfType and a static Instance. That works for a jam and collapses after a few months: nothing is testable, compile times grow, and scene order decides behaviour. Structure the project as assemblies with a dependency direction, plain C# for rules, thin components for engine glue, and data in assets.
Core principle: Rules in plain C# assemblies, components as adapters, data in ScriptableObjects, dependencies passed in. The repository's existing layout and DI choice win.
Game.Core (noEngineReferences: rules, math, state machines, save DTOs)
↑
Game.Runtime (MonoBehaviours, ScriptableObjects, adapters; references Core)
↑
Game.UI (views and presenters; references Runtime/Core, never the reverse)
Game.Editor (includePlatforms: Editor; tools, validators)
Tests.EditMode / Tests.PlayMode (test assemblies; see unity-testing)
{
"name": "Game.Core",
"rootNamespace": "Game.Core",
"references": [],
"noEngineReferences": true,
"autoReferenced": false
}
Game.Core with noEngineReferences: true can be compiled and tested by plain dotnet test when the editor is missing (testable-game-logic).// ❌ lookups every frame, public mutable fields, rules inside the component
public class Enemy : MonoBehaviour {
public int hp = 100;
void Update() {
var player = GameObject.Find("Player");
if (Vector3.Distance(transform.position, player.transform.position) < 5) GetComponent<Animator>().SetTrigger("Attack");
}
}
// ✅ cached references, serialized private fields, rule delegated to plain C#
[RequireComponent(typeof(Animator))]
public sealed class EnemyView : MonoBehaviour {
static readonly int AttackHash = Animator.StringToHash("Attack");
[SerializeField] EnemyDefinition definition;
Animator _animator; EnemyBrain _brain; ITargetProvider _targets;
public void Construct(ITargetProvider targets) => _targets = targets;
void Awake() { _animator = GetComponent<Animator>(); _brain = new EnemyBrain(definition.AttackRange); }
void Update() {
if (_brain.ShouldAttack(transform.position, _targets.PlayerPosition)) _animator.SetTrigger(AttackHash);
}
}
[SerializeField] private over public fields; public API through properties and methods.Awake initialises the object itself; OnEnable/Start wire up to others; OnDisable unsubscribes everything OnEnable subscribed.[RequireComponent] for hard dependencies on the same GameObject; TryGetComponent instead of GetComponent + null check.FixedUpdate through the Rigidbody API (MovePosition, AddForce, linearVelocity), never transform.position on a dynamic body.GameEvent : ScriptableObject with Raise() and listeners) decouple scenes, but keep them few and named for what happened (PlayerDied), not what should happen.LifetimeScope/installer and inject via constructor (plain classes) or [Inject] method (components).Construct(...) as above).static Instance for gameplay state. Engine-wide stateless helpers are fine as static classes.Input class — actions from the .inputactions asset, rebinding and device glyphs (game-input-and-accessibility). A project still on the legacy Input Manager stays on it unless the task migrates it.Resources/. Every LoadAssetAsync handle is released.Awaitable (Unity 6) or UniTask where the repo uses it; cancel with destroyCancellationToken so a destroyed object's continuation does not run. async void only for event handlers, with try/catch.[FormerlySerializedAs("oldName")].[SerializeReference]; plain [SerializeField] slices to the base type.Rigidbody.velocity → linearVelocity; drag/angularDrag → linearDamping/angularDamping.FindObjectsOfType/FindObjectOfType → FindObjectsByType(FindObjectsSortMode.None) / FindAnyObjectByType (and avoid both in gameplay paths).Object.InstantiateAsync for large prefabs; Awaitable.NextFrameAsync, Awaitable.WaitForSecondsAsync.GameObject.Find, FindAnyObjectByType or GetComponent in Update.static Instance managers that depend on scene load order.FormerlySerializedAs.OnEnable without unsubscribing in OnDisable — leaks and calls on destroyed objects.Resources.Load call.transform.position = on an object with a non-kinematic Rigidbody.No reviews yet. Tell others what you thought.
No login needed. Share how it worked for you, ask a question, or note where it did not run.
No comments yet. Be the first to write one.
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
The English summary is being prepared. Showing the original description.
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
The English summary is being prepared. Showing the original description.
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
The English summary is being prepared. Showing the original description.
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
The English summary is being prepared. Showing the original description.
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
The English summary is being prepared. Showing the original description.
Use when the repository keeps its alerting in code, or a person asks for alerts outside TaskTrooper - PrometheusRule YAML, a Cloud Monitoring alert policy in Terraform, a Datadog monitor, each routed to TaskTrooper's alert ingest URL so it opens an incident here
The English summary is being prepared. Showing the original description.