using UnityEngine; using UnityEngine.Rendering.PostProcessing; using Cinemachine; namespace Game { /// /// 主相机及后处理在此管理 /// public class CameraManager : ManagerBase { public GameCamera MGameCamera; private PostProcessVolume _mPostProcessVolume; private Camera _mMainCamera; private CinemachineVirtualCamera _mMainCameraVirtual; private CinemachineTargetGroup _mMainCameraGroup; private CinemachineImpulseSource _mMainCollisionImpulseSource; private Transform[] _mTargets = new Transform[2];//TODO 可扩展性 private Transform[] _mTargetsAgent = new Transform[2];//TODO 可扩展性 public CameraManager() { } public override void OnCreate() { var cameraRoot = GameObject.Find("CameraRoot"); Object.DontDestroyOnLoad(cameraRoot); _mMainCamera = cameraRoot.transform.Find("Camera_Main").GetComponent(); _mMainCameraVirtual = cameraRoot.transform.Find("Camera_Virtual").GetComponent(); _mMainCollisionImpulseSource = cameraRoot.transform.Find("Camera_Virtual").GetComponent(); _mMainCameraGroup = cameraRoot.transform.Find("Camera_Group").GetComponent(); _mMainCameraGroup.m_Targets = new CinemachineTargetGroup.Target[2]; MGameCamera = _mMainCamera.GetComponent(); MGameCamera.material.SetVector("_ScreenSize", new Vector4(Screen.width, Screen.height, 0, 0)); _mPostProcessVolume = _mMainCamera.GetComponent(); //TODO 有两个以上锁定目标时优化 var newTargt0 = PrefabManager.Instance.CreateGo("CameraTarget"); var newTargt1 = PrefabManager.Instance.CreateGo("CameraTarget"); newTargt0.transform.parent = cameraRoot.transform; newTargt1.transform.parent = cameraRoot.transform; _mTargetsAgent[0] = newTargt0.transform; _mTargetsAgent[1] = newTargt1.transform; _mMainCameraGroup.m_Targets[0].target = _mTargetsAgent[0]; _mMainCameraGroup.m_Targets[0].weight = 1; _mMainCameraGroup.m_Targets[0].radius = 2.5f; _mMainCameraGroup.m_Targets[1].target = _mTargetsAgent[1]; _mMainCameraGroup.m_Targets[1].weight = 1; _mMainCameraGroup.m_Targets[1].radius = 2.5f; //默认设置 TODO 好像没有用 // var brain = m_MainCamera.GetComponent(); // CinemachineImpulseManager.Instance.IgnoreTimeScale = true; // brain.m_UpdateMethod = CinemachineBrain.UpdateMethod.LateUpdate; // brain.m_IgnoreTimeScale = true; } public override void Update() { UpdateCameraTarget();//更新相机锁定目标 } public override void FixedUpdate() { if (Util.IsLevelLoading()) { return; } // UpdataBackground();//更新差速滚轴 } public override void OnDestroy() { } public void SetMainTarget(Transform target) { _mTargets[0] = target; } public void SetSubTarget(Transform target) { _mTargets[1] = target; } public void Shake() { _mMainCollisionImpulseSource.GenerateImpulse(); } public Vector3 GetScreenPos(Vector3 pos) { var ret = _mMainCamera.WorldToScreenPoint(pos); ret = new Vector3(ret.x, Screen.height - ret.y, ret.z); return ret; } public T GetPostProcessSetting() where T : PostProcessEffectSettings { return _mPostProcessVolume.profile.GetSetting(); } public CinemachineVirtualCamera GetVirtualCamera() { return _mMainCameraVirtual; } private void UpdateCameraTarget() { if (_mTargets[0] == null) { return; } if (_mTargets[1] == null) { _mTargets[1] = _mTargets[0]; } _mTargetsAgent[0].position = _mTargets[0].position; _mTargetsAgent[1].position = _mTargets[1].position; ClampToLevel(_mTargetsAgent[0]); ClampToLevel(_mTargetsAgent[1]); } private void ClampToLevel(Transform transform) { var pos = transform.position; var start = pos + Vector3.up; var x = pos.x; var z = pos.z; RaycastHit hitInfo; if (Physics.Raycast(start, Vector3.back, out hitInfo, GameConst.LevelCameraOffsetZ, UtilPhysics.LayerMaskWall)) { z = Mathf.Max(z, hitInfo.point.z + GameConst.LevelCameraOffsetZ); } if (Physics.Raycast(start, Vector3.left, out hitInfo, GameConst.LevelCameraOffsetX, UtilPhysics.LayerMaskWall)) { x = Mathf.Max(x, hitInfo.point.x + GameConst.LevelCameraOffsetX); } else if (Physics.Raycast(start, Vector3.right, out hitInfo, GameConst.LevelCameraOffsetX, UtilPhysics.LayerMaskWall)) { x = Mathf.Min(x, hitInfo.point.x - GameConst.LevelCameraOffsetX); } transform.position = new Vector3(x, 0, z); } } public abstract partial class Util { public static void SetMainTarget(Transform target) { CameraManager.Instance.SetMainTarget(target); } public static void SetSubTarget(Transform target) { CameraManager.Instance.SetSubTarget(target); } public static void Shake() { CameraManager.Instance.Shake(); } public static Vector3 GetScreenPos(Vector3 pos) { return CameraManager.Instance.GetScreenPos(pos); } public static T GetPostProcessSetting() where T : PostProcessEffectSettings { return CameraManager.Instance.GetPostProcessSetting(); } public static CinemachineVirtualCamera GetVirtualCamera() { return CameraManager.Instance.GetVirtualCamera(); } } }