using System; using UnityEngine; public class RWTCameraOrbit : MonoBehaviour { public Camera camera; public Vector3 pivot = new Vector3(512, 0, 512); public bool relativeY = true; public float distance = 1000; public float scrollSpeed = 100; public Vector2 rotation = new Vector2(0, 0); public Vector2 rotationSpeed = new Vector2(1, 1); public float maxRotationX = 80; private Vector3 _pivot; private float _distance; private Vector2 _rotation; private Vector2 lastInputPosition; private bool isDrag; private Plane? plane; private void Start() { lastInputPosition = Input.mousePosition; UpdateCamera(); } private void Update() { Vector2 inputPosition = Input.mousePosition; if (Input.GetMouseButton(0)) { if (plane == null) { Vector3? hit = GetHitPoint(inputPosition); if (hit != null) { plane = new Plane(Vector3.up, hit.Value); lastInputPosition = inputPosition; } } } else plane = null; if (lastInputPosition != inputPosition) { if (plane != null) { float d1, d2; Ray r1 = camera.ScreenPointToRay(lastInputPosition); Ray r2 = camera.ScreenPointToRay(inputPosition); bool s1 = plane.Value.Raycast(r1, out d1); bool s2 = plane.Value.Raycast(r2, out d2); if (s1 && s2) { Vector3 p1 = r1.GetPoint(d1); Vector3 p2 = r2.GetPoint(d2); Vector3 offset = p1 - p2; pivot.x += offset.x; pivot.z += offset.z; } } if (Input.GetMouseButton(1)) { Vector2 offset = lastInputPosition - inputPosition; rotation.x -= offset.y / 10f * rotationSpeed.x; rotation.y -= offset.x / 10f * rotationSpeed.y; } } float wheel = Input.GetAxis("Mouse ScrollWheel"); if (Math.Abs(wheel) > float.Epsilon) { distance -= wheel * scrollSpeed; } if (_pivot != pivot || _distance != distance || _rotation != rotation) UpdateCamera(); lastInputPosition = inputPosition; } private Vector3? GetHitPoint(Vector2 inputPosition) { RaycastHit[] hits = Physics.RaycastAll(camera.ScreenPointToRay(inputPosition)); foreach (RaycastHit hit in hits) { if (hit.transform.GetComponent() != null) return hit.point; } return null; } private void UpdateCamera() { _pivot = pivot; _distance = distance; _rotation = rotation; if (camera == null) return; if (rotation.x > maxRotationX) rotation.x = maxRotationX; else if (rotation.x < 0) rotation.x = 0; float rx = 90 - rotation.x; if (rx > 89.9) rx = 89.9f; double px = Math.Cos(rx * Mathf.Deg2Rad) * distance; double py = Math.Sin(rx * Mathf.Deg2Rad) * distance; double pz = Math.Cos(rotation.y * Mathf.Deg2Rad) * px; px = Math.Sin(rotation.y * Mathf.Deg2Rad) * px; float oy = 0; if (relativeY) { RaycastHit[] hits = Physics.RaycastAll(new Vector3(pivot.x, 100000, pivot.z), Vector3.down); foreach (RaycastHit hit in hits) { if (hit.transform.GetComponent() != null) { oy = hit.point.y; break; } } } Vector3 target = pivot + new Vector3(0, oy, 0); Vector3 newPosition = new Vector3((float)px, (float)py, (float)pz) + target; camera.transform.position = newPosition; camera.transform.LookAt(target); } }