144 lines
4.4 KiB
C#
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;
|
|
}
|
|
}
|
|
} |