From db481ae0a8428a2d48ad37174ede1d56015c1334 Mon Sep 17 00:00:00 2001 From: SepComet <202308010230@stu.csust.edu.cn> Date: Wed, 10 Jun 2026 09:55:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=95=E5=85=A5=20Cinemachine=20=E5=92=8C=20?= =?UTF-8?q?CameraModule=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=91=84=E5=83=8F?= =?UTF-8?q?=E6=9C=BA=E8=B7=9F=E9=9A=8F=E7=BC=93=E5=8A=A8=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/GameMain/Entities/Player.prefab | 129 ------ .../Scripts/Procedure/Game/ProcedureGame.cs | 2 + .../Scripts/Runtime/Base/GameEntry.Custom.cs | 4 + .../Runtime/CustomComponent/CameraModule.meta | 8 + .../CameraModule/CameraModuleComponent.cs | 188 +++++++++ .../CameraModuleComponent.cs.meta | 11 + .../Scripts/Runtime/SepCore.Runtime.asmdef | 6 +- Assets/Launcher.unity | 381 +++++++++++------- Assets/Plugins/CameraModule.meta | 8 + Assets/Plugins/CameraModule/Base.meta | 8 + .../CameraModule/Base/CameraEffectSettings.cs | 56 +++ .../Base/CameraEffectSettings.cs.meta | 11 + .../CameraModule/Base/CameraEffectType.cs | 18 + .../Base/CameraEffectType.cs.meta | 11 + .../CameraModule/Base/ICameraController.cs | 45 +++ .../Base/ICameraController.cs.meta | 11 + .../Base/SepCore.CameraModule.Base.asmdef | 17 + .../SepCore.CameraModule.Base.asmdef.meta | 7 + Assets/Plugins/CameraModule/Runtime.meta | 8 + .../Runtime/CinemachineCameraController.cs | 217 ++++++++++ .../CinemachineCameraController.cs.meta | 11 + .../Runtime/SepCore.CameraModule.asmdef | 18 + .../Runtime/SepCore.CameraModule.asmdef.meta | 7 + Assets/Plugins/CameraModule/接入说明.md | 69 ++++ Assets/Plugins/CameraModule/接入说明.md.meta | 7 + Packages/manifest.json | 1 + Packages/packages-lock.json | 9 + 27 files changed, 999 insertions(+), 269 deletions(-) create mode 100644 Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule.meta create mode 100644 Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule/CameraModuleComponent.cs create mode 100644 Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule/CameraModuleComponent.cs.meta create mode 100644 Assets/Plugins/CameraModule.meta create mode 100644 Assets/Plugins/CameraModule/Base.meta create mode 100644 Assets/Plugins/CameraModule/Base/CameraEffectSettings.cs create mode 100644 Assets/Plugins/CameraModule/Base/CameraEffectSettings.cs.meta create mode 100644 Assets/Plugins/CameraModule/Base/CameraEffectType.cs create mode 100644 Assets/Plugins/CameraModule/Base/CameraEffectType.cs.meta create mode 100644 Assets/Plugins/CameraModule/Base/ICameraController.cs create mode 100644 Assets/Plugins/CameraModule/Base/ICameraController.cs.meta create mode 100644 Assets/Plugins/CameraModule/Base/SepCore.CameraModule.Base.asmdef create mode 100644 Assets/Plugins/CameraModule/Base/SepCore.CameraModule.Base.asmdef.meta create mode 100644 Assets/Plugins/CameraModule/Runtime.meta create mode 100644 Assets/Plugins/CameraModule/Runtime/CinemachineCameraController.cs create mode 100644 Assets/Plugins/CameraModule/Runtime/CinemachineCameraController.cs.meta create mode 100644 Assets/Plugins/CameraModule/Runtime/SepCore.CameraModule.asmdef create mode 100644 Assets/Plugins/CameraModule/Runtime/SepCore.CameraModule.asmdef.meta create mode 100644 Assets/Plugins/CameraModule/接入说明.md create mode 100644 Assets/Plugins/CameraModule/接入说明.md.meta diff --git a/Assets/GameMain/Entities/Player.prefab b/Assets/GameMain/Entities/Player.prefab index caa909f..25b64a3 100644 --- a/Assets/GameMain/Entities/Player.prefab +++ b/Assets/GameMain/Entities/Player.prefab @@ -124,134 +124,6 @@ Transform: m_Children: [] m_Father: {fileID: 8294607788038773239} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &5383497626468778460 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 5901618247908801032} - - component: {fileID: 4064848608618185461} - - component: {fileID: 4294245010031275705} - m_Layer: 7 - m_Name: Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &5901618247908801032 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5383497626468778460} - serializedVersion: 2 - m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068} - m_LocalPosition: {x: 0, y: 10, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 9112716898534404901} - m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} ---- !u!20 &4064848608618185461 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5383497626468778460} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0, g: 0, b: 0, a: 1} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_Iso: 200 - m_ShutterSpeed: 0.005 - m_Aperture: 16 - m_FocusDistance: 10 - m_FocalLength: 50 - m_BladeCount: 5 - m_Curvature: {x: 2, y: 11} - m_BarrelClipping: 0.25 - m_Anamorphism: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 50 - field of view: 80 - orthographic: 1 - orthographic size: 10 - m_Depth: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!114 &4294245010031275705 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5383497626468778460} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} - m_Name: - m_EditorClassIdentifier: - m_RenderShadows: 1 - m_RequiresDepthTextureOption: 2 - m_RequiresOpaqueTextureOption: 2 - m_CameraType: 0 - m_Cameras: [] - m_RendererIndex: -1 - m_VolumeLayerMask: - serializedVersion: 2 - m_Bits: 1 - m_VolumeTrigger: {fileID: 0} - m_VolumeFrameworkUpdateModeOption: 2 - m_RenderPostProcessing: 0 - m_Antialiasing: 0 - m_AntialiasingQuality: 2 - m_StopNaN: 0 - m_Dithering: 0 - m_ClearDepth: 1 - m_AllowXRRendering: 1 - m_AllowHDROutput: 1 - m_UseScreenCoordOverride: 0 - m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} - m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} - m_RequiresDepthTexture: 0 - m_RequiresColorTexture: 0 - m_Version: 2 - m_TaaSettings: - m_Quality: 3 - m_FrameInfluence: 0.1 - m_JitterScale: 1 - m_MipBias: 0 - m_VarianceClampScale: 0.9 - m_ContrastAdaptiveSharpening: 0 --- !u!1 &6372140121958224629 GameObject: m_ObjectHideFlags: 0 @@ -390,7 +262,6 @@ Transform: m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: - - {fileID: 5901618247908801032} - {fileID: 8294607788038773239} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs b/Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs index e364516..5eb3d24 100644 --- a/Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs +++ b/Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs @@ -113,6 +113,7 @@ namespace SepCore.Procedure GameEntry.UIRouter.CloseUIAsync(UIFormType.HudForm).Forget(); + GameEntry.CameraModule?.SetTarget(null); Player = null; GameEntry.SimulationWorld?.ClearSimulationState(); @@ -126,6 +127,7 @@ namespace SepCore.Procedure try { Player = await GameEntry.Entity.ShowPlayerAsync(_currentPlayerData); + GameEntry.CameraModule?.SetTarget(Player != null ? Player.CachedTransform : null); await GameEntry.UIRouter.OpenUIAsync(UIFormType.HudForm); int selectedRoleId = procedureOwner.GetData("SelectedRoleId").Value; diff --git a/Assets/GameMain/Scripts/Runtime/Base/GameEntry.Custom.cs b/Assets/GameMain/Scripts/Runtime/Base/GameEntry.Custom.cs index 6b6f9ba..141a42d 100644 --- a/Assets/GameMain/Scripts/Runtime/Base/GameEntry.Custom.cs +++ b/Assets/GameMain/Scripts/Runtime/Base/GameEntry.Custom.cs @@ -3,6 +3,7 @@ using SepCore.DamageText; using SepCore.EnemyManager; using SepCore.HPBar; using SepCore.InputModule.Runtime; +using SepCore.CameraModule; using SepCore.SpriteCache; using SepCore.UIRouter; using SepCore.Simulation; @@ -28,6 +29,8 @@ public partial class GameEntry public static InputModuleComponent InputModule { get; private set; } + public static CameraModuleComponent CameraModule { get; private set; } + private static void InitCustomComponents() { BuiltinData = UnityGameFramework.Runtime.GameEntry.GetComponent(); @@ -38,5 +41,6 @@ public partial class GameEntry SpriteCache = UnityGameFramework.Runtime.GameEntry.GetComponent(); UIRouter = UnityGameFramework.Runtime.GameEntry.GetComponent(); InputModule = UnityGameFramework.Runtime.GameEntry.GetComponent(); + CameraModule = UnityGameFramework.Runtime.GameEntry.GetComponent(); } } diff --git a/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule.meta b/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule.meta new file mode 100644 index 0000000..0dcd557 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2c8aaad9a99f4e65a6ef8c47bc18873e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule/CameraModuleComponent.cs b/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule/CameraModuleComponent.cs new file mode 100644 index 0000000..1460d55 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule/CameraModuleComponent.cs @@ -0,0 +1,188 @@ +using UnityEngine; +using UnityGameFramework.Runtime; +using Object = UnityEngine.Object; + +namespace SepCore.CameraModule +{ + /// + /// UnityGameFramework 侧的相机模块组件。 + /// 作为 GameEntry.CameraModule 访问入口,统一持有并转发 CameraModule 控制器能力。 + /// + [DisallowMultipleComponent] + public class CameraModuleComponent : GameFrameworkComponent + { + [SerializeField] private CinemachineCameraController _cinemachineController; + [SerializeField] private bool _autoSearchController = true; + [SerializeField] private bool _logMissingControllerWarnings = true; + + private ICameraController _controller; + private bool _hasLoggedMissingController; + + public ICameraController Controller + { + get + { + ResolveController(false); + return IsControllerValid(_controller) ? _controller : null; + } + } + + public bool HasController => Controller != null; + + public Transform Target => Controller?.Target; + + public CameraEffectSettings CurrentSettings => Controller?.CurrentSettings ?? CameraEffectSettings.Default; + + protected override void Awake() + { + base.Awake(); + ResolveController(false); + } + + public void RegisterController(ICameraController controller) + { + if (!IsControllerValid(controller)) + { + Log.Warning("CameraModuleComponent.RegisterController() controller is invalid."); + return; + } + + _controller = controller; + _hasLoggedMissingController = false; + if (controller is CinemachineCameraController cinemachineController) + { + _cinemachineController = cinemachineController; + } + } + + public void UnregisterController(ICameraController controller) + { + if (controller != null && !ReferenceEquals(_controller, controller)) + { + return; + } + + _controller = null; + _cinemachineController = null; + } + + public void SetTarget(Transform target) + { + if (!EnsureController()) + { + return; + } + + _controller.SetTarget(target); + } + + public void ApplySettings(CameraEffectSettings settings) + { + if (!EnsureController()) + { + return; + } + + _controller.ApplySettings(settings); + } + + public void EnableEffect(CameraEffectType effect) + { + if (!EnsureController()) + { + return; + } + + _controller.EnableEffect(effect); + } + + public void DisableEffect(CameraEffectType effect) + { + if (!EnsureController()) + { + return; + } + + _controller.DisableEffect(effect); + } + + public bool IsEffectEnabled(CameraEffectType effect) + { + return EnsureController() && _controller.IsEffectEnabled(effect); + } + + private bool EnsureController() + { + ResolveController(_logMissingControllerWarnings); + return IsControllerValid(_controller); + } + + private void ResolveController(bool logWarning) + { + if (IsControllerValid(_controller)) + { + return; + } + + if (_cinemachineController != null) + { + _controller = _cinemachineController; + _hasLoggedMissingController = false; + return; + } + + if (!_autoSearchController) + { + LogMissingController(logWarning); + return; + } + + _cinemachineController = GetComponentInChildren(true); + if (_cinemachineController == null) + { +#if UNITY_2023_1_OR_NEWER + _cinemachineController = FindFirstObjectByType(FindObjectsInactive.Include); +#else + _cinemachineController = FindObjectOfType(true); +#endif + } + + if (_cinemachineController != null) + { + _controller = _cinemachineController; + _hasLoggedMissingController = false; + return; + } + + LogMissingController(logWarning); + } + + private void LogMissingController(bool logWarning) + { + if (!logWarning || _hasLoggedMissingController) + { + return; + } + + _hasLoggedMissingController = true; + Log.Warning( + "CameraModuleComponent requires a CinemachineCameraController. " + + "Assign one in Inspector or place one in the loaded scene."); + } + + private static bool IsControllerValid(ICameraController controller) + { + if (controller == null) + { + return false; + } + + if (controller is Object unityObject && unityObject == null) + { + return false; + } + + return true; + } + } +} diff --git a/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule/CameraModuleComponent.cs.meta b/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule/CameraModuleComponent.cs.meta new file mode 100644 index 0000000..38d9ba4 --- /dev/null +++ b/Assets/GameMain/Scripts/Runtime/CustomComponent/CameraModule/CameraModuleComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b77e5f4f170e44f38f20d5ac2dd287e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Runtime/SepCore.Runtime.asmdef b/Assets/GameMain/Scripts/Runtime/SepCore.Runtime.asmdef index 307dd03..4d689ad 100644 --- a/Assets/GameMain/Scripts/Runtime/SepCore.Runtime.asmdef +++ b/Assets/GameMain/Scripts/Runtime/SepCore.Runtime.asmdef @@ -11,7 +11,9 @@ "GUID:6055be8ebefd69e48b49212b09b47b2f", "GUID:fca0f81bc71f1944887dd65f134c54a0", "GUID:47a82ffa13c291447ab895cd0bc251cd", - "GUID:d54b9488b03814a44ab937f0aeb738b1" + "GUID:d54b9488b03814a44ab937f0aeb738b1", + "GUID:0e6a2ce06de727c44965fbc35958920f", + "GUID:1ddd9fc6811c1d14bbde99bd57869070" ], "includePlatforms": [], "excludePlatforms": [], @@ -22,4 +24,4 @@ "defineConstraints": [], "versionDefines": [], "noEngineReferences": false -} \ No newline at end of file +} diff --git a/Assets/Launcher.unity b/Assets/Launcher.unity index a3ccad9..e463d15 100644 --- a/Assets/Launcher.unity +++ b/Assets/Launcher.unity @@ -244,6 +244,7 @@ Transform: - {fileID: 477326942} - {fileID: 1652245191} - {fileID: 1245211031} + - {fileID: 1170305582} m_Father: {fileID: 1852670053} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &120093239 @@ -1124,6 +1125,54 @@ LightingSettings: m_PVRTiledBaking: 0 m_NumRaysToShootPerTexel: -1 m_RespectSceneVisibilityWhenBakingGI: 0 +--- !u!1 &1170305581 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1170305582} + - component: {fileID: 1170305583} + m_Layer: 0 + m_Name: CameraModule + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1170305582 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1170305581} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 2103467907} + m_Father: {fileID: 119167776} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1170305583 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1170305581} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b77e5f4f170e44f38f20d5ac2dd287e7, type: 3} + m_Name: + m_EditorClassIdentifier: + _cinemachineController: {fileID: 2103467908} + _autoSearchController: 0 + _logMissingControllerWarnings: 1 --- !u!1 &1245211030 GameObject: m_ObjectHideFlags: 0 @@ -1174,143 +1223,6 @@ MonoBehaviour: _loadBindingOverridesOnInit: 1 _saveBindingOverridesOnDestroy: 0 _bindingOverrideSettingKey: SepCore.InputModule.BindingOverrides ---- !u!1 &1433036105 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1433036109} - - component: {fileID: 1433036108} - - component: {fileID: 1433036107} - - component: {fileID: 1433036106} - m_Layer: 0 - m_Name: Camera - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &1433036106 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1433036105} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} - m_Name: - m_EditorClassIdentifier: - m_RenderShadows: 1 - m_RequiresDepthTextureOption: 2 - m_RequiresOpaqueTextureOption: 2 - m_CameraType: 0 - m_Cameras: [] - m_RendererIndex: -1 - m_VolumeLayerMask: - serializedVersion: 2 - m_Bits: 1 - m_VolumeTrigger: {fileID: 0} - m_VolumeFrameworkUpdateModeOption: 2 - m_RenderPostProcessing: 0 - m_Antialiasing: 0 - m_AntialiasingQuality: 2 - m_StopNaN: 0 - m_Dithering: 0 - m_ClearDepth: 1 - m_AllowXRRendering: 1 - m_AllowHDROutput: 1 - m_UseScreenCoordOverride: 0 - m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} - m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} - m_RequiresDepthTexture: 0 - m_RequiresColorTexture: 0 - m_Version: 2 - m_TaaSettings: - m_Quality: 3 - m_FrameInfluence: 0.1 - m_JitterScale: 1 - m_MipBias: 0 - m_VarianceClampScale: 0.9 - m_ContrastAdaptiveSharpening: 0 ---- !u!81 &1433036107 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1433036105} - m_Enabled: 1 ---- !u!20 &1433036108 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1433036105} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_Iso: 200 - m_ShutterSpeed: 0.005 - m_Aperture: 16 - m_FocusDistance: 10 - m_FocalLength: 50 - m_BladeCount: 5 - m_Curvature: {x: 2, y: 11} - m_BarrelClipping: 0.25 - m_Anamorphism: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &1433036109 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1433036105} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -5.5118976, y: 1.6327388, z: 10.270648} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1454214586 GameObject: m_ObjectHideFlags: 0 @@ -1676,10 +1588,203 @@ MonoBehaviour: - _uiFormType: 206 _controllerTypeName: SepCore.UI.JoystickController, SepCore.Presentation, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null +--- !u!1 &2103467906 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2103467907} + - component: {fileID: 2103467911} + - component: {fileID: 2103467909} + - component: {fileID: 2103467908} + - component: {fileID: 2103467910} + - component: {fileID: 2103467912} + m_Layer: 0 + m_Name: Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2103467907 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2103467906} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 5, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1170305582} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2103467908 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2103467906} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 72dbf93744f52c94ca50331c526685e9, type: 3} + m_Name: + m_EditorClassIdentifier: + _settings: + dampingX: 20 + dampingY: 1 + dampingZ: 20 + offsetStrength: 0 + maxOffsetDistance: 0 + offsetSmoothing: 0.8 + offsetDeadZone: 0.1 + _baseFollowOffset: {x: 0, y: 10, z: 0} +--- !u!114 &2103467909 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2103467906} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 72ece51f2901e7445ab60da3685d6b5f, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ShowDebugText: 0 + m_ShowCameraFrustum: 1 + m_IgnoreTimeScale: 0 + m_WorldUpOverride: {fileID: 0} + m_UpdateMethod: 2 + m_BlendUpdateMethod: 1 + m_DefaultBlend: + m_Style: 1 + m_Time: 2 + m_CustomCurve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_CustomBlends: {fileID: 0} + m_CameraCutEvent: + m_PersistentCalls: + m_Calls: [] + m_CameraActivatedEvent: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &2103467910 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2103467906} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 0 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_AllowHDROutput: 1 + m_UseScreenCoordOverride: 0 + m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 + m_TaaSettings: + m_Quality: 3 + m_FrameInfluence: 0.1 + m_JitterScale: 1 + m_MipBias: 0 + m_VarianceClampScale: 0.9 + m_ContrastAdaptiveSharpening: 0 +--- !u!20 &2103467911 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2103467906} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 50 + field of view: 80 + orthographic: 1 + orthographic size: 10 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!81 &2103467912 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2103467906} + m_Enabled: 1 --- !u!1660057539 &9223372036854775807 SceneRoots: m_ObjectHideFlags: 0 m_Roots: - {fileID: 1852670053} - {fileID: 120093242} - - {fileID: 1433036109} diff --git a/Assets/Plugins/CameraModule.meta b/Assets/Plugins/CameraModule.meta new file mode 100644 index 0000000..8352dff --- /dev/null +++ b/Assets/Plugins/CameraModule.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6a15f5e9feb85bd4eab52916ae709ee3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/CameraModule/Base.meta b/Assets/Plugins/CameraModule/Base.meta new file mode 100644 index 0000000..dc12caa --- /dev/null +++ b/Assets/Plugins/CameraModule/Base.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 306ccbf7cd5a0884e92485e113ae4e1a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/CameraModule/Base/CameraEffectSettings.cs b/Assets/Plugins/CameraModule/Base/CameraEffectSettings.cs new file mode 100644 index 0000000..dcc50c9 --- /dev/null +++ b/Assets/Plugins/CameraModule/Base/CameraEffectSettings.cs @@ -0,0 +1,56 @@ +using System; +using UnityEngine; + +namespace SepCore.CameraModule +{ + /// + /// 相机效果配置参数。 + /// + [Serializable] + public struct CameraEffectSettings + { + [Header("跟随缓动 (FollowDamping)")] + [Tooltip("X 轴阻尼,值越大跟随后的响应越慢")] + [Range(0f, 20f)] + public float dampingX; + + [Tooltip("Y 轴阻尼")] + [Range(0f, 20f)] + public float dampingY; + + [Tooltip("Z 轴阻尼")] + [Range(0f, 20f)] + public float dampingZ; + + [Header("移动方向偏移 (MovementDirectionOffset)")] + [Tooltip("偏移强度系数,值越大偏移越明显")] + [Range(0f, 10f)] + public float offsetStrength; + + [Tooltip("最大偏移距离(世界单位)")] + [Range(0f, 20f)] + public float maxOffsetDistance; + + [Tooltip("偏移平滑速度")] + [Range(0f, 20f)] + public float offsetSmoothing; + + [Tooltip("偏移采样速度低于此值时不产生偏移")] + [Range(0f, 5f)] + public float offsetDeadZone; + + /// + /// 默认配置:适中的阻尼和偏移参数。 + /// + public static CameraEffectSettings Default => new CameraEffectSettings + { + dampingX = 1f, + dampingY = 1f, + dampingZ = 1f, + offsetStrength = 2f, + maxOffsetDistance = 3f, + offsetSmoothing = 5f, + offsetDeadZone = 0.1f, + }; + } +} diff --git a/Assets/Plugins/CameraModule/Base/CameraEffectSettings.cs.meta b/Assets/Plugins/CameraModule/Base/CameraEffectSettings.cs.meta new file mode 100644 index 0000000..a741250 --- /dev/null +++ b/Assets/Plugins/CameraModule/Base/CameraEffectSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d1e0d1682fb702543b5fd918d51c72c4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/CameraModule/Base/CameraEffectType.cs b/Assets/Plugins/CameraModule/Base/CameraEffectType.cs new file mode 100644 index 0000000..e250056 --- /dev/null +++ b/Assets/Plugins/CameraModule/Base/CameraEffectType.cs @@ -0,0 +1,18 @@ +namespace SepCore.CameraModule +{ + /// + /// 相机效果类型,用于开关控制。 + /// + public enum CameraEffectType + { + /// + /// 跟随缓动 —— 相机跟随目标时的阻尼平滑。 + /// + FollowDamping, + + /// + /// 移动方向偏移 —— 相机根据目标移动方向产生额外偏移。 + /// + MovementDirectionOffset, + } +} diff --git a/Assets/Plugins/CameraModule/Base/CameraEffectType.cs.meta b/Assets/Plugins/CameraModule/Base/CameraEffectType.cs.meta new file mode 100644 index 0000000..e5b5db2 --- /dev/null +++ b/Assets/Plugins/CameraModule/Base/CameraEffectType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7676c458713132547a745d42db4cf179 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/CameraModule/Base/ICameraController.cs b/Assets/Plugins/CameraModule/Base/ICameraController.cs new file mode 100644 index 0000000..3332752 --- /dev/null +++ b/Assets/Plugins/CameraModule/Base/ICameraController.cs @@ -0,0 +1,45 @@ +using UnityEngine; + +namespace SepCore.CameraModule +{ + /// + /// 相机控制器接口。Base 层定义,Runtime 层(Cinemachine)实现。 + /// + public interface ICameraController + { + /// + /// 当前跟随目标。 + /// + Transform Target { get; } + + /// + /// 设置跟随目标。传 null 则停止跟随。 + /// + void SetTarget(Transform target); + + /// + /// 启用指定效果。 + /// + void EnableEffect(CameraEffectType effect); + + /// + /// 禁用指定效果。 + /// + void DisableEffect(CameraEffectType effect); + + /// + /// 查询指定效果是否启用。 + /// + bool IsEffectEnabled(CameraEffectType effect); + + /// + /// 应用效果配置参数。会立即生效。 + /// + void ApplySettings(CameraEffectSettings settings); + + /// + /// 当前生效的配置参数。 + /// + CameraEffectSettings CurrentSettings { get; } + } +} diff --git a/Assets/Plugins/CameraModule/Base/ICameraController.cs.meta b/Assets/Plugins/CameraModule/Base/ICameraController.cs.meta new file mode 100644 index 0000000..62977ef --- /dev/null +++ b/Assets/Plugins/CameraModule/Base/ICameraController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3c239333c308a174685e7f732738603b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/CameraModule/Base/SepCore.CameraModule.Base.asmdef b/Assets/Plugins/CameraModule/Base/SepCore.CameraModule.Base.asmdef new file mode 100644 index 0000000..f0e41c4 --- /dev/null +++ b/Assets/Plugins/CameraModule/Base/SepCore.CameraModule.Base.asmdef @@ -0,0 +1,17 @@ +{ + "name": "SepCore.CameraModule.Base", + "rootNamespace": "SepCore.CameraModule", + "references": [ + "GUID:363c5eb08ff8e6a439b85e37b8c20d96", + "GUID:a04b272484018094ab427253f20c416c" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/Assets/Plugins/CameraModule/Base/SepCore.CameraModule.Base.asmdef.meta b/Assets/Plugins/CameraModule/Base/SepCore.CameraModule.Base.asmdef.meta new file mode 100644 index 0000000..edceda6 --- /dev/null +++ b/Assets/Plugins/CameraModule/Base/SepCore.CameraModule.Base.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0e6a2ce06de727c44965fbc35958920f +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/CameraModule/Runtime.meta b/Assets/Plugins/CameraModule/Runtime.meta new file mode 100644 index 0000000..88b1445 --- /dev/null +++ b/Assets/Plugins/CameraModule/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 590eb06964a378441aadf2dae1eebc26 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/CameraModule/Runtime/CinemachineCameraController.cs b/Assets/Plugins/CameraModule/Runtime/CinemachineCameraController.cs new file mode 100644 index 0000000..8f513ae --- /dev/null +++ b/Assets/Plugins/CameraModule/Runtime/CinemachineCameraController.cs @@ -0,0 +1,217 @@ +using Cinemachine; +using UnityEngine; + +namespace SepCore.CameraModule +{ + /// + /// 基于 Cinemachine 的相机控制器。挂载到场景中的主相机上(主相机需有 CinemachineBrain)。 + /// 会在主相机同级自动创建 CinemachineVirtualCamera,避免虚拟相机成为被 Brain 驱动相机的子物体。 + /// + [RequireComponent(typeof(CinemachineBrain))] + public class CinemachineCameraController : MonoBehaviour, ICameraController + { + [SerializeField] private CameraEffectSettings _settings = CameraEffectSettings.Default; + [SerializeField] private Vector3 _baseFollowOffset = new Vector3(0f, 10f, -10f); + [SerializeField] private bool _lockRotation = true; + [SerializeField] private Vector3 _fixedRotationEuler = new Vector3(90f, 0f, 0f); + + private CinemachineVirtualCamera _virtualCamera; + private CinemachineTransposer _transposer; + private bool _followDampingEnabled = true; + private bool _movementDirectionOffsetEnabled = true; + + private Vector3 _currentAppliedOffset; + private Vector3 _previousTargetPosition; + private bool _hasTarget; + + public Transform Target { get; private set; } + public CameraEffectSettings CurrentSettings => _settings; + + private void Awake() + { + CreateVirtualCamera(); + } + + private void OnValidate() + { + ApplyRotationMode(); + } + + private void LateUpdate() + { + if (!_hasTarget || Target == null) + return; + + if (_movementDirectionOffsetEnabled) + UpdateMovementDirectionOffset(); + else + ResetOffsetSmoothly(); + + _previousTargetPosition = Target.position; + + if (_lockRotation) + ApplyFixedRotation(); + } + + public void SetTarget(Transform target) + { + Target = target; + _hasTarget = target != null; + + if (_virtualCamera == null) + return; + + _virtualCamera.Follow = target; + ApplyRotationMode(); + + if (_hasTarget) + { + _previousTargetPosition = target.position; + _currentAppliedOffset = _baseFollowOffset; + _transposer.m_FollowOffset = _baseFollowOffset; + } + } + + public void EnableEffect(CameraEffectType effect) + { + switch (effect) + { + case CameraEffectType.FollowDamping: + _followDampingEnabled = true; + ApplyDampingValues(); + break; + case CameraEffectType.MovementDirectionOffset: + _movementDirectionOffsetEnabled = true; + break; + } + } + + public void DisableEffect(CameraEffectType effect) + { + switch (effect) + { + case CameraEffectType.FollowDamping: + _followDampingEnabled = false; + ApplyDampingValues(); + break; + case CameraEffectType.MovementDirectionOffset: + _movementDirectionOffsetEnabled = false; + break; + } + } + + public bool IsEffectEnabled(CameraEffectType effect) + { + return effect switch + { + CameraEffectType.FollowDamping => _followDampingEnabled, + CameraEffectType.MovementDirectionOffset => _movementDirectionOffsetEnabled, + _ => false, + }; + } + + public void ApplySettings(CameraEffectSettings settings) + { + _settings = settings; + ApplyDampingValues(); + } + + private void CreateVirtualCamera() + { + var go = new GameObject("CM_CameraController_VCam"); + go.transform.SetParent(transform.parent, false); + go.transform.rotation = Quaternion.Euler(_fixedRotationEuler); + _virtualCamera = go.AddComponent(); + + _virtualCamera.m_Lens.FieldOfView = 60f; + + _transposer = _virtualCamera.AddCinemachineComponent(); + _transposer.m_BindingMode = CinemachineTransposer.BindingMode.WorldSpace; + _transposer.m_FollowOffset = _baseFollowOffset; + + ApplyRotationMode(); + + ApplyDampingValues(); + } + + private void ApplyRotationMode() + { + if (_virtualCamera == null) + return; + + if (_lockRotation) + { + _virtualCamera.LookAt = null; + _virtualCamera.DestroyCinemachineComponent(); + ApplyFixedRotation(); + return; + } + + _virtualCamera.LookAt = Target; + + if (_virtualCamera.GetCinemachineComponent() == null) + _virtualCamera.AddCinemachineComponent(); + } + + private void ApplyFixedRotation() + { + if (_virtualCamera == null) + return; + + _virtualCamera.transform.rotation = Quaternion.Euler(_fixedRotationEuler); + } + + private void ApplyDampingValues() + { + if (_transposer == null) + return; + + if (_followDampingEnabled) + { + _transposer.m_XDamping = _settings.dampingX; + _transposer.m_YDamping = _settings.dampingY; + _transposer.m_ZDamping = _settings.dampingZ; + } + else + { + _transposer.m_XDamping = 0f; + _transposer.m_YDamping = 0f; + _transposer.m_ZDamping = 0f; + } + } + + private void UpdateMovementDirectionOffset() + { + float dt = Time.deltaTime; + Vector3 velocity = (Target.position - _previousTargetPosition) / Mathf.Max(dt, 0.0001f); + float speed = new Vector3(velocity.x, 0f, velocity.z).magnitude; + + Vector3 targetOffset = _baseFollowOffset; + + if (speed > _settings.offsetDeadZone) + { + Vector3 dir = new Vector3(velocity.x, 0f, velocity.z).normalized; + float offsetAmount = Mathf.Min(speed * _settings.offsetStrength, _settings.maxOffsetDistance); + targetOffset += dir * offsetAmount; + } + + _currentAppliedOffset = Vector3.Lerp( + _currentAppliedOffset, + targetOffset, + _settings.offsetSmoothing * dt + ); + + _transposer.m_FollowOffset = _currentAppliedOffset; + } + + private void ResetOffsetSmoothly() + { + _currentAppliedOffset = Vector3.Lerp( + _currentAppliedOffset, + _baseFollowOffset, + _settings.offsetSmoothing * Time.deltaTime + ); + _transposer.m_FollowOffset = _currentAppliedOffset; + } + } +} diff --git a/Assets/Plugins/CameraModule/Runtime/CinemachineCameraController.cs.meta b/Assets/Plugins/CameraModule/Runtime/CinemachineCameraController.cs.meta new file mode 100644 index 0000000..45f4f4f --- /dev/null +++ b/Assets/Plugins/CameraModule/Runtime/CinemachineCameraController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 72dbf93744f52c94ca50331c526685e9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/CameraModule/Runtime/SepCore.CameraModule.asmdef b/Assets/Plugins/CameraModule/Runtime/SepCore.CameraModule.asmdef new file mode 100644 index 0000000..3afccad --- /dev/null +++ b/Assets/Plugins/CameraModule/Runtime/SepCore.CameraModule.asmdef @@ -0,0 +1,18 @@ +{ + "name": "SepCore.CameraModule", + "rootNamespace": "SepCore.CameraModule", + "references": [ + "GUID:363c5eb08ff8e6a439b85e37b8c20d96", + "GUID:0e6a2ce06de727c44965fbc35958920f", + "GUID:4307f53044263cf4b835bd812fc161a4" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/Assets/Plugins/CameraModule/Runtime/SepCore.CameraModule.asmdef.meta b/Assets/Plugins/CameraModule/Runtime/SepCore.CameraModule.asmdef.meta new file mode 100644 index 0000000..0b18d14 --- /dev/null +++ b/Assets/Plugins/CameraModule/Runtime/SepCore.CameraModule.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1ddd9fc6811c1d14bbde99bd57869070 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/CameraModule/接入说明.md b/Assets/Plugins/CameraModule/接入说明.md new file mode 100644 index 0000000..cae9f16 --- /dev/null +++ b/Assets/Plugins/CameraModule/接入说明.md @@ -0,0 +1,69 @@ +# CameraModule 接入说明 + +基于 Cinemachine 2.x 的可复用相机插件,提供跟随缓动、移动方向偏移等基础效果,支持开关控制。 + +## 导入步骤 + +1. 将 `Assets/Plugins/CameraModule/` 整个目录导入目标项目 +2. 确保目标项目已安装 `com.unity.cinemachine` 2.x(通过 Package Manager 或 manifest.json 添加) +3. 导入后基座项目仍可正常编译和运行——CameraModule 的 asmdef 独立于基座程序集 + +## 程序集结构 + +``` +SepCore.CameraModule.Base ← 接口与数据类型(无 Cinemachine 依赖) +SepCore.CameraModule ← Cinemachine 实现(依赖 Cinemachine 2.x) +``` + +- `SepCore.CameraModule.Base` 引用 `UnityGameFramework.Runtime` 和 `SepCore.Base` +- `SepCore.CameraModule` 额外引用 `Cinemachine` 和 `SepCore.CameraModule.Base` +- 移除 CameraModule 后,基座程序集不受任何影响 + +## 场景挂载要求 + +1. 在场景主相机上添加 `CinemachineBrain` 组件(如果还没有) +2. 在主相机上添加 `CinemachineCameraController` 组件 +3. 控制器会自动创建 `CinemachineVirtualCamera` 子对象 + +## API 初始化方式 + +```csharp +using SepCore.CameraModule; + +// 获取控制器引用(通常通过 Inspector 拖拽或 GetComponent) +var controller = GetComponent(); + +// 设置跟随目标 +controller.SetTarget(targetTransform); + +// 调整效果参数 +var settings = CameraEffectSettings.Default; +settings.dampingX = 2f; +settings.dampingY = 2f; +settings.dampingZ = 2f; +settings.offsetStrength = 3f; +settings.maxOffsetDistance = 5f; +controller.ApplySettings(settings); + +// 开关控制 +controller.DisableEffect(CameraEffectType.FollowDamping); // 关闭缓动 +controller.EnableEffect(CameraEffectType.FollowDamping); // 开启缓动 +controller.DisableEffect(CameraEffectType.MovementDirectionOffset); // 关闭方向偏移 +``` + +## CameraEffectSettings 参数说明 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `dampingX/Y/Z` | float | 1.0 | 跟随阻尼,值越大响应越慢。设为 0 则无缓动 | +| `offsetStrength` | float | 2.0 | 移动方向偏移强度系数 | +| `maxOffsetDistance` | float | 3.0 | 最大偏移距离(世界单位) | +| `offsetSmoothing` | float | 5.0 | 偏移平滑速度 | +| `offsetDeadZone` | float | 0.1 | 速度低于此值时不产生偏移 | + +## 效果开关 + +通过 `EnableEffect` / `DisableEffect` 控制: + +- `CameraEffectType.FollowDamping` — 跟随缓动。关闭后 damping 设为 0,相机即时跟随 +- `CameraEffectType.MovementDirectionOffset` — 移动方向偏移。关闭后 FollowOffset 平滑回归基础值 diff --git a/Assets/Plugins/CameraModule/接入说明.md.meta b/Assets/Plugins/CameraModule/接入说明.md.meta new file mode 100644 index 0000000..c459bad --- /dev/null +++ b/Assets/Plugins/CameraModule/接入说明.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e84e48de48841ab4b82efdd941a87f2e +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/manifest.json b/Packages/manifest.json index eea7132..df920e8 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -6,6 +6,7 @@ "com.unity.ai.navigation": "1.1.6", "com.unity.analytics": "3.8.1", "com.unity.burst": "1.8.28", + "com.unity.cinemachine": "2.10.7", "com.unity.collab-proxy": "2.11.2", "com.unity.collections": "2.5.7", "com.unity.ide.rider": "3.0.39", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 1dadb8e..41e824e 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -53,6 +53,15 @@ }, "url": "https://packages.unity.cn" }, + "com.unity.cinemachine": { + "version": "2.10.7", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.1.31" + }, + "url": "https://packages.unity.cn" + }, "com.unity.collab-proxy": { "version": "2.11.2", "depth": 0,