Files
test/Assets/Jianghu/Scripts/SpiralMovement.cs
T
2025-12-01 11:26:32 +07:00

144 lines
4.4 KiB
C#

using UnityEngine;
[ExecuteInEditMode] // Cho phép chạy trong Edit Mode
public class SpiralMovementY : MonoBehaviour
{
[Header("Spiral Settings")]
[SerializeField] private float initialRadius = 5f;
[SerializeField] private float radiusDecreaseRate = 0.5f;
[SerializeField] private float minRadius = 0.1f;
[SerializeField] private float angularSpeed = 2f;
[SerializeField] private float verticalSpeed = 1f;
[SerializeField] private Vector3 centerPoint = Vector3.zero;
[SerializeField] private bool moveUpward = true;
[Header("Animation Control")]
[SerializeField] private bool animate = true; // Bật/tắt animation
[SerializeField] private bool resetOnDisable = true; // Reset khi tắt
private float currentAngle = 0f;
private float currentRadius;
private float currentHeight;
private float lastTime;
private Vector3 startPosition;
void OnEnable()
{
startPosition = transform.position;
ResetSpiral();
lastTime = GetCurrentTime();
}
void OnDisable()
{
if (resetOnDisable)
{
transform.position = startPosition;
}
}
void Update()
{
if (!animate) return;
// Tính delta time cho cả Edit và Play mode
float currentTime = GetCurrentTime();
float deltaTime = currentTime - lastTime;
lastTime = currentTime;
// Giới hạn deltaTime để tránh nhảy cóc khi chuyển window
deltaTime = Mathf.Min(deltaTime, 0.1f);
// Tăng góc theo thời gian
currentAngle += angularSpeed * deltaTime;
// Giảm bán kính theo thời gian
currentRadius -= radiusDecreaseRate * deltaTime;
currentRadius = Mathf.Max(currentRadius, minRadius);
// Di chuyển theo trục Y
if (moveUpward)
currentHeight += verticalSpeed * deltaTime;
else
currentHeight -= verticalSpeed * deltaTime;
// Tính vị trí mới
Vector3 newPosition = new Vector3(
centerPoint.x + Mathf.Cos(currentAngle) * currentRadius,
currentHeight,
centerPoint.z + Mathf.Sin(currentAngle) * currentRadius
);
transform.position = newPosition;
// Đánh dấu scene đã thay đổi trong Edit Mode
#if UNITY_EDITOR
if (!Application.isPlaying)
{
UnityEditor.EditorUtility.SetDirty(transform);
}
#endif
}
// Lấy thời gian hiện tại (hoạt động cho cả Edit và Play mode)
private float GetCurrentTime()
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
return (float)UnityEditor.EditorApplication.timeSinceStartup;
}
#endif
return Time.time;
}
// Reset về vị trí ban đầu
[ContextMenu("Reset Spiral")] // Thêm vào context menu (chuột phải)
public void ResetSpiral()
{
currentAngle = 0f;
currentRadius = initialRadius;
currentHeight = centerPoint.y;
lastTime = GetCurrentTime();
}
// Vẽ đường xoắn ốc trong Scene view
void OnDrawGizmos()
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(centerPoint, 0.2f);
// Vẽ trục Y
Gizmos.color = Color.green;
Gizmos.DrawLine(centerPoint, centerPoint + Vector3.up * 10f);
// Vẽ preview đường xoắn ốc
float previewRadius = initialRadius;
float previewAngle = 0f;
float previewHeight = centerPoint.y;
Vector3 prevPoint = centerPoint;
int steps = 100;
for (int i = 0; i < steps; i++)
{
previewAngle += 0.2f;
previewRadius -= radiusDecreaseRate * 0.05f;
previewRadius = Mathf.Max(previewRadius, minRadius);
if (moveUpward)
previewHeight += verticalSpeed * 0.05f;
else
previewHeight -= verticalSpeed * 0.05f;
Vector3 point = new Vector3(
centerPoint.x + Mathf.Cos(previewAngle) * previewRadius,
previewHeight,
centerPoint.z + Mathf.Sin(previewAngle) * previewRadius
);
Gizmos.color = Color.Lerp(Color.cyan, Color.magenta, (float)i / steps);
Gizmos.DrawLine(prevPoint, point);
prevPoint = point;
}
}
}