[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CBB5SS3RQJZPXFFX8TYEFS":3,"skill-same:01M6CBB5SS3RQJZPXFFX8TYEFS":45},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":20,"linkOnly":21,"markdownContent":22,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":13,"repositoryHtmlUrl":27,"repositoryHomepageUrl":6,"ownerHtmlUrl":28,"ownerBlogUrl":6,"ownerDescription":29,"updatedAt":30,"install":31,"resources":44},"01M6CBB5SS3RQJZPXFFX8TYEFS","10-actor-system",null,"devwinsoft\u002Fdevian","devwinsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F22570160?v=4","01M6C6RR8W05NH8NPKQNCE3Q72","maoshy","01M6C6RRDJ5TJJCZXRTY801YDH",0,"MIT","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian-unity\u002F20-common-package\u002F10-actor-system\u002FSKILL.md",[],[18,19],"system","10 actor system","2026-11-10 10:12:30",false,"# 10-actor-system\n\nStatus: ACTIVE\nAppliesTo: v11\nType: Component Specification\n\n## 목적\n\n`ActorObject` \u002F `ActorController\u003CTOwner>`는 **Actor-Controller 패턴**의 공통 베이스이다.\n\n- `ActorObject` — MonoBehaviour + IPoolable. 컨트롤러 목록 관리, 외부 Init\u002FClear lifecycle\n- `ActorController\u003CTOwner>` — abstract generic MonoBehaviour. Owner에 종속되는 경량 모듈. 자체 등록 없음\n- Actor가 `RegisterController\u003CT>()`로 컨트롤러를 등록하고, `Init()`에서 일괄 초기화\n\n---\n\n## 범위\n\n### 포함\n\n- `ActorObject` — Actor lifecycle (Init\u002FClear), 컨트롤러 등록\u002F해제, 풀 훅\n- `ActorController\u003CTOwner>` — Controller lifecycle (Init\u002FClear), Owner 참조, Priority\n\n### 제외\n\n- 구체적 Actor\u002FController 구현 (서브클래스)\n- 입력 컨트롤러 (→ `25-input-controller`)\n- 풀 매니저 (→ `10-pool-system`)\n\n---\n\n## 네임스페이스\n\n```csharp\nnamespace Devian\n```\n\n---\n\n## 핵심 규약 (Hard Rule)\n\n### 1. Actor Lifecycle\n\n- `Awake()` → `onAwake()` — Unity 콜백. Init 호출 금지\n- `Init()` — **외부 호출 전용**. 1회만 실행 (idempotent)\n  1. `_initialized = true`\n  2. `onInit()` — 서브클래스 확장 훅\n  3. 등록된 컨트롤러 순회 → `controller.Init(this)`\n  4. `onPostInit()` — 컨트롤러 초기화 완료 후 훅\n- `Clear()` — **외부 호출 + OnDestroy\u002FOnPoolDespawned 방어**. 1회만 실행 (idempotent)\n  1. `_cleared = true`\n  2. `onClear()` — 서브클래스 정리 훅\n  3. 컨트롤러 역순 순회 → `controller.Clear()`\n  4. `_controllers.Clear()` + `_initialized = false`\n  5. `onPostClear()`\n- `OnDestroy()` → `Clear()` (방어)\n\n### 2. Controller Lifecycle\n\n- `Awake()` → `onAwake()` — Unity 콜백\n- `Init(TOwner owner)` — Actor.Init() 루프에서 호출. 1회만 실행 (idempotent)\n  1. `_owner = owner`, `_initialized = true`\n  2. `onInit(owner)` — 서브클래스 확장 훅\n- `Clear()` — Actor.Clear() 루프에서 호출. virtual. 1회만 실행 (idempotent)\n  1. `_cleared = true`\n  2. `onClear()` — 서브클래스 정리 훅\n  3. `_initialized = false`, `_owner = default`\n\n### 3. RegisterController\\\u003CT\\>()\n\n- `ActorObject.RegisterController\u003CT>()` — 파라미터 없는 제네릭\n  1. `GetComponent\u003CT>()` → null이면 `AddComponent\u003CT>()`\n  2. 중복 검사 후 `_controllers`에 추가\n  3. Init은 하지 않음 — `Actor.Init()` 루프에서 일괄 초기화\n- `ActorObject.RegisterController\u003CT>(GameObject obj)` — 외부 GameObject 대상 제네릭\n  1. `obj.GetComponent\u003CT>()` → null이면 `obj.AddComponent\u003CT>()`\n  2. 중복 검사 후 `_controllers`에 추가\n  3. Init은 하지 않음 — `Actor.Init()` 루프에서 일괄 초기화\n- `ActorObject.UnregisterController(ActorController\u003CActorObject>)` — 목록에서 제거\n\n### 4. Controller 자동 등록 없음\n\n- ActorController에 OnEnable\u002FOnDisable\u002FOnDestroy 없음\n- TryRegisterToActor \u002F RegisterSelf \u002F MarkRegistered 없음\n- 등록\u002F해제는 오직 Actor의 책임\n\n### 5. Pool 지원\n\n- `IPoolable\u003CActorObject>` 구현\n- `OnPoolSpawned()` — 재사용 준비 (non-virtual)\n  1. `_cleared = false`, `_initialized = false`\n  2. `onPoolSpawned()` — 서브클래스 확장 훅\n- `OnPoolDespawned()` — 정리 (non-virtual)\n  1. `onPoolDespawned()` — 서브클래스 정리 훅 (Clear 전)\n  2. `Clear()`\n\n### 6. Priority\n\n- `ActorController\u003CTOwner>.Priority` — `virtual int`, 기본값 0\n- 서브클래스에서 override 가능 (예: InputController 우선순위)\n\n---\n\n## API 시그니처\n\n```csharp\n\u002F\u002F --- ActorObject ---\npublic abstract class ActorObject : MonoBehaviour, IPoolable\u003CActorObject>\n{\n    \u002F\u002F Lifecycle\n    protected virtual void Awake();\n    protected virtual void onAwake() { }\n    public void Init();\n    protected virtual void onInit() { }\n    protected virtual void onPostInit() { }\n    public virtual void Clear();\n    protected virtual void onClear() { }\n    protected virtual void onPostClear() { }\n    protected virtual void OnDestroy();\n\n    \u002F\u002F Pool\n    public void OnPoolSpawned();\n    protected virtual void onPoolSpawned() { }\n    public void OnPoolDespawned();\n    protected virtual void onPoolDespawned() { }\n\n    \u002F\u002F Controller registry\n    public T RegisterController\u003CT>() where T : ActorController\u003CActorObject>;\n    public T RegisterController\u003CT>(GameObject obj) where T : ActorController\u003CActorObject>;\n    public bool UnregisterController(ActorController\u003CActorObject> controller);\n    public IReadOnlyList\u003CActorController\u003CActorObject>> Controllers { get; }\n    public bool IsInitialized { get; }\n    public bool IsCleared { get; }\n}\n\n\u002F\u002F --- ActorController\u003CTOwner> ---\npublic abstract class ActorController\u003CTOwner> : MonoBehaviour\n{\n    public virtual int Priority { get; }     \u002F\u002F default 0\n    protected virtual void Awake();\n    protected virtual void onAwake() { }\n\n    public void Init(TOwner owner);\n    protected virtual void onInit(TOwner owner) { }\n\n    public virtual void Clear();\n    protected virtual void onClear() { }\n\n    public TOwner Owner { get; }\n    public bool IsInitialized { get; }\n    public bool IsCleared { get; }\n}\n```\n\n---\n\n## 파일 경로\n\n| 타입 | 경로 |\n|------|------|\n| ActorObject | `com.devian.foundation\u002FSamples~\u002FCommonPackage\u002FRuntime\u002FUnity\u002FActors\u002FActorObject.cs` |\n| ActorController\\\u003CTOwner\\> | `com.devian.foundation\u002FSamples~\u002FCommonPackage\u002FRuntime\u002FUnity\u002FActors\u002FActorController.cs` |\n\n---\n\n## DoD (Definition of Done)\n\n- [ ] 모든 파일이 `namespace Devian` 사용\n- [ ] ActorObject가 `abstract class`, `IPoolable\u003CActorObject>` 구현\n- [ ] ActorController\\\u003CTOwner\\>가 `abstract class`, MonoBehaviour 상속\n- [ ] Controller 자동 등록 없음 (OnEnable\u002FRegisterSelf 등 없음)\n- [ ] `RegisterController\u003CT>()` — 파라미터 없는 제네릭, GetComponent\u002FAddComponent\n- [ ] `RegisterController\u003CT>(GameObject obj)` — 외부 GameObject 대상 제네릭\n- [ ] Actor.Init()에서 컨트롤러 일괄 Init (등록 시점에 Init 하지 않음)\n- [ ] Actor.Clear()에서 컨트롤러 역순 Clear\n- [ ] 모든 protected virtual 훅 소문자 시작 (onAwake, onInit, onClear, onPostInit, onPostClear)\n- [ ] Controller.Init\u002FClear idempotent (1회만 실행)\n- [ ] Pool 훅: OnPoolSpawned(리셋→onPoolSpawned), OnPoolDespawned(onPoolDespawned→Clear)\n- [ ] UPM ↔ UnityExample 동일\n\n---\n\n## Reference\n\n- Parent: `..\u002F00-overview\u002FSKILL.md`\n- 입력 컨트롤러: `..\u002F25-input-controller\u002FSKILL.md`\n- 풀 매니저: `..\u002F27-pool-system\u002FSKILL.md`\n",{},"main","8cb5bd877a3a7004867d2f55697cb9e4ff2f1734","skills\u002Fdevian-unity\u002F20-common-package\u002F10-actor-system","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian","https:\u002F\u002Fgithub.com\u002Fdevwinsoft","Kim Hyong Joon","2026-04-12 18:44:10",{"source":7,"skillName":5,"commands":32,"prompt":42,"zipAvailable":43},[33,36,39],{"tool":34,"command":35},"npx","npx skills add devwinsoft\u002Fdevian --skill 10-actor-system",{"tool":37,"command":38},"bunx","bunx skills add devwinsoft\u002Fdevian --skill 10-actor-system",{"tool":40,"command":41},"pnpm","pnpm dlx skills add devwinsoft\u002Fdevian --skill 10-actor-system","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian-unity\u002F20-common-package\u002F10-actor-system\u002FSKILL.md",true,[],[46,52,60,68,77,84],{"skillNo":47,"name":48,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":49,"categories":50,"keywords":51,"publishedAt":20},"01M6CBX3K2JJV38ANHVGCAT8A0","devian","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002FSKILL.md",[],[48],{"skillNo":53,"name":54,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":55,"categories":56,"keywords":57,"publishedAt":20},"01M6CBX210BFMM8AMN770J9WY8","90-project-archive","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F90-project-archive\u002FSKILL.md",[],[58,59],"archive","90 project archive",{"skillNo":61,"name":62,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":63,"categories":64,"keywords":65,"publishedAt":20},"01M6CBWZSGRR9R3YJZB3177667","30-env-management","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F30-env-management\u002FSKILL.md",[],[66,67],"management","30 env management",{"skillNo":69,"name":70,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":73,"publishedAt":20},"01M6CBWYD3TGWBQV7V35551THF","19-page-push-send","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F19-page-push-send\u002FSKILL.md",[],[74,75,76],"push","page","19 page push send",{"skillNo":78,"name":79,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":80,"categories":81,"keywords":82,"publishedAt":20},"01M6CBWWRQ05A7604GHJKTPJTF","18-page-savedata","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F18-page-savedata\u002FSKILL.md",[],[75,83],"18 page savedata",{"skillNo":85,"name":86,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":87,"categories":88,"keywords":89,"publishedAt":20},"01M6CBWVH4S2VF1V7B2GBTESCT","17-page-deobfuscate","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F17-page-deobfuscate\u002FSKILL.md",[],[75,90],"17 page deobfuscate"]