using asap.core; using Cinemachine; using System; using UniRx; using UnityEngine; public class BuildingCameraController : MonoBehaviour { //public Transform mainCameraTr; public CinemachineVirtualCamera cameraVirtual; public CinemachineFreeLook[] cameraFreeLook; public GameObject cameraMove; string inputAxisXName = "Mouse X"; string inputAxisYName = "Mouse Y"; // public CinemachineVirtualCameraBase vcam; private int index = 0; bool photo; private CinemachineVirtualCameraBase currentCamera; float zoomSpeed = 0.2f; private Vector2[] lastTouchPositions = new Vector2[2]; private Vector2[] currentTouchPositions = new Vector2[2]; private float lastTouchDistance; private float currentTouchDistance; //方向 圆心 private Vector2 circle; private Vector2 touchDelta0; private Vector2 touchDelta1; private Vector2 currentDelta0; private Vector2 currentDelta1; float signedAngle0; float signedAngle1; float angle0; float angle1; public Transform lookAt; public Transform boundary1; public Transform boundary2; private Vector3 minVec; private Vector3 maxVec; //是否双指 private bool isTouchTwo = false; //双指拖动开始阈值 public float touchTwoThreshold = 50; public CinemachineDollyCart cinemachineDollyCart; public CinemachineVirtualCamera cameraPhotoVirtual; bool isMove = false; bool isTransfer = false; Vector3 startPos; IDisposable disposable; bool isDrag = false; void Start() { transform.Find("CameraMain").gameObject.SetActive(false); startPos = lookAt.localPosition; cameraMove.SetActive(false); minVec = new Vector3(Mathf.Min(boundary1.localPosition.x, boundary2.localPosition.x), lookAt.localPosition.y, Mathf.Min(boundary1.localPosition.z, boundary2.localPosition.z)); maxVec = new Vector3(Mathf.Max(boundary1.localPosition.x, boundary2.localPosition.x), lookAt.localPosition.y, Mathf.Max(boundary1.localPosition.z, boundary2.localPosition.z)); //Zoom = cameraVirtual.m_Lens.FieldOfView; currentCamera = cameraVirtual; cameraVirtual.gameObject.SetActive(true); for (int i = 0; i < cameraFreeLook.Length; i++) { cameraFreeLook[i].gameObject.SetActive(false); } //mainCameraTr.gameObject.SetActive(false); } private void OnEnable() { disposable = GContext.OnEvent().Subscribe(OnSwitchVirtualCamera); } private void OnDisable() { disposable?.Dispose(); disposable = null; } //切换虚拟相机 void SwitchVirtualCamera(int _index) { if (index != _index) { CinemachineVirtualCameraBase nextCamera; if (_index != 0) { nextCamera = cameraFreeLook[_index - 1]; nextCamera.transform.position = currentCamera.transform.position; } else { nextCamera = cameraVirtual; lookAt.localPosition = startPos; } currentCamera.gameObject.SetActive(false); currentCamera = nextCamera; currentCamera.gameObject.SetActive(true); if (isMove && _index == 0) { cameraMove.SetActive(false); isMove = false; } } index = _index; } void OnSwitchVirtualCamera(SwitchVirtualCameraEvent eventData) { isDrag = eventData.isDrag; if (eventData.type > 10) { photo = true; if (eventData.type == 11) { SetPhotoVirtual(); } else if (eventData.type == 12) { SetCinemachineDollyCart(); } index = eventData.type; return; } if (isDrag || eventData.type == 0) { if (index > 10) { if (cameraPhotoVirtual != null) { cameraPhotoVirtual.gameObject.SetActive(false); } cinemachineDollyCart.transform.parent.gameObject.SetActive(false); } SwitchVirtualCamera(eventData.type); } } void SetPhotoVirtual() { if (cameraPhotoVirtual == null) { Debug.LogError("cameraPhotoVirtual is null"); return; } currentCamera.gameObject.SetActive(false); cameraPhotoVirtual.gameObject.SetActive(true); } void SetCinemachineDollyCart() { if (cameraPhotoVirtual != null) { cameraPhotoVirtual.gameObject.SetActive(false); } currentCamera.gameObject.SetActive(false); cinemachineDollyCart.transform.parent.gameObject.SetActive(true); cinemachineDollyCart.m_Speed = 0; } void Update() { if (!isDrag) { return; } if (photo) { if (Input.GetMouseButton(0) || Input.touchCount == 1) { if (cinemachineDollyCart.transform.parent.gameObject.activeSelf) { cinemachineDollyCart.m_Position -= Input.GetAxis(inputAxisXName); } } return; } #if UNITY_EDITOR if (Input.GetMouseButton(0) && index == 1) #else if (Input.touchCount==1&& index==1) #endif { if (!isTouchTwo) { //SwitchVirtualCamera(1); cameraFreeLook[index - 1].m_XAxis.m_InputAxisValue = Input.GetAxis(inputAxisXName); cameraFreeLook[index - 1].m_YAxis.m_InputAxisValue = Input.GetAxis(inputAxisYName); } } else if (Input.touchCount == 2) { if (Input.GetTouch(0).phase == TouchPhase.Moved || Input.GetTouch(1).phase == TouchPhase.Moved) { currentTouchPositions[0] = Input.GetTouch(0).position; currentTouchPositions[1] = Input.GetTouch(1).position; if (!isTouchTwo) { isTouchTwo = true; lastTouchPositions[0] = currentTouchPositions[0]; lastTouchPositions[1] = currentTouchPositions[1]; } if (Vector2.Distance(currentTouchPositions[0], lastTouchPositions[0]) + Vector2.Distance(currentTouchPositions[1], lastTouchPositions[1]) > touchTwoThreshold && index != 2) { SwitchVirtualCamera(2); } if (!isTransfer && !isMove && (Vector2.Distance(currentTouchPositions[0], lastTouchPositions[0]) < touchTwoThreshold && Vector2.Distance(currentTouchPositions[1], lastTouchPositions[1]) < touchTwoThreshold)) { return; } if (index == 2) { circle = (lastTouchPositions[0] + lastTouchPositions[1]) / 2; touchDelta0 = lastTouchPositions[0] - circle; touchDelta1 = lastTouchPositions[1] - circle; currentDelta0 = (currentTouchPositions[0] - lastTouchPositions[0]); currentDelta1 = (currentTouchPositions[1] - lastTouchPositions[1]); signedAngle0 = Vector2.SignedAngle(touchDelta0, currentDelta0); signedAngle1 = Vector2.SignedAngle(touchDelta1, currentDelta1); angle0 = Vector2.Angle(touchDelta0, currentDelta0); angle1 = Vector2.Angle(touchDelta1, currentDelta1); if ((Vector2.Angle(currentDelta0, currentDelta1) > 30) && !isMove || isTransfer) { TransferPOrR(); } else if ((!isTransfer && Vector2.Angle(currentDelta0, currentDelta1) < 20) || (isMove && (Vector2.Angle(currentDelta0, currentDelta1) < 50))) { Move(); } else { cameraFreeLook[index - 1].m_YAxis.m_InputAxisValue = 0; cameraFreeLook[index - 1].m_XAxis.m_InputAxisValue = 0; } lastTouchPositions[0] = currentTouchPositions[0]; lastTouchPositions[1] = currentTouchPositions[1]; } } else if (index != 0) { cameraFreeLook[index - 1].m_YAxis.m_InputAxisValue = 0; cameraFreeLook[index - 1].m_XAxis.m_InputAxisValue = 0; } } else if (Input.touchCount == 0 && index != 0) { isTouchTwo = false; isTransfer = false; if (isMove) { cameraFreeLook[1].transform.position = cameraMove.transform.position; currentCamera.gameObject.SetActive(true); cameraMove.SetActive(false); isMove = false; } cameraFreeLook[index - 1].m_XAxis.m_InputAxisValue = 0; cameraFreeLook[index - 1].m_YAxis.m_InputAxisValue = 0; } } //旋转缩放 void TransferPOrR() { isTransfer = true; if (signedAngle0 * signedAngle1 > 0 && ((angle0 > 60 && angle0 < 120) || (angle1 > 60 && angle1 < 120))) { float delta = currentDelta0.magnitude + currentDelta1.magnitude; if (signedAngle0 > 0) { cameraFreeLook[index - 1].m_XAxis.m_InputAxisValue = delta * zoomSpeed; } else { cameraFreeLook[index - 1].m_XAxis.m_InputAxisValue = -delta * zoomSpeed; }//旋转 } else if ((angle0 > 150 && angle1 > 150) || (angle0 < 30 && angle1 < 30)) { currentTouchDistance = Vector2.Distance(currentTouchPositions[0], currentTouchPositions[1]); lastTouchDistance = Vector2.Distance(lastTouchPositions[0], lastTouchPositions[1]);//缩放 float delta = currentTouchDistance - lastTouchDistance; if (delta < 0) { cameraFreeLook[index - 1].m_YAxis.m_InputAxisValue = delta * zoomSpeed; } else { cameraFreeLook[index - 1].m_YAxis.m_InputAxisValue = delta * zoomSpeed; } } } //移动 void Move() { if (!isMove) { isMove = true; cameraMove.transform.position = cameraFreeLook[index - 1].transform.position; cameraMove.SetActive(true); currentCamera.gameObject.SetActive(false); } //方向 Vector2 offset; if (currentDelta0.magnitude > currentDelta1.magnitude) { offset = currentDelta0; } else { offset = currentDelta1; } //同方向移动 //Vector2 offset = (currentDelta0 + currentDelta1).normalized; //offst在相机坐标系下的向量 Vector3 vector = Camera.main.transform.TransformDirection(offset.x, 0, offset.y); vector.y = 0; lookAt.localPosition += vector.normalized * Time.deltaTime * 30; lookAt.localPosition = new Vector3(Mathf.Clamp(lookAt.localPosition.x, minVec.x, maxVec.x), lookAt.localPosition.y, Mathf.Clamp(lookAt.localPosition.z, minVec.z, maxVec.z)); //cameraFreeLook[index - 1].m_Orbits[0].m_Radius += vector.magnitude; //cameraFreeLook[index - 1].m_Orbits[1].m_Radius += vector.magnitude; //cameraFreeLook[index - 1].m_Orbits[2].m_Radius += vector.magnitude; } }