153 lines
4.5 KiB
C#
153 lines
4.5 KiB
C#
using UnityEngine;
|
|
|
|
namespace Streamingle.Utils
|
|
{
|
|
/// <summary>
|
|
/// 타겟 오브젝트를 부드럽게 따라가는 컴포넌트
|
|
/// </summary>
|
|
public class SmoothFollow : MonoBehaviour
|
|
{
|
|
[Header("Target")]
|
|
[Tooltip("따라갈 대상 Transform")]
|
|
public Transform target;
|
|
|
|
[Header("Follow Settings")]
|
|
[Tooltip("위치 따라가기 활성화")]
|
|
public bool followPosition = true;
|
|
|
|
[Tooltip("회전 따라가기 활성화")]
|
|
public bool followRotation = false;
|
|
|
|
[Header("Smoothing")]
|
|
[Tooltip("위치 보간 속도 (낮을수록 더 부드럽게)")]
|
|
[Range(0.01f, 20f)]
|
|
public float positionSmoothSpeed = 5f;
|
|
|
|
[Tooltip("회전 보간 속도 (낮을수록 더 부드럽게)")]
|
|
[Range(0.01f, 20f)]
|
|
public float rotationSmoothSpeed = 5f;
|
|
|
|
[Header("Offset")]
|
|
[Tooltip("타겟으로부터의 위치 오프셋 (로컬 기준)")]
|
|
public Vector3 positionOffset = Vector3.zero;
|
|
|
|
[Tooltip("타겟으로부터의 회전 오프셋")]
|
|
public Vector3 rotationOffset = Vector3.zero;
|
|
|
|
[Header("Constraints")]
|
|
[Tooltip("X축 위치 고정")]
|
|
public bool freezePositionX = false;
|
|
[Tooltip("Y축 위치 고정")]
|
|
public bool freezePositionY = false;
|
|
[Tooltip("Z축 위치 고정")]
|
|
public bool freezePositionZ = false;
|
|
|
|
private Vector3 _initialPosition;
|
|
private Quaternion _initialRotation;
|
|
private Vector3 _velocity = Vector3.zero;
|
|
|
|
private void Awake()
|
|
{
|
|
_initialPosition = transform.position;
|
|
_initialRotation = transform.rotation;
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
if (target == null) return;
|
|
|
|
if (followPosition)
|
|
{
|
|
UpdatePosition();
|
|
}
|
|
|
|
if (followRotation)
|
|
{
|
|
UpdateRotation();
|
|
}
|
|
}
|
|
|
|
private void UpdatePosition()
|
|
{
|
|
// 타겟 위치 + 로컬 오프셋 계산
|
|
Vector3 targetPosition = target.TransformPoint(positionOffset);
|
|
|
|
// 부드러운 보간
|
|
Vector3 smoothedPosition = Vector3.Lerp(
|
|
transform.position,
|
|
targetPosition,
|
|
positionSmoothSpeed * Time.deltaTime
|
|
);
|
|
|
|
// 축 고정 적용
|
|
if (freezePositionX) smoothedPosition.x = _initialPosition.x;
|
|
if (freezePositionY) smoothedPosition.y = _initialPosition.y;
|
|
if (freezePositionZ) smoothedPosition.z = _initialPosition.z;
|
|
|
|
transform.position = smoothedPosition;
|
|
}
|
|
|
|
private void UpdateRotation()
|
|
{
|
|
Quaternion targetRotation = target.rotation * Quaternion.Euler(rotationOffset);
|
|
|
|
transform.rotation = Quaternion.Slerp(
|
|
transform.rotation,
|
|
targetRotation,
|
|
rotationSmoothSpeed * Time.deltaTime
|
|
);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 타겟을 런타임에 변경
|
|
/// </summary>
|
|
public void SetTarget(Transform newTarget)
|
|
{
|
|
target = newTarget;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 즉시 타겟 위치로 이동 (보간 없이)
|
|
/// </summary>
|
|
public void SnapToTarget()
|
|
{
|
|
if (target == null) return;
|
|
|
|
if (followPosition)
|
|
{
|
|
Vector3 targetPosition = target.TransformPoint(positionOffset);
|
|
if (freezePositionX) targetPosition.x = _initialPosition.x;
|
|
if (freezePositionY) targetPosition.y = _initialPosition.y;
|
|
if (freezePositionZ) targetPosition.z = _initialPosition.z;
|
|
transform.position = targetPosition;
|
|
}
|
|
|
|
if (followRotation)
|
|
{
|
|
transform.rotation = target.rotation * Quaternion.Euler(rotationOffset);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 초기 위치로 복귀
|
|
/// </summary>
|
|
public void ResetToInitial()
|
|
{
|
|
transform.position = _initialPosition;
|
|
transform.rotation = _initialRotation;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
if (target == null) return;
|
|
|
|
Gizmos.color = Color.cyan;
|
|
Vector3 targetPos = target.TransformPoint(positionOffset);
|
|
Gizmos.DrawLine(transform.position, targetPos);
|
|
Gizmos.DrawWireSphere(targetPos, 0.1f);
|
|
}
|
|
#endif
|
|
}
|
|
}
|