Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when adding or changing tuning values, items, enemies, abilities or levels - put them in the engine's data assets (ScriptableObject, Resource, DataAsset/DataTable, JSON/RON) with validation and stable IDs, keep runtime state out of shared data, inject services instead of singletons, and test data invariants.
インストール方法を見るインストールする前に、エージェントに与えられる指示の中身を確認できます。
Designers balance games by changing numbers hundreds of times. If a number lives in code, each change is a programmer task, a rebuild and a review. If it lives in a data asset, it is an edit a designer can make and a test can check. The code defines what a sword is; the data says what this sword does.
Core principle: Behaviour in code, tuning in data. Data is typed, validated at load, referenced by a stable ID, and never mutated at runtime.
// Unity: ScriptableObject definition
[CreateAssetMenu(menuName = "Game/Weapon")]
public sealed class WeaponDefinition : ScriptableObject {
[SerializeField] string id;
[SerializeField, Min(0)] int damage = 10;
[SerializeField, Min(0.05f)] float cooldownSeconds = 0.5f;
[SerializeField] AnimationCurve falloff = AnimationCurve.Linear(0, 1, 1, 0);
public string Id => id; public int Damage => damage; public float CooldownSeconds => cooldownSeconds;
void OnValidate() { if (string.IsNullOrWhiteSpace(id)) Debug.LogError($"{name}: missing id", this); }
}
# Godot: a Resource saved as .tres
class_name WeaponDefinition extends Resource
@export var id: StringName
@export_range(0, 1000) var damage: int = 10
@export_range(0.05, 10.0, 0.05) var cooldown_seconds: float = 0.5
// Unreal: a primary data asset (or an FTableRowBase row in a DataTable imported from CSV)
UCLASS(BlueprintType)
class UWeaponDefinition : public UPrimaryDataAsset {
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly, meta = (ClampMin = "0")) int32 Damage = 10;
UPROPERTY(EditDefaultsOnly, meta = (ClampMin = "0.05")) float CooldownSeconds = 0.5f;
virtual FPrimaryAssetId GetPrimaryAssetId() const override { return FPrimaryAssetId("Weapon", GetFName()); }
};
// Web: JSON validated once at load (zod)
export const Weapon = z.object({
id: z.string().min(1),
damage: z.number().int().nonnegative(),
cooldownSeconds: z.number().min(0.05),
});
export const weapons = z.array(Weapon).parse(await (await fetch("data/weapons.json")).json());
// Bevy: a serde struct loaded from RON/JSON via an asset loader (or bevy_common_assets)
#[derive(Asset, TypePath, Deserialize)]
pub struct WeaponDefinition { pub id: String, pub damage: u32, pub cooldown_seconds: f32 }
damage = 25 in a script is a data bug. Physics constants and engine settings belong in project settings or a config asset too.OnValidate / IsDataValid(FDataValidationContext&) / @export_range / a schema parse."sword_iron", never "the third weapon" or "Iron Sword"..tres mutated by one enemy changes every enemy. Copy into a runtime state object, or duplicate() the Resource (or set resource_local_to_scene).AnimationCurve, Godot Curve, UCurveFloat/UCurveTable, or a table in JSON. A level-1-to-50 XP formula hard-coded in a switch is not tunable.// ❌ hidden global state; tests share it; order of initialisation decides behaviour
GameManager.Instance.Gold += reward;
// ✅ the dependency is explicit and replaceable in a test
public sealed class LootSystem {
readonly IWallet _wallet; readonly IRandom _rng;
public LootSystem(IWallet wallet, IRandom rng) { _wallet = wallet; _rng = rng; }
}
Each engine has a sanctioned place for services: Unity — a composition root or the repository's DI container (VContainer, Zenject); Godot — an autoload for a service (save, audio, scene loading), never for a level's state; Unreal — subsystems (UGameInstanceSubsystem, UWorldSubsystem); Bevy — Resources inserted by a plugin. Use the one the repository already uses.
Two kinds of tests:
ScriptableObject.CreateInstance<WeaponDefinition>(), WeaponDefinition.new(), a literal object) so the test does not change when a designer rebalances.describe("shipped data", () => {
it("every drop table has positive total weight and only known item ids", () => {
for (const t of dropTables) {
expect(t.entries.reduce((s, e) => s + e.weight, 0)).toBeGreaterThan(0);
for (const e of t.entries) expect(itemIds.has(e.itemId)).toBe(true);
}
});
});
In Unity this is an EditMode test using AssetDatabase.FindAssets("t:WeaponDefinition"); in Godot a test iterating DirAccess over the data folder; in Unreal an Automation test using the Asset Registry or the editor's Data Validation.
Assert.AreEqual(25, sword.Damage)) — that is a change detector that breaks on every rebalance.Update "just for now"..tres at runtime.Instance holding gameplay state across scenes and tests..cs, .gd, .cpp, .ts or .rs file.まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
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
日本語の概要は準備中です。原文の説明を表示しています。
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
日本語の概要は準備中です。原文の説明を表示しています。
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
日本語の概要は準備中です。原文の説明を表示しています。
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.
日本語の概要は準備中です。原文の説明を表示しています。
Use when deciding whether a request needs an analiz task before implementation - the conditions that require the architect's analysis versus going straight to implementation
日本語の概要は準備中です。原文の説明を表示しています。