chore: initial commit

This commit is contained in:
2026-05-08 11:04:00 +08:00
commit f55d2a57c3
6278 changed files with 866081 additions and 0 deletions

View File

View File

@@ -0,0 +1,17 @@
{
"excludePlatforms": [],
"allowUnsafeCode": false,
"precompiledReferences": [],
"name": "BaseGames.Camera",
"defineConstraints": [],
"noEngineReferences": false,
"versionDefines": [],
"rootNamespace": "BaseGames.Camera",
"references": [
"BaseGames.Core.Events",
"Unity.Cinemachine"
],
"autoReferenced": true,
"overrideReferences": false,
"includePlatforms": []
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5b9cbc0f2e569d64a862f3b7f417c7b6
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
using UnityEngine;
using Unity.Cinemachine;
namespace BaseGames.Camera
{
[CreateAssetMenu(menuName = "Camera/BlendProfile")]
public class CameraBlendProfileSO : ScriptableObject
{
public CinemachineBlendDefinition.Styles Style = CinemachineBlendDefinition.Styles.EaseInOut;
public float BlendTime = 0.5f;
[Tooltip("Style = Custom 时使用")]
public AnimationCurve CustomCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
/// <summary>转换为 Cinemachine 混合定义。</summary>
public CinemachineBlendDefinition ToBlendDefinition()
{
return new CinemachineBlendDefinition
{
Style = this.Style,
Time = this.BlendTime,
CustomCurve = this.Style == CinemachineBlendDefinition.Styles.Custom ? CustomCurve : null
};
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 04f7b183b6d364d4ea85283d30339db7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
using UnityEngine;
namespace BaseGames.Camera
{
[CreateAssetMenu(menuName = "Camera/CameraConfig")]
public class CameraConfigSO : ScriptableObject
{
[Header("跟随")]
public float FollowDamping = 0.15f;
public float LookAheadTime = 0.3f;
public float LookAheadSmoothing = 0.1f;
public Vector2 DeadZoneSize = new Vector2(1f, 0.5f);
public Vector2 SoftZoneSize = new Vector2(2.5f, 2f);
[Header("偏移")]
public float LookDownOffset = -1.5f;
public float LookUpOffset = 1.5f;
[Header("画面抖动默认强度")]
public float DefaultImpulseStrength = 0.3f;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b358a30ac16c6a34fb673ede0a288e48
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,87 @@
using System.Collections.Generic;
using UnityEngine;
using Unity.Cinemachine;
namespace BaseGames.Camera
{
/// <summary>
/// 相机状态单例控制器。管理房间相机切换、限位器更新与屏幕抖动。
/// 须放置在持久化场景中。
/// </summary>
[DefaultExecutionOrder(-100)]
public class CameraStateController : MonoBehaviour
{
public static CameraStateController Instance { get; private set; }
[Header("引用")]
[SerializeField] private CinemachineBrain _brain;
[SerializeField] private CinemachineImpulseSource _impulseSource;
[Header("默认混合配置")]
[SerializeField] private CameraBlendProfileSO _defaultBlendProfile;
// ── 注册表 ────────────────────────────────────────────────────────────
private readonly HashSet<RoomCamera> _registeredCameras = new HashSet<RoomCamera>();
private RoomCamera _activeCamera;
// ── Unity Lifecycle ───────────────────────────────────────────────────
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
}
private void OnDestroy()
{
if (Instance == this) Instance = null;
}
// ── 公开 API ──────────────────────────────────────────────────────────
/// <summary>向控制器注册一个房间相机(可选,也可由触发器直接调用 SwitchRoom。</summary>
public void RegisterRoomCamera(RoomCamera camera)
{
if (camera != null) _registeredCameras.Add(camera);
}
/// <summary>注销房间相机。</summary>
public void UnregisterRoomCamera(RoomCamera camera)
{
if (camera != null) _registeredCameras.Remove(camera);
}
/// <summary>切换到目标房间相机,并应用对应的混合配置。</summary>
public void SwitchRoom(RoomCamera targetCamera)
{
if (targetCamera == null || targetCamera == _activeCamera) return;
// 应用混合配置到 Brain
if (_brain != null)
{
var profile = targetCamera.BlendProfile ?? _defaultBlendProfile;
if (profile != null)
_brain.DefaultBlend = profile.ToBlendDefinition();
}
// 禁用旧相机、启用新相机
_activeCamera?.Deactivate();
_activeCamera = targetCamera;
_activeCamera.Activate();
}
/// <summary>触发屏幕抖动。</summary>
public void TriggerImpulse(Vector3 velocity)
{
if (_impulseSource != null)
_impulseSource.GenerateImpulse(velocity);
}
/// <summary>以默认强度触发屏幕抖动。</summary>
public void TriggerImpulse(float strength = 0.3f)
=> TriggerImpulse(Vector3.down * strength);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 49f718c655d71394ea13e312a2dd9eed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,42 @@
using UnityEngine;
namespace BaseGames.Camera
{
/// <summary>
/// 相机区域切换触发器。玩家进入时通知 CameraStateController 切换到目标房间相机。
/// [ExecuteAlways] 确保编辑器中 Gizmo 立即更新。
/// </summary>
[ExecuteAlways]
[RequireComponent(typeof(BoxCollider2D))]
public class CameraTriggerZone : MonoBehaviour
{
[SerializeField] private RoomCamera _targetCamera;
[SerializeField] private string _playerTag = "Player";
private BoxCollider2D _collider;
private void Awake()
{
_collider = GetComponent<BoxCollider2D>();
_collider.isTrigger = true;
}
private void OnTriggerEnter2D(Collider2D other)
{
if (!Application.isPlaying) return;
if (!other.CompareTag(_playerTag)) return;
if (_targetCamera != null)
CameraStateController.Instance?.SwitchRoom(_targetCamera);
}
private void OnDrawGizmos()
{
if (_collider == null) _collider = GetComponent<BoxCollider2D>();
Gizmos.color = new Color(0.2f, 0.8f, 1f, 0.25f);
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawCube(_collider.offset, _collider.size);
Gizmos.color = new Color(0.2f, 0.8f, 1f, 0.8f);
Gizmos.DrawWireCube(_collider.offset, _collider.size);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 108d2b73047255f44a823dbcdea4a7fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using UnityEngine;
using Unity.Cinemachine;
namespace BaseGames.Camera
{
/// <summary>
/// 单房间虚拟相机。激活时提升优先级,停用时降为 0。
/// 挂载在每个房间的 CinemachineCamera GameObject 上。
/// </summary>
[RequireComponent(typeof(CinemachineCamera))]
public class RoomCamera : MonoBehaviour
{
[Header("房间设置")]
[SerializeField] private RoomVisibleArea _visibleArea;
[SerializeField] private Vector2 _cameraOffset = Vector2.zero;
[SerializeField] private CameraBlendProfileSO _blendProfile;
[SerializeField] private int _activePriority = 15;
private CinemachineCamera _vcam;
private void Awake() => _vcam = GetComponent<CinemachineCamera>();
private void OnEnable() => _vcam.Priority = _activePriority;
private void OnDisable() => _vcam.Priority = 0;
public PolygonCollider2D ConfinerCollider => _visibleArea?.Collider;
public Vector2 CameraOffset => _cameraOffset;
public CameraBlendProfileSO BlendProfile => _blendProfile;
/// <summary>在 CameraStateController 管理的激活流程中调用。</summary>
public void Activate() => gameObject.SetActive(true);
public void Deactivate() => gameObject.SetActive(false);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: af7e12583264b8c4da8dcd69df274793
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
using UnityEngine;
namespace BaseGames.Camera
{
/// <summary>
/// 标记房间的可见区域(多边形)。供 CinemachineConfiner2D 使用。
/// [ExecuteAlways] 确保编辑器中碰撞体立即更新。
/// </summary>
[ExecuteAlways]
[RequireComponent(typeof(PolygonCollider2D))]
public class RoomVisibleArea : MonoBehaviour
{
private PolygonCollider2D _collider;
private void Awake()
{
_collider = GetComponent<PolygonCollider2D>();
_collider.isTrigger = true;
}
public PolygonCollider2D Collider
{
get
{
if (_collider == null) _collider = GetComponent<PolygonCollider2D>();
return _collider;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 38af2eabab7039c4a919181e4c507d12
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
// Placeholder to prevent asmdef-no-scripts warning.
namespace BaseGames.Camera { }

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5097f44608b602a46a8b8304e2edf090
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: