角色能力,存档
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Animancer;
|
||||
using BaseGames.Camera;
|
||||
using BaseGames.Combat;
|
||||
using BaseGames.Combat.StatusEffects;
|
||||
using BaseGames.Dialogue;
|
||||
using BaseGames.Enemies;
|
||||
using BaseGames.Equipment;
|
||||
using BaseGames.Parry;
|
||||
using BaseGames.Player;
|
||||
using BaseGames.Player.States;
|
||||
using BaseGames.Skills;
|
||||
using BaseGames.World;
|
||||
using PathBerserker2d;
|
||||
using Unity.Cinemachine;
|
||||
@@ -33,53 +38,83 @@ namespace BaseGames.Editor
|
||||
{
|
||||
var report = new List<string>();
|
||||
|
||||
GameObject go = new GameObject("Player");
|
||||
Undo.RegisterCreatedObjectUndo(go, "Place Player");
|
||||
go.transform.position = GetDropPosition();
|
||||
go.tag = "Player";
|
||||
SetLayer(go, "Player", report);
|
||||
// ── Player 根节点(行为+物理+标签三合一)──────────────────────────────
|
||||
// Rigidbody2D / 所有 MonoBehaviour 集中于此节点。
|
||||
// HurtBox 作为其子节点,GetComponentInParent<IDamageable>() 向上即可找到
|
||||
// 本节点上的 PlayerController(IDamageable 实现者)。
|
||||
GameObject root = new GameObject("Player");
|
||||
Undo.RegisterCreatedObjectUndo(root, "Place Player");
|
||||
root.transform.position = GetDropPosition();
|
||||
root.tag = "Player";
|
||||
SetLayer(root, "Player", report);
|
||||
|
||||
Rigidbody2D rb = GetOrAddComponent<Rigidbody2D>(go);
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
rb.gravityScale = 2f;
|
||||
rb.constraints = RigidbodyConstraints2D.FreezeRotation;
|
||||
rb.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
|
||||
// 物理组件(PlayerMovement RequireComponent(Rigidbody2D),必须同节点)
|
||||
Rigidbody2D rb = GetOrAddComponent<Rigidbody2D>(root);
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
rb.gravityScale = 2f;
|
||||
rb.constraints = RigidbodyConstraints2D.FreezeRotation;
|
||||
rb.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
|
||||
rb.interpolation = RigidbodyInterpolation2D.Interpolate;
|
||||
GetOrAddComponent<BoxCollider2D>(root);
|
||||
|
||||
GetOrAddComponent<CapsuleCollider2D>(go);
|
||||
GetOrAddComponent<Animator>(go);
|
||||
SetupSpriteRenderer(go);
|
||||
// 动画组件(AnimancerComponent 需要 Animator 存在;PlayerController
|
||||
// [RequireComponent(typeof(AnimancerComponent))] 保证其存在)
|
||||
GetOrAddComponent<Animator>(root);
|
||||
GetOrAddComponent<AnimancerComponent>(root);
|
||||
|
||||
SetupSpriteRenderer(root);
|
||||
|
||||
PlayerStats playerStats = GetOrAddComponent<PlayerStats>(go);
|
||||
PlayerMovement playerMovement = GetOrAddComponent<PlayerMovement>(go);
|
||||
PlayerController playerController = GetOrAddComponent<PlayerController>(go);
|
||||
PlayerCombat playerCombat = GetOrAddComponent<PlayerCombat>(go);
|
||||
// 核心行为组件
|
||||
PlayerStats playerStats = GetOrAddComponent<PlayerStats>(root);
|
||||
PlayerMovement playerMovement = GetOrAddComponent<PlayerMovement>(root);
|
||||
PlayerCombat playerCombat = GetOrAddComponent<PlayerCombat>(root);
|
||||
FormController formController = GetOrAddComponent<FormController>(root);
|
||||
WeaponManager weaponManager = GetOrAddComponent<WeaponManager>(root);
|
||||
SkillManager skillManager = GetOrAddComponent<SkillManager>(root);
|
||||
SpringSystem springSystem = GetOrAddComponent<SpringSystem>(root);
|
||||
ParrySystem parrySystem = GetOrAddComponent<ParrySystem>(root);
|
||||
ShieldComponent shield = GetOrAddComponent<ShieldComponent>(root);
|
||||
PlayerWallDetector wallDetector = GetOrAddComponent<PlayerWallDetector>(root);
|
||||
EquipmentManager equipmentManager = GetOrAddComponent<EquipmentManager>(root);
|
||||
GetOrAddComponent<SkillModifierRegistry>(root);
|
||||
GetOrAddComponent<StatusEffectManager>(root);
|
||||
// PlayerController 最后添加:RequireComponent 会拉取上方已加好的组件
|
||||
PlayerController playerController = GetOrAddComponent<PlayerController>(root);
|
||||
|
||||
// Ground check pivot
|
||||
Transform groundCheckGo = GetOrCreateChild(go.transform, "GroundCheck");
|
||||
groundCheckGo.localPosition = new Vector3(0f, -0.75f, 0f);
|
||||
AssignReference(playerMovement, "_groundCheck", groundCheckGo, report);
|
||||
AssignLayerMask(playerMovement, "_groundLayer", "Ground", report);
|
||||
|
||||
// Weapon socket (WeaponManager instantiates weapons here at runtime)
|
||||
GetOrCreateChild(go.transform, "WeaponSocket");
|
||||
|
||||
// Camera follow target — CinemachineCamera.Follow 使用此子节点而非 Player 根节点
|
||||
GetOrCreateChild(go.transform, "CameraFollowTarget");
|
||||
|
||||
// HurtBox child
|
||||
Transform hurtBoxT = GetOrCreateChild(go.transform, "HurtBox");
|
||||
// ── HurtBox 子节点 ───────────────────────────────────────────────────
|
||||
Transform hurtBoxT = GetOrCreateChild(root.transform, "HurtBox");
|
||||
SetLayer(hurtBoxT.gameObject, "PlayerHurtBox", report);
|
||||
CapsuleCollider2D hurtCollider = GetOrAddComponent<CapsuleCollider2D>(hurtBoxT.gameObject);
|
||||
BoxCollider2D hurtCollider = GetOrAddComponent<BoxCollider2D>(hurtBoxT.gameObject);
|
||||
hurtCollider.isTrigger = true;
|
||||
HurtBox hurtBox = GetOrAddComponent<HurtBox>(hurtBoxT.gameObject);
|
||||
|
||||
// Assign controller references
|
||||
AssignReference(playerController, "_stats", playerStats, report);
|
||||
AssignReference(playerController, "_hurtBox", hurtBox, report);
|
||||
AssignReference(playerController, "_movement", playerMovement, report);
|
||||
AssignReference(playerController, "_combat", playerCombat, report);
|
||||
// ── [WeaponSocket] 子节点(WeaponManager 动态实例化武器 HitBox 的挂点)
|
||||
GetOrCreateChild(root.transform, "[WeaponSocket]");
|
||||
|
||||
// Event channels (all optional — will be skipped silently if assets missing)
|
||||
// ── GroundCheck 子节点(地面检测 Transform)────────────────────────
|
||||
Transform groundCheckT = GetOrCreateChild(root.transform, "GroundCheck");
|
||||
groundCheckT.localPosition = new Vector3(0f, -0.75f, 0f);
|
||||
AssignReference(playerMovement, "_groundCheck", groundCheckT, report);
|
||||
AssignLayerMask(playerMovement, "_groundLayer", "Ground", report);
|
||||
|
||||
// ── SkillHitBox_Slot 子节点(技能 HitBox 实例化挂点)────────────────
|
||||
GetOrCreateChild(root.transform, "SkillHitBox_Slot");
|
||||
|
||||
// ── CameraFollowTarget 子节点(CinemachineCamera.Follow 目标)────────
|
||||
GetOrCreateChild(root.transform, "CameraFollowTarget");
|
||||
|
||||
// ── PlayerController SerializeField 引用赋值 ──────────────────────
|
||||
AssignReference(playerController, "_combat", playerCombat, report);
|
||||
AssignReference(playerController, "_formController", formController, report);
|
||||
AssignReference(playerController, "_weaponManager", weaponManager, report);
|
||||
AssignReference(playerController, "_skillManager", skillManager, report);
|
||||
AssignReference(playerController, "_springSystem", springSystem, report);
|
||||
AssignReference(playerController, "_parrySystem", parrySystem, report);
|
||||
AssignReference(playerController, "_hurtBox", hurtBox, report);
|
||||
AssignReference(playerController, "_shield", shield, report);
|
||||
AssignReference(playerController, "_wallDetector", wallDetector, report);
|
||||
|
||||
// ── 事件频道(可选,缺失时跳过) ───────────────────────────────────
|
||||
AssignAsset(playerStats, "_onHPChanged", report, false, "EVT_HPChanged");
|
||||
AssignAsset(playerStats, "_onMaxHPChanged", report, false, "EVT_MaxHPChanged");
|
||||
AssignAsset(playerStats, "_onSoulPowerChanged", report, false, "EVT_SoulPowerChanged");
|
||||
@@ -93,17 +128,43 @@ namespace BaseGames.Editor
|
||||
AssignAsset(hurtBox, "_onDamageDealt", report, false, "EVT_DamageDealt");
|
||||
AssignAsset(hurtBox, "_onHitConfirmed", report, false, "EVT_HitConfirmed");
|
||||
|
||||
// Config ScriptableObjects (optional — link manually after placing)
|
||||
Object statsConfig = FindFirstAsset("PLY_PlayerStats", "PlayerStats");
|
||||
Object movConfig = FindFirstAsset("PLY_PlayerMovementConfig", "PlayerMovementConfig");
|
||||
if (movConfig != null) AssignReference(playerController, "_movementConfig", movConfig, report);
|
||||
if (statsConfig != null) AssignReference(playerStats, "_config", statsConfig, report);
|
||||
if (movConfig != null) AssignReference(playerMovement, "_config", movConfig, report);
|
||||
// ── Config SO 自动查找(资产存在时自动绑定)──────────────────────
|
||||
Object statsConfig = FindFirstAsset("PLY_PlayerStats");
|
||||
Object movConfig = FindFirstAsset("PLY_PlayerMovementConfig");
|
||||
Object formConfig = FindFirstAsset("PLY_FormConfig");
|
||||
Object parryConfig = FindFirstAsset("PLY_ParryConfig");
|
||||
Object shieldConfig = FindFirstAsset("PLY_ShieldConfig");
|
||||
Object inputReader = FindFirstAsset("InputReader");
|
||||
Object equipmentConfig = FindFirstAsset("PLY_EquipmentConfig");
|
||||
Object charmCatalog = FindFirstAsset("PLY_CharmCatalog");
|
||||
|
||||
report.Add("PlayerMovement._config、PlayerController._animConfig、_inputReader 等需后续手动绑定。");
|
||||
if (statsConfig != null) AssignReference(playerStats, "_config", statsConfig, report);
|
||||
if (movConfig != null)
|
||||
{
|
||||
AssignReference(playerController, "_movementConfig", movConfig, report);
|
||||
AssignReference(playerMovement, "_config", movConfig, report);
|
||||
AssignReference(wallDetector, "_config", movConfig, report);
|
||||
}
|
||||
if (formConfig != null)
|
||||
{
|
||||
AssignReference(playerController, "_formConfig", formConfig, report);
|
||||
AssignReference(formController, "_config", formConfig, report);
|
||||
}
|
||||
if (parryConfig != null) AssignReference(parrySystem, "_config", parryConfig, report);
|
||||
if (shieldConfig != null) AssignReference(shield, "_config", shieldConfig, report);
|
||||
if (inputReader != null) AssignReference(playerController, "_inputReader", inputReader, report);
|
||||
if (equipmentConfig != null) AssignReference(equipmentManager, "_config", equipmentConfig, report);
|
||||
if (charmCatalog != null) AssignReference(equipmentManager, "_charmCatalog", charmCatalog, report);
|
||||
|
||||
Selection.activeGameObject = go;
|
||||
MarkDirtyAndLog("Player", go, report);
|
||||
report.Add("★ 需手动绑定:PlayerController._animConfig(PLY_PlayerAnimationConfig)");
|
||||
if (statsConfig == null) report.Add("★ 需创建并绑定:PlayerStats._config(PlayerStatsSO)");
|
||||
if (inputReader == null) report.Add("★ 需手动绑定:PlayerController._inputReader(InputReaderSO)");
|
||||
if (equipmentConfig == null) report.Add("★ 需创建并绑定:EquipmentManager._config(EquipmentConfigSO)");
|
||||
if (charmCatalog == null) report.Add("★ 需创建并绑定:EquipmentManager._charmCatalog(CharmCatalogSO)");
|
||||
report.Add("SkillManager 技能槽 SO 需手动填入。");
|
||||
|
||||
Selection.activeGameObject = root;
|
||||
MarkDirtyAndLog("Player", root, report);
|
||||
}
|
||||
|
||||
[MenuItem("BaseGames/Scene/Place/Player Spawn Point", priority = 105)]
|
||||
@@ -168,11 +229,11 @@ namespace BaseGames.Editor
|
||||
AssignReference(enemyBase, "_stats", enemyStats, report);
|
||||
|
||||
// DamageSourceSO for body contact (optional — create manually if missing)
|
||||
Object dmgSrc = FindFirstAsset("DS_EnemyBody", "DS_TestEnemyBody");
|
||||
Object dmgSrc = FindFirstAsset("CMB_DS_EnemyBody", "DS_EnemyBody");
|
||||
if (dmgSrc != null)
|
||||
AssignReference(hitBox, "_defaultSource", dmgSrc, report);
|
||||
else
|
||||
report.Add("未找到 DamageSourceSO (DS_EnemyBody),HitBox_Body._defaultSource 未绑定。请创建后手动指定。");
|
||||
report.Add("未找到 DamageSourceSO,HitBox_Body._defaultSource 未绑定。请按规范创建 CMB_DS_EnemyBody.asset。");
|
||||
|
||||
// Event channels
|
||||
AssignAsset(enemyBase, "_onEnemyDied", report, false, "EVT_EnemyDied");
|
||||
@@ -186,7 +247,7 @@ namespace BaseGames.Editor
|
||||
if (enemyStatsSO != null)
|
||||
AssignReference(enemyBase, "_statsSO", enemyStatsSO, report);
|
||||
else
|
||||
report.Add("未找到 EnemyStatsSO,EnemyBase._statsSO 未绑定。请在 Data/Enemies/ 创建后手动指定。");
|
||||
report.Add("未找到 EnemyStatsSO,EnemyBase._statsSO 未绑定。请在 Data/Enemies/ 创建 ENM_{id}_Stats.asset 后手动指定。");
|
||||
|
||||
report.Add("行为树、导航参数(NavAgent)、动画片段需后续手工挂载。");
|
||||
|
||||
@@ -239,11 +300,11 @@ namespace BaseGames.Editor
|
||||
AssignReference(bossBase, "_stats", bossStats, report);
|
||||
|
||||
// DamageSourceSO
|
||||
Object dmgSrc = FindFirstAsset("DS_BossBody", "DS_EnemyBody");
|
||||
Object dmgSrc = FindFirstAsset("CMB_DS_BossBody", "CMB_DS_EnemyBody", "DS_BossBody");
|
||||
if (dmgSrc != null)
|
||||
AssignReference(hitBox, "_defaultSource", dmgSrc, report);
|
||||
else
|
||||
report.Add("未找到 DamageSourceSO,HitBox_Body._defaultSource 未绑定。");
|
||||
report.Add("未找到 DamageSourceSO,HitBox_Body._defaultSource 未绑定。请按规范创建 CMB_DS_BossBody.asset。");
|
||||
|
||||
// Event channels
|
||||
AssignAsset(bossBase, "_onEnemyDied", report, false, "EVT_EnemyDied");
|
||||
@@ -290,7 +351,8 @@ namespace BaseGames.Editor
|
||||
hurtCol.size = new Vector2(2f, 0.3f);
|
||||
GetOrAddComponent<HurtBox>(hurtBoxT.gameObject);
|
||||
|
||||
AssignAsset(trap, "_onPlayerDied", report, false, "EVT_PlayerDied");
|
||||
AssignAsset(trap, "_onPlayerDied", report, false, "EVT_PlayerDied");
|
||||
AssignAsset(trap, "_onCheckpointRespawn", report, false, "EVT_CheckpointRespawn");
|
||||
|
||||
report.Add("_canPogo=true:子 HurtBox 供玩家下劈弹起;设为 false 可改为纯死亡区(无需子 HurtBox)。");
|
||||
|
||||
@@ -298,7 +360,32 @@ namespace BaseGames.Editor
|
||||
MarkDirtyAndLog("Hazard (LethalTrap)", go, report);
|
||||
}
|
||||
|
||||
[MenuItem("BaseGames/Scene/Place/Collectible (LingZhu)", priority = 125)]
|
||||
[MenuItem("BaseGames/Scene/Place/Checkpoint Marker", priority = 125)]
|
||||
public static void PlaceCheckpointMarker()
|
||||
{
|
||||
var report = new List<string>();
|
||||
|
||||
GameObject go = new GameObject("CheckpointMarker");
|
||||
Undo.RegisterCreatedObjectUndo(go, "Place CheckpointMarker");
|
||||
go.transform.position = GetDropPosition();
|
||||
SetLayer(go, "TriggerZone", report);
|
||||
|
||||
BoxCollider2D col = GetOrAddComponent<BoxCollider2D>(go);
|
||||
col.isTrigger = true;
|
||||
col.size = new Vector2(1f, 2f);
|
||||
|
||||
CheckpointMarker marker = GetOrAddComponent<CheckpointMarker>(go);
|
||||
AssignLayerMask(marker, "_playerLayers", "Player", report);
|
||||
AssignAsset(marker, "_onCheckpointReached", report, false, "EVT_CheckpointReached");
|
||||
|
||||
report.Add("放置于跳跳乐段落的关键节点处;玩家经过后成为该房间最近检查点。");
|
||||
report.Add("同一房间可放置多个,以最近经过的为准。");
|
||||
|
||||
Selection.activeGameObject = go;
|
||||
MarkDirtyAndLog("Checkpoint Marker", go, report);
|
||||
}
|
||||
|
||||
[MenuItem("BaseGames/Scene/Place/Collectible (LingZhu)", priority = 130)]
|
||||
public static void PlaceCollectible()
|
||||
{
|
||||
var report = new List<string>();
|
||||
@@ -349,14 +436,41 @@ namespace BaseGames.Editor
|
||||
|
||||
SavePoint savePoint = GetOrAddComponent<SavePoint>(go);
|
||||
|
||||
AssignAsset(savePoint, "_onSceneLoaded", report, false, "EVT_SceneLoaded");
|
||||
AssignAsset(savePoint, "_onSavePointActivated", report, false, "EVT_SavePointActivated");
|
||||
AssignAsset(savePoint, "_onFastTravelOpen", report, false, "EVT_FastTravelOpen");
|
||||
|
||||
report.Add("填写 _savePointId(全局唯一字符串,用于存档点激活记录与复活定位)。");
|
||||
|
||||
Selection.activeGameObject = go;
|
||||
MarkDirtyAndLog("Save Point", go, report);
|
||||
}
|
||||
|
||||
[MenuItem("BaseGames/Scene/Place/Room Transition", priority = 135)]
|
||||
[MenuItem("BaseGames/Scene/Place/Teleport Station", priority = 135)]
|
||||
public static void PlaceTeleportStation()
|
||||
{
|
||||
var report = new List<string>();
|
||||
|
||||
GameObject go = new GameObject("TeleportStation");
|
||||
Undo.RegisterCreatedObjectUndo(go, "Place TeleportStation");
|
||||
go.transform.position = GetDropPosition();
|
||||
SetLayer(go, "TriggerZone", report);
|
||||
|
||||
BoxCollider2D col = GetOrAddComponent<BoxCollider2D>(go);
|
||||
col.isTrigger = true;
|
||||
col.size = new Vector2(1.5f, 2f);
|
||||
SetupSpriteRenderer(go);
|
||||
|
||||
TeleportStation station = GetOrAddComponent<TeleportStation>(go);
|
||||
AssignAsset(station, "_onFastTravelOpen", report, false, "EVT_FastTravelOpen");
|
||||
|
||||
report.Add("填写 _stationId(传送站唯一 ID,用于地图 UI 标注)。");
|
||||
report.Add("传送站不存档、不复活、不恢复 HP;与存档点是独立对象。");
|
||||
|
||||
Selection.activeGameObject = go;
|
||||
MarkDirtyAndLog("Teleport Station", go, report);
|
||||
}
|
||||
|
||||
[MenuItem("BaseGames/Scene/Place/Room Transition", priority = 140)]
|
||||
public static void PlaceRoomTransition()
|
||||
{
|
||||
var report = new List<string>();
|
||||
@@ -410,20 +524,12 @@ namespace BaseGames.Editor
|
||||
|
||||
CameraArea cameraArea = GetOrAddComponent<CameraArea>(go);
|
||||
|
||||
// AreaBoundary child — 提供 CinemachineConfiner2D 所需的限位多边形(isTrigger = true,仅作为相机约束边界)
|
||||
// AreaBoundary child — 提供 CinemachineConfiner3D 所需的限位体积
|
||||
Transform boundaryT = GetOrCreateChild(go.transform, $"{areaName}_AreaBoundary");
|
||||
PolygonCollider2D boundaryCollider = GetOrAddComponent<PolygonCollider2D>(boundaryT.gameObject);
|
||||
BoxCollider boundaryCollider = GetOrAddComponent<BoxCollider>(boundaryT.gameObject);
|
||||
boundaryCollider.isTrigger = true;
|
||||
boundaryCollider.pathCount = 1;
|
||||
// 顶点必须逆时针(CCW)排列:Cinemachine 底层 Clipper 库对 CW 多边形(area<0)会取反 delta,
|
||||
// 导致向外膨胀而非向内收缩,相机将不受限制地跑出边界。
|
||||
boundaryCollider.SetPath(0, new Vector2[]
|
||||
{
|
||||
new Vector2(-12f, -6f), // BL
|
||||
new Vector2( 12f, -6f), // BR
|
||||
new Vector2( 12f, 6f), // TR
|
||||
new Vector2(-12f, 6f), // TL
|
||||
});
|
||||
boundaryCollider.center = new Vector3(0f, 0f, -10f); // Z 占位符,实际深度由 SyncConfiner 按 LensConfig 计算
|
||||
boundaryCollider.size = new Vector3(24f, 12f, 1f); // 默认房间尺寸占位符
|
||||
|
||||
AssignReference(cameraArea, "_confinerCollider", boundaryCollider, report);
|
||||
|
||||
@@ -433,26 +539,26 @@ namespace BaseGames.Editor
|
||||
zoneGo.transform.position = pos;
|
||||
SetLayer(zoneGo, "TriggerZone", report);
|
||||
|
||||
PolygonCollider2D col = GetOrAddComponent<PolygonCollider2D>(zoneGo);
|
||||
CameraTriggerZone zone = GetOrAddComponent<CameraTriggerZone>(zoneGo);
|
||||
PolygonCollider2D col = GetOrAddComponent<PolygonCollider2D>(zoneGo);
|
||||
col.isTrigger = true;
|
||||
// 默认矩形轮廓(CCW),与 AreaBoundary 默认尺寸一致(可在 Inspector 中编辑顶点调整为任意多边形)
|
||||
// 默认矩形多边形(24×12),可在 Inspector 中编辑顶点
|
||||
col.SetPath(0, new Vector2[]
|
||||
{
|
||||
new Vector2(-12f, -6f), // BL
|
||||
new Vector2( 12f, -6f), // BR
|
||||
new Vector2( 12f, 6f), // TR
|
||||
new Vector2(-12f, 6f), // TL
|
||||
new Vector2(-12f, -6f),
|
||||
new Vector2(-12f, 6f),
|
||||
new Vector2( 12f, 6f),
|
||||
new Vector2( 12f, -6f),
|
||||
});
|
||||
|
||||
CameraTriggerZone zone = GetOrAddComponent<CameraTriggerZone>(zoneGo);
|
||||
AssignReference(zone, "_targetArea", cameraArea, report);
|
||||
// TriggerZone 归入 CameraArea 节点,方便统一调整与查找
|
||||
Undo.SetTransformParent(zoneGo.transform, go.transform, "Parent TriggerZone to CameraArea");
|
||||
zoneGo.transform.localPosition = Vector3.zero;
|
||||
Undo.CollapseUndoOperations(undoGroup);
|
||||
|
||||
report.Add($"调整 {areaName}_AreaBoundary PolygonCollider2D 顶点以匹配区域边界。");
|
||||
report.Add($"调整 {areaName}_TriggerZone PolygonCollider2D 顶点以匹配入口走廊(支持任意多边形)。");
|
||||
report.Add($"绑定 LensConfig SO 后单击 Inspector 中「从可视区域更新限位区域」计算 {areaName}_AreaBoundary BoxCollider。");
|
||||
report.Add($"编辑 {areaName}_TriggerZone PolygonCollider2D 的顶点以匹配入口多边形区域。");
|
||||
|
||||
// ── 自动关联到同场景 RoomController(若其 _cameraArea 为空)────────
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace BaseGames.Editor
|
||||
|
||||
GameObject vcamAGo = GetOrCreateChild(camera, "VCamA").gameObject;
|
||||
CinemachineCamera vcamA = GetOrAddComponent<CinemachineCamera>(vcamAGo);
|
||||
GetOrAddComponent<CinemachineConfiner2D>(vcamAGo);
|
||||
GetOrAddComponent<CinemachineConfiner3D>(vcamAGo);
|
||||
GetOrAddComponent<CameraAxisLockExtension>(vcamAGo);
|
||||
GetOrAddComponent<CameraAsymmetricDampingExtension>(vcamAGo);
|
||||
GetOrAddComponent<CameraAdaptiveLookaheadExtension>(vcamAGo);
|
||||
@@ -102,7 +102,7 @@ namespace BaseGames.Editor
|
||||
|
||||
GameObject vcamBGo = GetOrCreateChild(camera, "VCamB").gameObject;
|
||||
CinemachineCamera vcamB = GetOrAddComponent<CinemachineCamera>(vcamBGo);
|
||||
GetOrAddComponent<CinemachineConfiner2D>(vcamBGo);
|
||||
GetOrAddComponent<CinemachineConfiner3D>(vcamBGo);
|
||||
GetOrAddComponent<CameraAxisLockExtension>(vcamBGo);
|
||||
GetOrAddComponent<CameraAsymmetricDampingExtension>(vcamBGo);
|
||||
GetOrAddComponent<CameraAdaptiveLookaheadExtension>(vcamBGo);
|
||||
@@ -221,15 +221,11 @@ namespace BaseGames.Editor
|
||||
GameObject cameraAreaGo = GetOrCreateChild(cameraGroup, "CameraArea").gameObject;
|
||||
CameraArea cameraArea = GetOrAddComponent<CameraArea>(cameraAreaGo);
|
||||
|
||||
// AreaBoundary — 提供 CinemachineConfiner2D 所需的限位多边形
|
||||
// AreaBoundary — 提供 CinemachineConfiner3D 所需的限位体积
|
||||
Transform boundaryT = GetOrCreateChild(cameraAreaGo.transform, "AreaBoundary");
|
||||
PolygonCollider2D boundaryCollider = GetOrAddComponent<PolygonCollider2D>(boundaryT.gameObject);
|
||||
boundaryCollider.pathCount = 1;
|
||||
boundaryCollider.SetPath(0, new Vector2[]
|
||||
{
|
||||
new Vector2(-12f, -6f), new Vector2(-12f, 6f),
|
||||
new Vector2( 12f, 6f), new Vector2( 12f, -6f),
|
||||
});
|
||||
BoxCollider boundaryCollider = GetOrAddComponent<BoxCollider>(boundaryT.gameObject);
|
||||
boundaryCollider.center = new Vector3(0f, 0f, -10f); // Z 占位符,实际深度由 SyncConfiner 按 LensConfig 计算
|
||||
boundaryCollider.size = new Vector3(24f, 12f, 1f); // 默认房间尺寸占位符
|
||||
|
||||
AssignReference(cameraArea, "_confinerCollider", boundaryCollider);
|
||||
|
||||
@@ -282,7 +278,7 @@ namespace BaseGames.Editor
|
||||
|
||||
// ── Report ─────────────────────────────────────────────────────
|
||||
report.Add("在 RoomController._roomId 填写唯一房间 ID(如 \"Room_Forest_01\")。");
|
||||
report.Add("调整 AreaBoundary PolygonCollider2D 顶点以匹配实际房间大小。");
|
||||
report.Add("绑定 LensConfig SO 后单击 Inspector 中「从可视区域更新限位区域」计算正确的 BoxCollider。");
|
||||
report.Add("使用 Tile Palette 在 Ground Tilemap 上绘制地形,然后在 NavSurface Inspector 中点击 Bake。");
|
||||
report.Add("[Transitions] 子节点下使用 BaseGames/Scene/Place/Room Transition 添加过渡点。");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user