using System.Collections; using System.Collections.Generic; using UnityEngine; public class DraggableObject : MonoBehaviour { [HideInInspector] public float mass = 1f; [HideInInspector] public bool isHeavy = false; [HideInInspector] public Transform priorityTarget = null; public Vector3 startPosition { get; private set; } public Quaternion startRotation { get; private set; } private Vector3 _mousePosition; private Vector3 _mouseCameraPos; private Vector3 _initialPosition; private Rigidbody _rb; private Camera _camera; private Transform _scaleTarget; private float _lerpPosition; [HideInInspector] public bool isDragging; [SerializeField] private float _minY = 0.2f; [SerializeField] private float _maxDistanceFromStart = 30f; private void Awake() { _rb = GetComponent(); } private void Start() { _camera = Camera.main; _rb.isKinematic = true; startPosition = transform.position; startRotation = transform.rotation; } private Vector3 GetMousePos() { return _camera != null ? _camera.WorldToScreenPoint(transform.position) : Vector3.zero; } private Transform GetNearestTargetToCursor() { if (priorityTarget != null && priorityTarget.gameObject.activeInHierarchy) return priorityTarget; var targets = new List(); targets.AddRange(GameObject.FindGameObjectsWithTag("ScaleTarget")); targets.AddRange(GameObject.FindGameObjectsWithTag("MainScale")); Transform nearest = null; float minDist = float.MaxValue; foreach (var t in targets) { Vector3 screenPos = _camera.WorldToScreenPoint(t.transform.position); float d = Vector2.Distance( new Vector2(Input.mousePosition.x, Input.mousePosition.y), new Vector2(screenPos.x, screenPos.y)); if (d < minDist) { minDist = d; nearest = t.transform; } } return nearest; } private void OnMouseDown() { _rb.isKinematic = false; _rb.useGravity = false; _rb.velocity = Vector3.zero; _scaleTarget = GetNearestTargetToCursor(); _initialPosition = transform.position; _mousePosition = Input.mousePosition - GetMousePos(); isDragging = true; } private void Update() { if (!isDragging || _camera == null) return; _rb.angularVelocity = Vector3.zero; _mouseCameraPos = _camera.ScreenToWorldPoint(Input.mousePosition - _mousePosition); float targetZ = _scaleTarget != null ? _scaleTarget.position.z : _initialPosition.z; _lerpPosition = _scaleTarget != null ? Mathf.InverseLerp(_initialPosition.x, _scaleTarget.position.x, _mouseCameraPos.x) : 0f; transform.position = new Vector3( _mouseCameraPos.x, Mathf.Max(_mouseCameraPos.y, _minY), Mathf.Lerp(_initialPosition.z, targetZ, _lerpPosition) ); if (Input.GetMouseButtonUp(0)) { isDragging = false; _rb.useGravity = true; _rb.isKinematic = false; } } private void FixedUpdate() { if (isDragging) return; if (Vector3.Distance(transform.position, startPosition) > _maxDistanceFromStart) ResetToStart(); } public void ResetToStart() { _rb.velocity = Vector3.zero; _rb.angularVelocity = Vector3.zero; _rb.isKinematic = true; transform.position = startPosition; transform.rotation = startRotation; isDragging = false; } private void OnTriggerEnter(Collider other) { if (isDragging) return; if (!other.CompareTag("ScalePan")) return; StartCoroutine(SnapToPan(other.transform)); } private IEnumerator SnapToPan(Transform pan) { _rb.isKinematic = true; _rb.useGravity = false; Vector3 targetPos = pan.position + Vector3.up * 0.1f; float t = 0f; Vector3 startPos = transform.position; while (t < 1f) { t += Time.deltaTime * 5f; transform.position = Vector3.Lerp(startPos, targetPos, t); yield return null; } _rb.isKinematic = false; _rb.useGravity = true; } }