using UnityEngine; using Thousandto.Core.Asset; using EventManager = UnityEngine.Gonbest.MagicCube.EventManager; using CoreEventDefine = UnityEngine.Gonbest.MagicCube.CoreEventDefine; namespace Thousandto.Plugins.Common.UniScene { //摄像机控制器 public class CameraControl : MonoBehaviour { #region//私有变量 //锁定的目标 private Transform _targetTrans = null; //当前pitch [SerializeField] private float _curPitch = 0f; //当前yaw [SerializeField] private float _curYaw = 0f; //当前跟随距离 private float _curDis = 0f; //当前Y轴偏移量 [SerializeField] private float _curOffsetY = 1.5f; //当前X轴偏移量 [SerializeField] private float _curOffsetX = 0f; //当前fov [SerializeField] private float _curFov = 0f; //是否锁定 private bool _isLock = false; // private Transform _transFormInst = null; RayCheckModel _rayCheckModel = null; private Camera _curCamera = null; #endregion #region//动画变量 //是否正在播放动画 private bool _isPlayAnim = false; //动画曲线 private AnimationCurve _animCurve = null; //动画时间 private float _animMaxTime = 0.001f; //动画计时器 private float _animTimer = 0f; //原pitch private float _oriPitch = 0f; //目标picth private float _tarPitch = 0f; //原yaw private float _oriYaw = 0f; //目标yaw private float _tarYaw = 0f; //原dis private float _oriDis = 0f; //原fov private float _oriFov = 0f; //目标dis [SerializeField] private float _tarDis = 0f; //原y轴偏移量 private float _oriOffsetY = 0f; //目标y轴偏移量 private float _tarOffsetY = 0f; //原x轴偏移量 private float _oriOffsetX = 0f; //目标x轴偏移量 private float _tarOffsetX = 0f; //目标fov private float _tarFov = 0f; #endregion #region//属性 public Transform TargetTrans { get { return _targetTrans; } } //当前摄像机 public Camera CurCamera { get { return _curCamera; } set { _curCamera = value; } } //当前pitch public float CurPitch { get { return _curPitch; } set { _curPitch = value; } } //当前yaw public float CurYaw { get { return _curYaw; } set { _curYaw = value; } } //当前跟随距离 public float CurDis { get { return _curDis; } set { _curDis = value; _tarDis = value; //Debug.Log("fix yy CurDis 333 " + value.ToString()); } } //当前Y轴偏移量 public float CurOffsetY { get { return _curOffsetY; } set { _curOffsetY = value; _tarOffsetY = value; _oriOffsetY = value; } } //当前X轴偏移量 public float CurOffsetX { get { return _curOffsetX; } set { _curOffsetX = value; } } //当前fov public float CurFov { get { return _curFov; } set { _curFov = value; } } //是否锁定 public bool IsLock { get { return _isLock; } } public Transform TransFormInst { get { if (_transFormInst == null) { _transFormInst = transform; } return _transFormInst; } } public float TarDis { get { return _tarDis; } set { _tarDis = value; //Debug.Log("fix yy TarDis " + value.ToString()); } } private RayCheckModel RayCheckModel { get { if(_rayCheckModel == null) { _rayCheckModel = new RayCheckModel(); } return _rayCheckModel; } } //自由操控模式,进入此模式后摄像机不会做任何限制 public bool FreeMode { get; set; } //是否正在播放动画 public bool IsPlayAnim { get { return _isPlayAnim; } } //特写高度 public float FeatureHeight { get; set; } #endregion #region//私有函数 private void UpdateAnim(float dt) { if (_isPlayAnim) { _animTimer += dt; float lerpValue = 0f; if (_animMaxTime <= 0f) { lerpValue = 1f; _isPlayAnim = false; } else if (_animTimer <= _animMaxTime) { lerpValue = _animTimer / _animMaxTime; if (_animCurve != null) { lerpValue = _animCurve.Evaluate(lerpValue); } } else { lerpValue = 1f; _isPlayAnim = false; } if(_isPlayAnim) { _curPitch = Mathf.Lerp(_oriPitch, _tarPitch, lerpValue); _curYaw = Mathf.Lerp(_oriYaw, _tarYaw, lerpValue); _curDis = Mathf.Lerp(_oriDis, _tarDis, lerpValue); _curOffsetY = Mathf.Lerp(_oriOffsetY, _tarOffsetY, lerpValue); _curOffsetX = Mathf.Lerp(_oriOffsetX, _tarOffsetX, lerpValue); _curFov = Mathf.Lerp(_oriFov, _tarFov, lerpValue); } else { _curPitch = _tarPitch; _curYaw = _tarYaw; _curDis = _tarDis; _curOffsetY = _tarOffsetY; _curOffsetX = _tarOffsetX; _curFov = _tarFov; } } } public void Update() { //屏蔽掉射线处理 //RayCheckModel.UpdateRay(TransFormInst); if (_targetTrans == null) return; if (FreeMode) { var targetPos = _targetTrans.position + Vector3.up * _curOffsetY; Quaternion rot = Quaternion.Euler(CurPitch, CurYaw, 0f); var selfPos = targetPos - rot * Vector3.forward * _curDis; if (_curOffsetX != 0) { var dir = (_targetTrans.position - selfPos); dir.y = 0; dir = Quaternion.AngleAxis(90, Vector3.up) * dir; dir = dir.normalized; targetPos = targetPos + dir * _curOffsetX; selfPos = targetPos - rot * Vector3.forward * _curDis; } if (CurCamera != null && CurCamera.fieldOfView != _curFov) { CurCamera.fieldOfView = _curFov; } TransFormInst.position = selfPos; TransFormInst.rotation = rot; } else { var useOffsetY = _curOffsetY; if (_isPlayAnim) { UpdateAnim(Time.deltaTime); } else { //规范yaw值 if (_curYaw > 0) { _curYaw = _curYaw % 360f; if (_curYaw > 180f) { _curYaw = _curYaw - 360f; } } else if (_curYaw < 0f) { _curYaw = _curYaw % 360; if (_curYaw < -180f) { _curYaw = _curYaw + 360f; } } if (_isLock) { _curYaw = Mathf.Clamp(_curYaw, CameraControlDefine.MinYaw, CameraControlDefine.MaxYaw); //规范跟随距离 _tarDis = Mathf.Clamp(_tarDis, CameraControlDefine.CurMinDis, CameraControlDefine.CurMaxDis); var halfMaxDis = (CameraControlDefine.CurMaxDis - CameraControlDefine.CurMinDis) / 2f; if (_curDis >= halfMaxDis) { _curPitch = CameraControlDefine.LockPitch; useOffsetY = _curOffsetY; } else { _curPitch = Mathf.Lerp(6f, CameraControlDefine.LockPitch, (_curDis - CameraControlDefine.CurMinDis) / halfMaxDis); useOffsetY = Mathf.Lerp(FeatureHeight, _curOffsetY, (_curDis - CameraControlDefine.CurMinDis) / halfMaxDis); } } else { //规范picth值 _curPitch = Mathf.Clamp(_curPitch, CameraControlDefine.ConstMinPitch, CameraControlDefine.ConstMaxPitch); _tarDis = Mathf.Clamp(_tarDis, CameraControlDefine.CurMinDis, CameraControlDefine.ConstMaxFlowDis-3); //fix yy:新增 拉近视角相机跟随到上半身 useOffsetY = Mathf.Lerp(FeatureHeight, _curOffsetY, (_curDis - CameraControlDefine.CurMinDis) / CameraControlDefine.CurMaxDis); } } float oldDis = _curDis; if (_curDis != _tarDis) { if (_curDis > _tarDis) { _curDis -= Time.deltaTime * CameraControlDefine.DisChangeSpeed; if (_curDis <= _tarDis) { _curDis = _tarDis; } } else { _curDis += Time.deltaTime * CameraControlDefine.DisChangeSpeed; if (_curDis >= _tarDis) { _curDis = _tarDis; } } } var targetPos = _targetTrans.position + Vector3.up * useOffsetY; Quaternion rot = Quaternion.Euler(CurPitch, CurYaw, 0f); var selfPos = targetPos - rot * Vector3.forward * _curDis; if (_curOffsetX != 0) { var dir = (_targetTrans.position - selfPos); dir.y = 0; dir = Quaternion.AngleAxis(90, Vector3.up) * dir; dir = dir.normalized; targetPos = targetPos + dir * _curOffsetX; selfPos = targetPos - rot * Vector3.forward * _curDis; } //锁定模式下不做摄像机碰撞 if (!_isLock) { if (Physics.CheckSphere(targetPos, 0.1f, LayerUtils.Terrain_Mask)) { selfPos = targetPos; _curDis = 0f; } else { RaycastHit hit; Ray ray = new Ray(targetPos, selfPos - targetPos); if (Physics.SphereCast(ray, 0.5f, out hit, _curDis, LayerUtils.Terrain_Mask)) { selfPos = targetPos - rot * Vector3.forward * hit.distance; _curDis = hit.distance; } } } if(CurCamera != null && CurCamera.fieldOfView != _curFov) { CurCamera.fieldOfView = _curFov; } TransFormInst.position = selfPos; TransFormInst.rotation = rot; if (oldDis != _curDis) { EventManager.SharedInstance.PushFixEvent(CoreEventDefine.EID_EVENT_CAMERAFOLLOWDIS_CHANGED, _curDis); } } if (AudioPlayer.ChannelManager.RootGo != null) { Transform trans = AudioPlayer.ChannelManager.RootGo.transform; trans.position = TransFormInst.position; } } #endregion #region//公有函数 //设置射线检测 public void SetRayCheckModel(bool isenable) { RayCheckModel.IsEnable = isenable; } //设置射线检测Alpha变化值 public void SetRayAlpha(float alpha) { RayCheckModel.Alpha = alpha; } //设置射线检测变化时间 public void SetRayTime(float offsettime) { RayCheckModel.ChangeTime = offsettime; } //设置跟随目标 public void SetTarget(Transform target) { if (target != null) { _targetTrans = target; } } //改变锁定状态 public void ChangeLockState(bool state) { _isLock = state; if (_isLock) { SetFarViewState(CameraControlDefine.IsFarView); } else { PlayAnim(CameraControlDefine.ConstDefaultPitch, CameraControlDefine.ConstDefaultYaw, CameraControlDefine.ConstDefaultFlowDis, _curOffsetX, _curOffsetY, CameraControlDefine.CurFov, 0.5f); } EventManager.SharedInstance.PushFixEvent(CoreEventDefine.EID_EVENT_CAMERALOCKSTATE_CHANGED, _isLock); } public void SetFarViewState(bool state) { CameraControlDefine.IsFarView = state; _curYaw = CameraControlDefine.LockYaw; _curPitch = CameraControlDefine.LockPitch; _curDis = CameraControlDefine.CurMaxDis - 1f; PlayAnim(CameraControlDefine.LockPitch, CameraControlDefine.LockYaw, CameraControlDefine.CurMaxDis, _curOffsetX, _curOffsetY, CameraControlDefine.CurFov, 0.5f); } //播放运动动画 public void PlayAnim(float tarPitch, float tarYaw, float tarDis, float tarOffsetX, float tarOffsetY, float tarFov, float animTime, AnimationCurve curve = null) { //规范yaw值 -180到180 if (_curYaw > 0) { _curYaw = _curYaw % 360f; if (_curYaw > 180f) { _curYaw = _curYaw - 360f; } } else if (_curYaw < 0f) { _curYaw = _curYaw % 360; if (_curYaw < -180f) { _curYaw = _curYaw + 360f; } } //规范yaw值 -180到180 if (tarYaw > 0) { tarYaw = tarYaw % 360f; if (tarYaw > 180f) { tarYaw = tarYaw - 360f; } } else if (tarYaw < 0f) { tarYaw = tarYaw % 360; if (tarYaw < -180f) { tarYaw = tarYaw + 360f; } } var moveAbs = Mathf.Abs(tarYaw - CurYaw); var moveAbs2 = 360f - moveAbs; if (moveAbs2 < moveAbs) { if (tarYaw > CurYaw) { tarYaw = CurYaw - moveAbs2; } else { tarYaw = CurYaw + moveAbs2; } } _oriPitch = _curPitch; _oriYaw = _curYaw; _oriDis = _curDis; _oriOffsetX = _curOffsetX; _oriOffsetY = _curOffsetY; _oriFov = _curFov; if(_oriFov <= 0) { _oriFov = _tarFov; } _tarPitch = tarPitch; _tarYaw = tarYaw; _tarDis = tarDis; _tarOffsetX = tarOffsetX; _tarOffsetY = tarOffsetY; _tarFov = tarFov; _animMaxTime = animTime; _animCurve = curve; _isPlayAnim = true; _animTimer = 0f; UpdateAnim(0f); } #endregion } }