using GISTech.GISTerrainLoader; using UnityEngine; public class Camera3D : MonoBehaviour { public KeyCode RotateLeft; public KeyCode RotateRight; public KeyCode ResetCameraPosKey; [Header("Adapte Camera to GIS Container")] public bool AdapteToGISContainer; [Header("Camera Movements")] public float PanSpeed = 0.1f; public float RotationSpeed = 0.15f; public float ZoomSpeed; public float FollowSpeed = 0.1f; public float SmoothingFactor = 0.1f; [Header("Camera Parameters")] [Space(4f)] public bool UseKeyboardInput = true; public bool UseMouseInput = true; public bool AdaptToTerrainHeight = true; public bool IncreaseSpeedWhenZoomedOut = true; public bool CorrectZoomingOutRatio = true; public bool Smoothing = true; [Header("Follow a GameObject")] public GameObject TargetToFollow; [Header("Enable/Disbale Position On Start")] public bool UseStartPosition; public Vector3 StartPosition; public Vector3 StartRotation; private float mousepanSpeed = 15f; private float mousezoomSpeed = 100f; private Vector2 MinMaxZoom = new Vector2(0f, 0f); private float minZoomDistance = 20f; private float maxZoomDistance = 2f; private Vector3 cameraTarget; private float currentCameraDistance; private Vector3 lastMousePos; private Vector3 lastPanSpeed = Vector3.zero; private Vector3 goingToCameraTarget = Vector3.zero; private bool doingAutoMovement; private Vector3 lastpos; private Rect bound; private GISTerrainContainer container; private void OnEnable() { RuntimeTerrainGenerator.OnFinish += OnTerrainGenerated; } private void OnDisable() { RuntimeTerrainGenerator.OnFinish -= OnTerrainGenerated; } public void Start() { currentCameraDistance = minZoomDistance + (maxZoomDistance - minZoomDistance) / 2f; base.transform.position = lastpos; if (UseStartPosition) { GoTo(StartPosition); base.transform.localEulerAngles = StartRotation; } } public void Update() { if (Input.GetKeyDown(ResetCameraPosKey)) { ResetCameraPosition(); } UpdatePanning(); UpdateZooming(); UpdatePosition(); UpdateAutoMovement(); lastMousePos = Input.mousePosition; } public void GoTo(Vector3 position) { doingAutoMovement = true; goingToCameraTarget = position; TargetToFollow = null; } public void Follow(GameObject gameObjectToFollow) { TargetToFollow = gameObjectToFollow; } private void UpdatePanning() { Vector3 vector = new Vector3(0f, 0f, 0f); if (UseKeyboardInput) { if (Input.GetKey(KeyCode.LeftArrow)) { vector.x -= 1f; } if (Input.GetKey(KeyCode.DownArrow)) { vector.z -= 1f; } if (Input.GetKey(KeyCode.RightArrow)) { vector.x += 1f; } if (Input.GetKey(KeyCode.UpArrow)) { vector.z += 1f; } } if (UseMouseInput) { if (Input.GetMouseButton(0)) { Vector3 vector2 = Input.mousePosition - lastMousePos; vector += new Vector3(0f - vector2.x, 0f, 0f - vector2.y) * PanSpeed; } if (Input.GetMouseButton(2)) { vector += new Vector3(0f, 0f - (Input.mousePosition - lastMousePos).y, 0f) * PanSpeed; } } if (vector != Vector3.zero) { TargetToFollow = null; doingAutoMovement = false; } Vector3 direction = vector; if (Smoothing) { direction = (lastPanSpeed = Vector3.Lerp(lastPanSpeed, vector, SmoothingFactor)); } float x = base.transform.localEulerAngles.x; base.transform.SetLocalEulerAngles(0f); float num = (IncreaseSpeedWhenZoomedOut ? Mathf.Sqrt(currentCameraDistance) : 1f); cameraTarget += base.transform.TransformDirection(direction) * mousepanSpeed * num * Time.deltaTime; base.transform.SetLocalEulerAngles(x); } private void UpdateZooming() { float num = 0f; if (UseKeyboardInput) { if (Input.GetKey(KeyCode.F)) { num = 1f; } if (Input.GetKey(KeyCode.R)) { num = -1f; } } if (!UseMouseInput) { return; } float axis = Input.GetAxis("Mouse ScrollWheel"); num -= axis * ZoomSpeed; float num2 = (CorrectZoomingOutRatio ? ((currentCameraDistance - minZoomDistance) / (maxZoomDistance - minZoomDistance)) : 0f); if (axis > 0f || axis < 0f) { float num3 = minZoomDistance * axis * ZoomSpeed * Time.deltaTime; if (axis < 0f && minZoomDistance - num3 < MinMaxZoom.y) { minZoomDistance -= num3; } if (axis > 0f && minZoomDistance + num3 > MinMaxZoom.x) { minZoomDistance -= num3; } if (minZoomDistance <= MinMaxZoom.x) { minZoomDistance = MinMaxZoom.x; } float num4 = Mathf.Clamp(Mathf.Max(minZoomDistance, Mathf.Min(maxZoomDistance, currentCameraDistance + num * Time.deltaTime * mousezoomSpeed * (num2 * 2f + 1f))), MinMaxZoom.x, MinMaxZoom.y); currentCameraDistance = num4; } } private void UpdatePosition() { if (TargetToFollow != null && FollowSpeed > 0f) { cameraTarget = Vector3.Lerp(cameraTarget, TargetToFollow.transform.position, FollowSpeed); } if (base.transform.position != Vector3.zero && cameraTarget != Vector3.zero) { base.transform.position = cameraTarget; base.transform.Translate(Vector3.back * currentCameraDistance); } if (AdapteToGISContainer) { if (cameraTarget.y >= MinMaxZoom.y) { cameraTarget = new Vector3(cameraTarget.x, MinMaxZoom.y, cameraTarget.z); } if (cameraTarget.x <= MinMaxZoom.x) { cameraTarget = new Vector3(cameraTarget.x, MinMaxZoom.x, cameraTarget.z); } float x = Mathf.Clamp(base.transform.position.x, bound.xMin, bound.xMax); float y = Mathf.Clamp(base.transform.position.y, MinMaxZoom.x, MinMaxZoom.y); float z = Mathf.Clamp(base.transform.position.z, bound.yMin, bound.yMax); base.transform.position = new Vector3(x, y, z); } } private void UpdateAutoMovement() { if (doingAutoMovement) { cameraTarget = Vector3.Lerp(cameraTarget, goingToCameraTarget, FollowSpeed); if (Vector3.Distance(goingToCameraTarget, cameraTarget) < 1f) { doingAutoMovement = false; } } } private void OnDrawGizmosSelected() { if (AdapteToGISContainer) { Vector3 position = base.transform.position; Gizmos.DrawLine(new Vector3(bound.xMin, position.y, bound.yMin), new Vector3(bound.xMin, position.y, bound.yMax)); Gizmos.DrawLine(new Vector3(bound.xMin, position.y, bound.yMax), new Vector3(bound.xMax, position.y, bound.yMax)); Gizmos.DrawLine(new Vector3(bound.xMax, position.y, bound.yMax), new Vector3(bound.xMax, position.y, bound.yMin)); Gizmos.DrawLine(new Vector3(bound.xMax, position.y, bound.yMin), new Vector3(bound.xMin, position.y, bound.yMin)); } } private void OnTerrainGenerated(GISTerrainContainer m_container) { container = m_container; ResetCameraPosition(); } public void ResetCameraPosition() { if (container != null) { bound = new Rect(new Vector2((0f - container.ContainerSize.x) / 2f, (0f - container.ContainerSize.z) / 2f), new Vector2(container.ContainerSize.x * 2f, container.ContainerSize.z * 2f)); Vector3 position = (cameraTarget = new Vector3(container.ContainerSize.x / 2f, (container.ContainerSize.x + container.ContainerSize.z) / 4f, container.ContainerSize.z / 2f)); base.transform.position = position; lastpos = position; base.enabled = true; PanSpeed = container.Scale.x * 2f; ZoomSpeed = container.Scale.x * 300f; MinMaxZoom.x = 40f; MinMaxZoom.y = (container.ContainerSize.x + container.ContainerSize.z) / 2f; } } }