using UnityEngine; namespace BrewMonster { /// /// Animation test scene helpers for editor/bootstrap weapon iteration. /// 动画测试场景:编辑器 / Bootstrap 武器调试辅助。 /// public abstract partial class CECPlayer { /// /// Attach weapon prefabs like (hand hooks), and set for . /// Omit both prefabs (or pass ) to clear meshes and reset attack type. /// 与 ShowEquipments 相同挂点挂接武器,并设置 m_uAttackType 以驱动动作后缀。两预制体均为空则清除并还原默认攻击类型。 /// public void AnimSceneAttachWeaponPrefabs(GameObject rightPrefab, GameObject leftPrefab, uint weaponActionType) { if (_currentRightHandWeapon != null) { Destroy(_currentRightHandWeapon); _currentRightHandWeapon = null; } if (_currentLeftHandWeapon != null) { Destroy(_currentLeftHandWeapon); _currentLeftHandWeapon = null; } bool anyAttached = false; if (rightPrefab != null) { GameObject hookGo = FindChildObjectRecursive(transform, _hh_right_hand_weapon); if (hookGo != null) { GameObject weaponObject = Instantiate(rightPrefab); weaponObject.transform.SetParent(hookGo.transform); weaponObject.transform.localPosition = rightPrefab.transform.localPosition; weaponObject.transform.localRotation = rightPrefab.transform.localRotation; weaponObject.transform.localScale = Vector3.one; weaponObject.SetActive(true); _currentRightHandWeapon = weaponObject; anyAttached = true; } else { Debug.LogWarning( "[AnimSceneBootstrap] AnimSceneAttachWeaponPrefabs: hook not found: " + _hh_right_hand_weapon); } } if (leftPrefab != null) { GameObject hookGo = FindChildObjectRecursive(transform, _hh_left_hand_weapon); if (hookGo != null) { GameObject weaponObject = Instantiate(leftPrefab); weaponObject.transform.SetParent(hookGo.transform); weaponObject.transform.localPosition = leftPrefab.transform.localPosition; weaponObject.transform.localRotation = leftPrefab.transform.localRotation; weaponObject.transform.localScale = Vector3.one; weaponObject.SetActive(true); _currentLeftHandWeapon = weaponObject; anyAttached = true; } else { Debug.LogWarning( "[AnimSceneBootstrap] AnimSceneAttachWeaponPrefabs: hook not found: " + _hh_left_hand_weapon); } } if (anyAttached) { m_uAttackType = weaponActionType; m_bWeaponAttached = true; } else { m_uAttackType = DEFAULT_ACTION_TYPE; AttachWeapon(); } } /// /// assigns = before fills the static table — rebind after bootstrap calls InitStaticRes. /// Mirrors (state 111 → turning table). /// Awake 时静态动作表可能尚未构建;Bootstrap 在 InitStaticRes 之后调用本方法。逻辑与 SetNewExtendStates 一致(扩展状态 111 用旋转表)。 /// public void AnimSceneRebindPlayerActions() { if (GetExtState(111) && _turning_actions != null) { m_PlayerActions = _turning_actions; } else { m_PlayerActions = _default_actions; } } /// /// Animation test scene: elementdataman may not register DT_FASHION_WEAPON_CONFIG, so /// can NRE on a null action_mask when is in [0, NUM_WEAPON_TYPE). /// Setting -1 makes skip the fashion branch (early out in IsFashionWeaponTypeFit). /// 动画测试:元素表可能未注册时装武器配置;将时尚武器类型置为 -1 避免 IsFashionWeaponTypeFit 空引用。 /// public void AnimSceneSanitizeFashionWeaponStateForElementDataCompat() { m_iFashionWeaponType = -1; } /// /// Inspector/debug: non-null string means will no-op or return false before Animancer runs. /// 非空表示 PlayAction 会在播放前失败或直接被拒。 /// public string AnimSceneTryExplainPlayActionFailure(int iAction) { if (iAction < 0 || iAction >= (int)PLAYER_ACTION_TYPE.ACT_MAX) { return $"Action index must be 0..{(int)PLAYER_ACTION_TYPE.ACT_MAX - 1}."; } if (m_pPlayerCECModel == null) { return "CECModel is null — wait for SetPlayerModel / Switch model to finish."; } if (m_PlayerActions == null) { return "m_PlayerActions is null — click Play again after bootstrap runs, or call AnimSceneRebindPlayerActions()."; } if (m_PlayerActions[iAction].data.id == 0) { return $"No PLAYER_ACTION_INFO_CONFIG for index {iAction} (data.id==0). Check actions_player / element data for this action."; } if (m_pActionController == null) { return "m_pActionController is null — model setup did not call RecreateActionController (SetPlayerModel incomplete?)."; } if (iAction >= (int)PLAYER_ACTION_TYPE.ACT_ATTACK_1 && iAction <= (int)PLAYER_ACTION_TYPE.ACT_ATTACK_4) { return "ACT_ATTACK_1..4 are blocked in PlayActionWithConfig — use skill/combat paths."; } return null; } } }