using UnityEngine; using System.Collections; public class CameraController : MonoBehaviour { public static CameraController Instance; [HideInInspector] public bool AcceptInput = true; public Transform Node; public Camera CameraObject; public Transform LookAtTarget; public Camera MaskCamera; public GameObject Mask; private Animation m_Animation; public float lookHeight = 0; public float Distance = 10.0f; public float MinDistance = 2.0f; public float MaxDistance = 10.0f; public float rotationX = 0.0f; public float rotationY = 35.0f; public float rotationSpeed = 5.0f; public float MinRotationY = 35.0f; public float MaxRotationY = 50.0f; public float MoveDamping = 0.1f; public float RotationDamping = 0.1f; public float ZoomDamping = 0.3f; private float m_CurrentRotationY; private float m_CurrentRotationX; private Vector3 m_MoveVelocity = Vector3.zero; private float m_ZoomVelocity = 0; [HideInInspector] public float originalDistance = 0; [HideInInspector] public float originalRotX = 0; [HideInInspector] public float originalRotY = 0; [HideInInspector] public float sceneDistance = 0; public bool IsPlayingAnim { get; private set; } void Awake() { Instance = this; CameraManager.sceneCamera = CameraObject; m_Animation = GetComponent(); sceneDistance = originalDistance = Distance; originalRotX = rotationX; originalRotY = rotationY; DontDestroyOnLoad(this); SystemSetting.Instance.qualityLevelChangeEvent += QualityLevelChanged; } public void QualityLevelChanged() { if (CameraObject == null) { return; } if (SystemSetting.Instance.GetCurrentQualityLevel() == GameQuality.Low) { CameraObject.cullingMask |= LayerUtility.BattleEffectLowMask; CameraObject.cullingMask &= ~LayerUtility.BattleEffectMidMask; CameraObject.cullingMask &= ~LayerUtility.BattleEffectHighMask; } else if (SystemSetting.Instance.GetCurrentQualityLevel() == GameQuality.Medium) { CameraObject.cullingMask |= LayerUtility.BattleEffectLowMask; CameraObject.cullingMask |= LayerUtility.BattleEffectMidMask; CameraObject.cullingMask &= ~LayerUtility.BattleEffectHighMask; } else if (SystemSetting.Instance.GetCurrentQualityLevel() == GameQuality.High) { CameraObject.cullingMask |= LayerUtility.BattleEffectLowMask; CameraObject.cullingMask |= LayerUtility.BattleEffectMidMask; CameraObject.cullingMask |= LayerUtility.BattleEffectHighMask; } } public void PlayAnimationClip(string name) { AnimationClip _clip = BuiltInLoader.LoadAnimationClip(name); if (_clip != null) { IsPlayingAnim = true; m_Animation.AddClip(_clip, "start_show"); m_Animation.Play("start_show"); } } public void PlayAnimationClipUnLimit(string name) { AnimationClip _clip = BuiltInLoader.LoadAnimationClip(name); if (_clip != null) { m_Animation.AddClip(_clip, "start_show"); m_Animation.Play("start_show"); } } private void OnAnimationOver() { IsPlayingAnim = false; } public void ResetOriginal() { SnxxzGame.Instance.StopAllCameraCo(); StopAllCoroutines(); RotationDamping = 0.02f; ZoomDamping = 0.02f; sceneDistance = Distance = originalDistance; rotationX = originalRotX; rotationY = originalRotY; } public void SetLookTarget(Transform _target) { LookAtTarget = _target; } public void SetRotationX(float _angle) { rotationX = _angle; } public void ChangeRotationX(float _change_value) { rotationX += _change_value; } IEnumerator CameraRotationX(float _angle) { while (rotationX != _angle) { rotationX = Mathf.SmoothDampAngle(rotationX, _angle, ref m_CurrentRotationX, RotationDamping); if (Mathf.Abs(rotationX - _angle) <= 0.01f) { rotationX = _angle; } yield return null; } } // Update is called once per frame void Update() { // 是否正在播放摄像机动画 if (IsPlayingAnim) { return; } //#if UNITY_EDITOR //if (AcceptInput) //{ // if (Input.GetMouseButtonDown(0)) // { // Ray _ray = CameraObject.ScreenPointToRay(Input.mousePosition); // RaycastHit _hit; // if (Physics.Raycast(_ray, out _hit, 100, LayerUtility.WalkbleMask)) // { // if (LookAtTarget != null) // { // LookAtTarget.transform.position = _hit.point; // } // } // } //} //#endif Vector3 eulerAngles = transform.eulerAngles; float newCameraRotUp = Mathf.SmoothDampAngle(eulerAngles.x, rotationY, ref m_CurrentRotationY, RotationDamping); float newCameraRotSide = Mathf.SmoothDampAngle(eulerAngles.y, rotationX, ref m_CurrentRotationX, RotationDamping); Vector3 _dir = new Vector3(newCameraRotUp, newCameraRotSide, 0); if (_dir.magnitude > 0.01f) { transform.rotation = Quaternion.Euler(_dir); } if (LookAtTarget != null) { transform.position = Vector3.SmoothDamp(transform.position, LookAtTarget.position + new Vector3(0, lookHeight, 0), ref m_MoveVelocity, MoveDamping); } float dist = Mathf.SmoothDamp(-CameraObject.transform.localPosition.z, Distance, ref m_ZoomVelocity, ZoomDamping); CameraObject.transform.localPosition = -Vector3.forward * dist; } public void Apply() { if (LookAtTarget == null) { return; } transform.position = LookAtTarget.position + new Vector3(0, lookHeight, 0); transform.eulerAngles = new Vector3(rotationY, rotationX, 0); CameraObject.transform.localPosition = -Vector3.forward * Distance; } void OnDrawGizmos() { if (CameraObject != null) { Gizmos.color = new Color(1.0f, 1.0f, 0.0f, 0.8f); // Color.yellow; Gizmos.DrawSphere(CameraObject.transform.position, 0.2f); Gizmos.color = new Color(1.0f, 0.0f, 0.0f, 0.8f); // Color.yellow; Gizmos.DrawSphere(transform.position, 0.2f); Gizmos.color = Color.yellow; Gizmos.DrawLine(CameraObject.transform.position, transform.position); } } private void OnDestroy() { LookAtTarget = null; Instance = null; if (CameraManager.sceneCamera == CameraObject) { CameraManager.sceneCamera = null; } } private struct ZoomVo { public float scale; public float time; } public void StartZoom(float scale, float zoomTime) { if (zoomTime == 0) { return; } StopZoom(); ZoomVo _vo = new ZoomVo { scale = scale, time = zoomTime }; StartCoroutine("Zoom", _vo); } public void StopZoom() { StopCoroutine("Zoom"); } IEnumerator Zoom(ZoomVo vo) { float _cacheDistance = Distance; float _time = 0; float _percent; float _zoomDistance = sceneDistance * vo.scale - Distance; while (_time < vo.time) { _percent = _time / vo.time; _percent = Constants.zoomAniCurve.animationCurve.Evaluate(_percent); Distance = _cacheDistance + _percent * _zoomDistance; _time += Time.deltaTime; yield return null; } Distance = _cacheDistance + _zoomDistance; //_cacheDistance = Distance; //_zoomDistance = m_OriginalDistance - Distance; //while (_time < vo.recoverTime) //{ // _percent = _time / vo.recoverTime; // _percent = Constants.zoomAniCurve.animationCurve.Evaluate(_percent); // Distance = _cacheDistance + _percent * _zoomDistance; // _time += Time.deltaTime; // yield return null; //} //Distance = m_OriginalDistance; } private struct ShakeVo { public Vector3 shakeDir; public float power; public float interval; public float duration; } public void DoShake(Vector3 dir, float power, float interval, float duration) { ShakeVo _vo = new ShakeVo { shakeDir = dir.normalized, power = power, interval = interval, duration = duration }; Node.transform.localPosition = Vector3.zero; StopCoroutine("Shake"); StartCoroutine("Shake", _vo); } public void StopShake() { Node.transform.localPosition = Vector3.zero; StopCoroutine("Shake"); } IEnumerator Shake(ShakeVo vo) { float _percent = 0; float _interval = 0; float _duration = vo.duration; Vector3 _localPos = Vector3.zero; Vector3 _direction = vo.shakeDir; float _distance = Vector3.Distance(vo.power * _direction, Vector3.zero); while (_duration > 0) { _interval += Time.deltaTime; _percent = _interval / vo.interval; _percent = Constants.shakeAniCurve.animationCurve.Evaluate(_percent); Node.transform.localPosition = _localPos + _direction * _distance * _percent; if (_interval > vo.interval) { _localPos = Node.transform.localPosition; _direction = -_direction; _distance = Vector3.Distance(vo.power * _direction, _localPos); _interval = 0; } _duration -= Time.deltaTime; yield return null; } _interval = 0; _localPos = Node.transform.localPosition; _direction = (Vector3.zero - Node.transform.localPosition).normalized; _distance = Vector3.Distance(Vector3.zero, _localPos); while (_interval < vo.interval) { _interval += Time.deltaTime; _percent = _interval / vo.interval; _percent = Constants.shakeAniCurve.animationCurve.Evaluate(_percent); Node.transform.localPosition = _localPos + _direction * _distance * _percent; yield return null; } Node.transform.localPosition = Vector3.zero; } }