Files
test/Assets/PerfectWorld/Scripts/_Doc/AnimationSceneEditor.md
T
Tran Hai Nam 9baa8207b0 Add scene
2026-05-19 10:47:21 +07:00

14 KiB
Raw Blame History

Animation Scene — Editor Tooling

This document tracks Editor-only tooling used with the runtime animation test workflow described in AnimationSceneSetup.md.

Scene docs (runtime hierarchy, managers, APIs): see Assets/PerfectWorld/Scripts/_Doc/AnimationSceneSetup.md.

How to extend this file: whenever you add or plan a new piece of Editor UI / automation for the animation scene, append a ### Feature block under Feature log using the Feature template below. Keep one feature per numbered section so history stays searchable.


Goals

Goal Notes
Faster iteration Load and validate character models from Play Mode, driven by Editor menus where appropriate — no Edit Mode .ecm preview without a dedicated preview pipeline
Stable bootstrap Respect the same prerequisites as runtime (NPCManager, elementdataman, CECPlayer.InitStaticRes(), etc.—see §Prerequisites below)
Traceability Features and acceptance criteria live here before or while implementing the Editor scripts

Suggested implementation locations (when you create them):

  • Menu: e.g. Tools / PerfectWorld / Animation Scene / …
  • Scripts: under Assets/PerfectWorld/Scripts/Editor/ (or project convention for Editor assemblies)

Prerequisites (runtime + Editor)

Anything the Editor tool drives must satisfy the same constraints as a Play Mode session:

Prerequisite Why
AutoInitializer in the open scene Bootstraps IAutoInitialize types including ElementDataManProvider; runs EC_Game.Init(), SkillStubs.Init()
elementdataman loaded CECPlayer.InitStaticRes()BuildActionList() uses ElementDataManProvider.GetElementDataMan()
CECPlayer.InitStaticRes() called once after element data is usable InitializePlayer does not register IAutoInitialize (interface commented); not invoked by CECGameRun.Init() alone. Normal login hits it via CECGameRun.InitCharacter. Animation scene tooling must arrange this explicitly if you rely on skill / action maps
NPCManager in scene SetPlayerModelNPCManager.Instance.GetModelPlayer(profession, gender)
CECAttacksMan in scene PlayAttackEffect, SkillGfxMan.InstanceSub.Tick path (see AnimationSceneSetup.md §12)
EC_ManMessageMono in scene SkillGfxMan resolves EC_ManMessageMono.Instance references
CECHostPlayer reference (selection or serialized) await player.SetPlayerModel(byte profession, byte gender) is CECPlayer API; host implementation is CECHostPlayer
InGameGraphicOption in scene (optional) EC_Game.InitSetting() adjusts render scale / MSAA via InGameGraphicOption. If omitted, MonoSingleton auto-creates a host component; InGameGraphicOption resolves URP from GraphicsSettings.defaultRenderPipeline. Fully custom scenes should still assign URP (+ optional Cinemachine) on InGameGraphicOption for predictable behavior.

Editor caveat: CECHostPlayer.LoadResources uses UnityGameSession.Instance.GetRoleInfo(). For offline Editor-driven loads, prefer calling SetPlayerModel directly (and/or setting m_iProfession, m_iGender on the player instance as your tool requires) rather than invoking full InitCharacter unless session is mocked.


Feature log

Feature 1 — Editor / Play Mode: bootstrap player model

Status: Planned (spec captured here; implementation optional).

Problem: In the animation test scene you need a repeatable way to load the .ecm player model by profession and gender without going through the server login flow.

Proposed behavior:

  1. User opens the animation test scene (or any scene that contains the required managers + a CECHostPlayer instance).
  2. Play Mode required for real SetPlayerModel / Addressables — Editor UI only queues work once Unity is playing (same constraint as Feature 23).
  3. Tool or scene MonoBehaviour exposes Profession / Gender mapped to CECPlayer.SetPlayerModel(byte, byte).
  4. Sequence (recommended): wait until elementdataman load has succeeded → CECPlayer.InitStaticRes() once → await SetPlayerModel(profession, gender).
  5. Success: visible .ecm under Player per parentModel rules (CECPlayer.SetPlayerModel — first child if present, else root); Console filter AnimSceneBootstrap shows SetPlayerModel BEGIN/END when those logs exist.

Out of scope: Full InitCharacter / UnityGameSession parity unless explicitly mocked elsewhere.

Acceptance criteria:

  • Model appears after bootstrap when NPCManager, Addressables, and element data are healthy.
  • Failures are visible (NPCManager null, GetModelPlayer null, InvalidOperationException from SetPlayerModel).
  • InitStaticRes either runs before skill/action-dependent tests or is intentionally skipped with a clear warning.

Primary APIs: CECPlayer.SetPlayerModel, CECPlayer.InitStaticRes — see AnimationSceneSetup.md §1, §1011.


Feature 2 — Editor: trigger Play Action (animation probe)

Status: Planned.

Problem: Quickly verify CECPlayerActionController / Animancer wiring without hunting hotkeys or server-driven triggers.

Proposed behavior:

  1. Menu entry e.g. Tools / PerfectWorld / Animation Scene / … opens a small EditorWindow (or equivalent).
  2. Window active only in Play Mode; references CECHostPlayer (object field or auto-find).
  3. User enters PLAYER_ACTION_TYPE index (same int as CECPlayer.PlayAction(int iAction, bool bRestart)ACT_STAND = 0, etc.; see CECPlayer enum).
  4. Button Play action invokes host.PlayAction(index, true) on the live instance.

Out of scope: Driving PlaySkillCastAction / PlayAttackEffect from this panel (those belong to combat/skill tooling or separate Feature entries).

Acceptance criteria:

  • With model loaded and action maps built (InitStaticRes), ACT_STAND / ACT_RUN-class actions behave like runtime calls.
  • ACT_ATTACK_1..4 may still refuse PlayAction by design (CECPlayer.PlayActionWithConfig blocks normal melee slots — use documented skill APIs instead).

Primary API: CECPlayer.PlayAction(int iAction, bool bRestart) on CECHostPlayer.


Feature 3 — Offline host init: god stats + synthetic skills (below character level 80, human form)

Status: Planned.

Problem: OnMsgHstSkillData never runs offline, so m_aPtSkills / SkillWrapper stay empty — GetNormalSkill / cast checks cannot mirror a real character. You still want most combat skills usable for VFX/animation testing without shape-change prerequisites.

Design summary: After InitStaticRes and SetPlayerModel, synthesize a cmd_skill_data-equivalent payload in memory and apply the same conceptual pipeline as CECHostPlayer.OnMsgHstSkillData: ElementSkill.LoadSkillDataSkillWrapper.Instance.LoadData → instantiate CECSkill rows into m_aPtSkills / m_aPsSkills by skill type (positive vs passive/production/life). Optionally align m_iProfession / m_iGender with the loaded model before filtering.

Simulated character limits:

Constraint Intent
Player level ceiling below 80 Treat maximum simulated level as 79 (or equivalent) when choosing skill rank: for each skill id, pick the highest rank whose SkillStub.GetRequiredLevel(skill) is that simulated level (exact comparison uses live Skill instance at each candidate rank).
Realm Set m_RealmLevel (and any extend props you rely on) high enough so GetRequiredRealmLevel does not fail for included ranks.
SP / Mana / AP / Vigour / HP Raise ROLEBASICPROP (iCurMP, iCurAP, iSP, iVigour, iCurHP, etc.) and matching ROLEEXTPROP caps (max_hp, max_mp, max_ap) so CheckSkillCastCondition resource checks succeed for typical casts.
Exclude transform-shape-only skills ElementSkill.Condition tests (allow_forms & (1 << form_type)) where form_type comes from m_iShape high bits (FORM_MASK_HIGH). Base human m_iShape = 0form_type = 0 ⇒ skill must allow bit 0 in SkillStub.allow_forms. Exclude stubs where (allow_forms & 1) == 0 (human/base form disallowed). Also exclude stubs flagged restrict_change when they denote transformation-only restrictions in data.
Exclude combo-chain prerequisites Skip stubs with combosk_preskill != 0 unless you also simulate combo state (CECComboSkillState).
Exclude item / ammo gated skills Skip itemcost > 0 or arrowcost > 0 unless you populate inventory accordingly.
Exclude goblin line Skip cls == 258.
Profession filter Include stub.cls == playerProfession or cls == 255 (general skills).

Caveats (document in tooltips):

  • restrict_weapons: skills may still return condition invalid weapon if no matching weapon sits in m_pEquipPack — either equip a dummy weapon per profession or accept skipped casts.
  • cmd_skill_data.SKILL.id_skill is a short in GPDataType: skill ids > 32767 cannot be represented; skip or warn.
  • Passive / prerequisite graphs are imperfectly simulated — goal is animation/VFX iteration, not authoritative balance.

Acceptance criteria:

  • GetPositiveSkillByID / GetNormalSkill resolve for a large subset of profession skills after injection.
  • CheckSkillCastCondition returns 0 for a sampled skill without shape-change, assuming weapon/item caveats addressed.
  • Transform-only skills (allow_forms missing human bit or restrict_change) do not appear in the injected list.

Primary references: CECHostPlayer.OnMsgHstSkillData (CECHostPlayer.Skill.cs), ElementSkill.Condition, SkillStub.allow_forms, ROLEBASICPROP, SkillWrapper.


Feature 4 — AnimScenePlayerBootstrap inspector: play action + weapon slots (action_type index)

Status: Done.

Problem: Drive PlayAction and test weapon-mesh + action_weapon_suffix alignment without a separate EditorWindow; GetShowingWeaponType ignores attached meshes when m_uAttackType == DEFAULT_ACTION_TYPE, so animation tests must set m_uAttackType the same way as CECPlayer_Inventory.ShowEquipments (from WEAPON_SUB_TYPE.action_type).

Implemented behavior:

  1. AnimScenePlayerBootstrapEditor (Play Mode): Play action (int + RestartCECHostPlayer.PlayAction), Re-apply active weapon slot.
  2. AnimScenePlayerBootstrap: AnimSceneWeaponSlot[15] (rightHandModelPrefab / leftHandModelPrefab per row i === action_type), activeWeaponActionTypeIndex, applyWeaponAfterModelLoad; after SetPlayerModel, ApplyWeaponForActiveSlot() runs when enabled.
  3. CECPlayer.AnimSceneAttachWeaponPrefabs: clears _currentRightHandWeapon / _currentLeftHandWeapon, parents instances under HH_righthandweapon / HH_lefthandweapon (same as CECPlayer_Inventory.ShowEquipments), sets m_uAttackType when any side attaches; empty slot → DEFAULT_ACTION_TYPE and AttachWeapon().

Primary API / hooks: CECPlayer.AnimSceneAttachWeaponPrefabs, AnimScenePlayerBootstrap.ApplyWeaponForActiveSlot, Assets/PerfectWorld/Scripts/Editor/AnimScenePlayerBootstrapEditor.cs


Feature 1 legacy API snippet (reference only)

Use when implementing Feature 1 bootstrap:

await player.SetPlayerModel((byte)profession, (byte)gender);
CECPlayer.InitStaticRes();

Related runtime doc sections: AnimationSceneSetup.md §1 (model loading), §911 (scene objects / init order).


Feature template (copy for Feature 4, 5, …)

Paste and fill whenever you scope a new Editor capability:

### Feature N — <short title>

**Status:** Planned | In progress | Done

**Problem:** <what pain this removes>

**Proposed behavior:**
1. <step>
2. <step>

**Out of scope:** <explicit non-goals>

**Acceptance criteria:**
- <testable criterion>
- <…>

**Primary API / hooks:** `<class.method or menu path>`

**Related docs / code paths:** `<links to markdown or scripts>`

Maintaining this doc

When Do
You start designing an Editor capability Add a ### Feature N section with Status: Planned and acceptance criteria
You implement or change behavior Update Status, Primary API, and point to concrete script paths under Assets/.../Editor/
Behaviour diverges from runtime Refresh Prerequisites and cross-check AnimationSceneSetup.md

Play Mode — Bootstrap log tag [AnimSceneBootstrap]

Scripts log a shared prefix [AnimSceneBootstrap] so you can filter the Unity Console while verifying initialization order:

Typical order Location
Scene Awake boot AutoInitializer: BEGIN → IAutoInitialize count → EC_Game.InitSkillStubs.Init → END
Element data finished (async after above) ElementDataManProvider: SUCCESS or FAILED after load_data
Attacks/GFX composers CECAttacksMan: AwakeStartSetupAttacksMan → optional GFX preload kick
Action/skill tables (when you call it) CECPlayer.InitStaticRes: BEGIN / END

SetPlayerModel also logs BEGIN / END with the same prefix when loading the player .ecm.

Filter: Console search AnimSceneBootstrap.