Files
2026-04-07 03:14:32 +03:00

147 lines
4.3 KiB
C#

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<Rigidbody>();
}
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<GameObject>();
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;
}
}