using System; using UnityEngine; using UnityEngine.EventSystems; /* 弓的相机 */ public class BowCamera : MonoBehaviour { //相机组件 Camera _cameraComp; Camera cameraComp { get { if (!_cameraComp) _cameraComp = GetComponent(); return _cameraComp; } } //控制的手臂弓 ArmBow _armBow; ArmBow armBow { get { if (!_armBow) _armBow = GetComponentInChildren(); return _armBow; } } //本地欧拉角记录值 Vector3 localEulerAngles; //触摸检测器 JCUnityLib.TouchChecker touchChecker = new JCUnityLib.TouchChecker(); //触摸模式开关 private static bool _isTouchMode = true; public static bool isTouchMode { get { if (CommonConfig.isReleaseVersion) return false; return _isTouchMode; } set { _isTouchMode = value; } } //左右转动范围限制 float[] limitRangeRotateY = { -80, 80 }; //上下转动范围限制 float[] limitRangeRotateX = { -80, 80 }; //禁止逻辑,只用于同步状态和渲染,目前用于联机 [NonSerialized] public bool banLogic = false; private static BowCamera _ins; public static BowCamera ins { get { if (!_ins) { _ins = GameObject.FindObjectOfType(); } return _ins; } } void Awake() { _ins = this; localEulerAngles = transform.localEulerAngles; if (CommonConfig.SpecialVersion1) { if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name.Equals("GameChallenge")) { this.cameraComp.fieldOfView = UserSettings.ins.bowRotateConvert.fieldOfView; } } RecordDefaultCameraFieldOfView(); if (UserSettings.ins.bowCameraFixed && !CommonConfig.isReleaseVersion) { bowCameraFixed = new BowCameraFixed(this); } } void Start() { touchChecker.onMoved += delegate (Touch t, bool isOnUI) { if (banLogic) return; if (isOnUI) return; //触摸控制镜头和拉弓射箭 this.localEulerAngles.x = Mathf.Clamp(this.localEulerAngles.x - t.deltaPosition.y * Time.deltaTime * 5, limitRangeRotateX[0], limitRangeRotateX[1]); this.localEulerAngles.y = Mathf.Clamp(this.localEulerAngles.y + t.deltaPosition.x * Time.deltaTime * 5, limitRangeRotateY[0], limitRangeRotateY[1]); this.transform.localEulerAngles = this.localEulerAngles; }; touchChecker.onEnded += delegate (Touch t, bool isOnUI) { if (banLogic) return; if (!isOnUI) armBow.ADS_fire(); }; } void OnDestroy() { if (_ins == this) _ins = null; } void Update() { //更新相机视野 if (cameraComp && !banCameraFieldOfView) { cameraComp.fieldOfView = cameraFieldOfView; } if (banLogic) return; //满足以下条件则阻止控制输入 if (GameMgr.ins.gameOver) { return; } if (GameMgr.debugInEditor) { //鼠标控制镜头和拉弓射箭 this.localEulerAngles.x = Mathf.Clamp(this.localEulerAngles.x - 2f * Input.GetAxis("Mouse Y"), limitRangeRotateX[0], limitRangeRotateX[1]); this.localEulerAngles.y = Mathf.Clamp(this.localEulerAngles.y + 2f * Input.GetAxis("Mouse X"), limitRangeRotateY[0], limitRangeRotateY[1]); this.transform.localEulerAngles = this.localEulerAngles; if (EventSystem.current.IsPointerOverGameObject()) return; } else if (isTouchMode) { touchChecker.Update(); } else { if (SB_EventSystem.ins && SB_EventSystem.ins.simulateMouseIsAwaked) return; //需要-镜头看向九轴姿态虚拟节点 needLookAtPoint = true; } } //需要-镜头看向九轴姿态虚拟节点? bool needLookAtPoint = false; //镜头旋转转换比值 float[] _bowRotateConvertRate = null; float bowRotateConvertRate { get { if (_bowRotateConvertRate == null) { _bowRotateConvertRate = new float[] { UserSettings.ins.bowRotateConvert.GetRate() }; } return _bowRotateConvertRate[0]; } } void LateUpdate() { #if UNITY_STANDALONE_WIN || UNITY_EDITOR if (InfraredDemo.DebugInEditor) needLookAtPoint = true; #endif if (needLookAtPoint) { needLookAtPoint = false; //镜头看向九轴姿态虚拟节点 this.transform.LookAt(CameraToLook.ins.point); // if (BowQuatDebug.ins) BowQuatDebug.ins.ShowRealBowQuat(this.transform.localEulerAngles); if (!CommonConfig.isReleaseVersion) { //镜头旋转比值转换 Vector3 localAngles = this.transform.localEulerAngles; localAngles.x = Mathf.Clamp((localAngles.x > 180 ? localAngles.x - 360 : localAngles.x) * bowRotateConvertRate, limitRangeRotateX[0], limitRangeRotateX[1]); localAngles.y = Mathf.Clamp((localAngles.y > 180 ? localAngles.y - 360 : localAngles.y) * bowRotateConvertRate, limitRangeRotateY[0], limitRangeRotateY[1]); if (bowCameraFixed != null) { localAngles = bowCameraFixed.LimitBowAngle(localAngles); } this.transform.localEulerAngles = localAngles; // if (BowQuatDebug.ins) BowQuatDebug.ins.ShowGameBowQuat(this.transform.localEulerAngles); } } onAfterLateUpdate?.Invoke(); } [NonSerialized] public Action onAfterLateUpdate; //---------------相机视野的相关操作--------------------- //视野值记录 float cameraFieldOfView = 60; [NonSerialized] public float defaultCameraFieldOfView = 60; private void RecordDefaultCameraFieldOfView() { defaultCameraFieldOfView = cameraComp.fieldOfView; cameraFieldOfView = defaultCameraFieldOfView; } //禁止相机视野改变 [NonSerialized] public bool banCameraFieldOfView = false; public void SetCameraFieldOfView(float value) { cameraComp.fieldOfView = value; } public void SetCameraFieldOfViewRecord(float value) { cameraFieldOfView = value; } //拉弓时的相机视野值变化 public void updateFollowPullBow() { // if (cameraFieldOfView > 40) { // cameraFieldOfView -= 20 * Time.deltaTime; // } else { // cameraFieldOfView = 40; // } } //松开拉弓时的相机视野值变化 public void updateGiveUpPullBow() { // if (cameraFieldOfView < 60) { // cameraFieldOfView += 20 * Time.deltaTime; // } else { // cameraFieldOfView = 60; // } } // 2022-04-28 // ------ 添加固定镜头选项后,新增的API ------ bool isArrowFollowing = false; public void SetArrowFollowing(bool value) { isArrowFollowing = value; cameraComp.enabled = !isArrowFollowing; AutoSwitchCamera(); } bool isScaleAimDisplaying = false; public void SetScaleAimDisplaying(bool value) { isScaleAimDisplaying = value; AutoSwitchCamera(); } void AutoSwitchCamera() { if (bowCameraFixed == null) { cameraComp.enabled = !isArrowFollowing; } else { bowCameraFixed.gameObject.SetActive(!isScaleAimDisplaying && !isArrowFollowing); cameraComp.enabled = isScaleAimDisplaying && !isArrowFollowing; } } public Camera GetRenderCamera() { if (bowCameraFixed == null) { return cameraComp; } else { if (bowCameraFixed.gameObject.activeSelf) { return bowCameraFixed.camera; } else { return cameraComp; } } } public BowCameraFixed bowCameraFixed = null; public class BowCameraFixed { public GameObject gameObject; public Transform transform; public Camera camera; private UnityStandardAssets.ImageEffects.Blur blur; //bowCameraComponent BowCamera bowCamera; private Camera targetCamera; private UnityStandardAssets.ImageEffects.Blur targetBlur; public BowCameraFixed(BowCamera bowCamera) { this.bowCamera = bowCamera; gameObject = new GameObject("BowCameraFixed"); transform = gameObject.transform; //复制Camera组件 targetCamera = bowCamera.cameraComp; camera = gameObject.AddComponent(); camera.tag = "MainCamera"; camera.clearFlags = targetCamera.clearFlags; camera.backgroundColor = targetCamera.backgroundColor; camera.cullingMask = targetCamera.cullingMask; camera.fieldOfView = targetCamera.fieldOfView; camera.nearClipPlane = targetCamera.nearClipPlane; camera.depth = targetCamera.depth + 0.1f; camera.renderingPath = targetCamera.renderingPath; //复制Blur组件 targetBlur = bowCamera.GetComponent(); if (targetBlur) { blur = gameObject.AddComponent(); blur.enabled = targetBlur.enabled; blur.blurShader = targetBlur.blurShader; blur.blurSpread = targetBlur.blurSpread; blur.iterations = targetBlur.iterations; } //设置Transform属性 transform.parent = bowCamera.transform.parent; transform.localPosition = bowCamera.transform.localPosition; transform.localScale = bowCamera.transform.localScale; transform.localRotation = Quaternion.identity; //监听和驱动LateUpdate bowCamera.onAfterLateUpdate += LateUpdate; //切换镜头 bowCamera.AutoSwitchCamera(); InitForLimitBound(); } void LateUpdate() { if (gameObject.activeSelf) { CrossHair.ins.UpdatePostionWhenFixedCamera(); } if (blur) { blur.enabled = targetBlur.enabled; if (blur.enabled) { blur.blurShader = targetBlur.blurShader; blur.blurSpread = targetBlur.blurSpread; blur.iterations = targetBlur.iterations; } } } //边界限制 float[] rangeRotateY = { -80, 80 }; float rangeRotateX = 25; Vector3 vecF; Vector3 vecU; public int outBoundIndex = -1; //-1为未出界 void InitForLimitBound() { int _leftNum = 4;//以前的设置 //如果是红外设备。不限制旋转 if (BluetoothAim.ins && (BluetoothAim.ins.isMainConnectToInfraredDevice() || BluetoothAim.ins.isMainConnectToGun())) { //// 如果不启用边界限制,则直接设置默认的范围 //rangeRotateY = new float[] { -180, 180 }; // 设置默认的无边界限制值(根据需求调整) //rangeRotateX = camera.fieldOfView / 2; //vecF = Quaternion.AngleAxis(rangeRotateX, Vector3.right) * Vector3.forward; //vecU = Quaternion.AngleAxis(rangeRotateX, Vector3.right) * Vector3.up; _leftNum = 0; } for (int i = (int)rangeRotateY[0]; i < 0; i++) { Vector3 pos = transform.position + Quaternion.AngleAxis(i, Vector3.up) * transform.forward; pos = camera.WorldToViewportPoint(pos); if (pos.x >= 0) { rangeRotateY[0] = i; rangeRotateY[1] = -i - _leftNum; break; } } rangeRotateX = camera.fieldOfView / 2; vecF = Quaternion.AngleAxis(rangeRotateX, Vector3.right) * Vector3.forward; vecU = Quaternion.AngleAxis(rangeRotateX, Vector3.right) * Vector3.up; } public Vector3 LimitBowAngle(Vector3 outAngle) { float angleY = outAngle.y; float angleX = outAngle.x; outAngle.y = Mathf.Clamp(angleY, rangeRotateY[0], rangeRotateY[1]); Vector3 vec = Quaternion.AngleAxis(outAngle.y, vecU) * vecF; float rx = (float)(Math.Asin(vec.y) / Math.PI * 180) * (angleX < 0 ? 1 : -1); if (angleY < rangeRotateY[0]) outBoundIndex = 0; else if (angleY > rangeRotateY[1]) outBoundIndex = 1; else if (angleX < -rangeRotateX) outBoundIndex = 2; else if (angleX > rangeRotateX) outBoundIndex = 3; else outBoundIndex = -1; if (Mathf.Abs(angleX) > Mathf.Abs(rx)) { outAngle.x = rx; } //因为Vector3是struct,传递给函数是值传递而非引用传递 return outAngle; } } }