摄像机区域的优化

This commit is contained in:
2026-05-17 07:56:12 +08:00
parent f264329751
commit d25f237e76
62 changed files with 25774 additions and 5450 deletions

View File

@@ -86,6 +86,29 @@ namespace BaseGames.Editor
CameraStateController cameraStateController = GetOrAddComponent<CameraStateController>(cameraStateGo);
CinemachineImpulseSource impulseSource = GetOrAddComponent<CinemachineImpulseSource>(cameraStateGo);
// 垂直窥视系统独立节点CameraStateController 持引用
GameObject lookSystemGo = GetOrCreateChild(camera, "CameraLookSystem").gameObject;
CameraLookSystem lookSystem = GetOrAddComponent<CameraLookSystem>(lookSystemGo);
GameObject vcamAGo = GetOrCreateChild(camera, "VCamA").gameObject;
CinemachineCamera vcamA = GetOrAddComponent<CinemachineCamera>(vcamAGo);
GetOrAddComponent<CinemachineConfiner2D>(vcamAGo);
GetOrAddComponent<CameraAxisLockExtension>(vcamAGo);
GetOrAddComponent<CameraAsymmetricDampingExtension>(vcamAGo);
GetOrAddComponent<CameraAdaptiveLookaheadExtension>(vcamAGo);
// CinemachinePositionComposerBody 阶段组件必须存在ConfigureSlot 依赖它写入所有相机跟随参数
var composerA = GetOrAddComponent<CinemachinePositionComposer>(vcamAGo);
ApplyComposerDefaults(composerA);
GameObject vcamBGo = GetOrCreateChild(camera, "VCamB").gameObject;
CinemachineCamera vcamB = GetOrAddComponent<CinemachineCamera>(vcamBGo);
GetOrAddComponent<CinemachineConfiner2D>(vcamBGo);
GetOrAddComponent<CameraAxisLockExtension>(vcamBGo);
GetOrAddComponent<CameraAsymmetricDampingExtension>(vcamBGo);
GetOrAddComponent<CameraAdaptiveLookaheadExtension>(vcamBGo);
var composerB = GetOrAddComponent<CinemachinePositionComposer>(vcamBGo);
ApplyComposerDefaults(composerB);
GameObject uiRootGo = GetOrCreateChild(ui, "UIRoot").gameObject;
UIManager uiManager = GetOrAddComponent<UIManager>(uiRootGo);
@@ -146,6 +169,11 @@ namespace BaseGames.Editor
AssignReference(cameraStateController, "_brain", brain);
AssignReference(cameraStateController, "_impulseSource", impulseSource);
AssignReference(cameraStateController, "_lookSystem", lookSystem);
AssignReference(cameraStateController, "_vcamA", vcamA);
AssignReference(cameraStateController, "_vcamB", vcamB);
AssignAsset(cameraStateController, "_onPlayerSpawned", report, true, "EVT_PlayerSpawned");
AssignAsset(cameraStateController, "_lensConfig", report, false, "CAM_LensConfig", "LensConfig", "CameraLensConfig");
AssignReference(uiManager, "_hudRoot", hudRootGo);
AssignReference(uiManager, "_pauseMenuRoot", pauseRootGo);
@@ -189,13 +217,12 @@ namespace BaseGames.Editor
// ── [Camera] ───────────────────────────────────────────────────
Transform cameraGroup = GetOrCreateChild(root.transform, "[Camera]");
GameObject roomCameraGo = GetOrCreateChild(cameraGroup, "RoomCamera").gameObject;
CinemachineCamera cinemachineCamera = GetOrAddComponent<CinemachineCamera>(roomCameraGo);
RoomCamera roomCamera = GetOrAddComponent<RoomCamera>(roomCameraGo);
CinemachineConfiner2D confiner = GetOrAddComponent<CinemachineConfiner2D>(roomCameraGo);
// CameraArea — 定义相机区域(限位 + 混合配置 + 可选专有 VCam
GameObject cameraAreaGo = GetOrCreateChild(cameraGroup, "CameraArea").gameObject;
CameraArea cameraArea = GetOrAddComponent<CameraArea>(cameraAreaGo);
// RoomBoundary — defines visible area and confiner polygon
Transform boundaryT = GetOrCreateChild(roomCameraGo.transform, "RoomBoundary");
// AreaBoundary — 提供 CinemachineConfiner2D 所需的限位多边形
Transform boundaryT = GetOrCreateChild(cameraAreaGo.transform, "AreaBoundary");
PolygonCollider2D boundaryCollider = GetOrAddComponent<PolygonCollider2D>(boundaryT.gameObject);
boundaryCollider.pathCount = 1;
boundaryCollider.SetPath(0, new Vector2[]
@@ -203,16 +230,8 @@ namespace BaseGames.Editor
new Vector2(-12f, -6f), new Vector2(-12f, 6f),
new Vector2( 12f, 6f), new Vector2( 12f, -6f),
});
RoomVisibleArea visibleArea = GetOrAddComponent<RoomVisibleArea>(boundaryT.gameObject);
AssignReference(roomCamera, "_visibleArea", visibleArea);
AssignReference(confiner, "m_BoundingShape2D", boundaryCollider);
// Disable stray Camera / AudioListener components sometimes added by Cinemachine
UnityEngine.Camera staleCam = roomCameraGo.GetComponent<UnityEngine.Camera>();
if (staleCam != null) staleCam.enabled = false;
AudioListener staleAl = roomCameraGo.GetComponent<AudioListener>();
if (staleAl != null) { Undo.DestroyObjectImmediate(staleAl); }
AssignReference(cameraArea, "_confinerCollider", boundaryCollider);
// ── [SpawnPoints] ──────────────────────────────────────────────
Transform spawnGroup = GetOrCreateChild(root.transform, "[SpawnPoints]");
@@ -250,7 +269,7 @@ namespace BaseGames.Editor
GetOrCreateChild(root.transform, "[Transitions]");
// ── Wire RoomController ────────────────────────────────────────
AssignReference(roomController, "_roomCamera", roomCamera);
AssignReference(roomController, "_cameraArea", cameraArea);
SerializedObject roomSO = new SerializedObject(roomController);
SerializedProperty spawnArrayProp = roomSO.FindProperty("_spawnPoints");
@@ -263,8 +282,7 @@ namespace BaseGames.Editor
// ── Report ─────────────────────────────────────────────────────
report.Add("在 RoomController._roomId 填写唯一房间 ID如 \"Room_Forest_01\")。");
report.Add("将 Player/CameraFollowTarget Transform 拖入 CinemachineCamera.Follow 字段以跟随玩家(或使用 BaseGames → Camera → Room Camera Setup 工具批量赋值)。");
report.Add("调整 RoomBoundary PolygonCollider2D 顶点以匹配实际房间大小。");
report.Add("调整 AreaBoundary PolygonCollider2D 顶点以匹配实际房间大小。");
report.Add("使用 Tile Palette 在 Ground Tilemap 上绘制地形,然后在 NavSurface Inspector 中点击 Bake。");
report.Add("[Transitions] 子节点下使用 BaseGames/Scene/Place/Room Transition 添加过渡点。");
@@ -561,6 +579,34 @@ namespace BaseGames.Editor
Debug.LogWarning($"[SceneScaffoldTools] {scaffoldName} 完成,但仍有 {report.Count} 项需要手工确认:\n- {string.Join("\n- ", report)}", root);
}
/// <summary>
/// 为 VCam 上的 CinemachinePositionComposer 写入初始默认展示参数。
/// 这些値与 <see cref="CameraArea"/> 的默认値一致,确保脆架生成后 Scene 预览即有正确感觉。
/// 运行时 CameraStateController.ConfigureSlot 会在每次 SwitchArea 时用 per-area 配置覆写。
/// </summary>
private static void ApplyComposerDefaults(CinemachinePositionComposer composer)
{
if (composer == null) return;
// 屏幕位置:玩家稍低于中心,上方有更多视野
var comp = composer.Composition;
comp.ScreenPosition = new Vector2(0f, -0.15f);
comp.DeadZone.Enabled = true;
comp.DeadZone.Size = new Vector2(0.15f, 0.05f);
composer.Composition = comp;
// 阻尼X 轻度缓冲Y = 0由 CameraAsymmetricDampingExtension 接管非对称 Y 阻尼)
composer.Damping = new Vector3(0.5f, 0f, 0f);
// Lookahead水平引领预测开启IgnoreY = true平台游戏 Y 轴不预测,避免起跳时镜头猛拉)
var lah = composer.Lookahead;
lah.Enabled = true;
lah.Time = 0.28f;
lah.Smoothing = 5f;
lah.IgnoreY = true;
composer.Lookahead = lah;
}
}
}