89 lines
3.4 KiB
C#
89 lines
3.4 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
namespace Samkwang
|
|
{
|
|
public class ObjectTourController : MonoBehaviour
|
|
{
|
|
public Transform controlObject;
|
|
public ObjectTourPoint[] tourPoints;
|
|
|
|
public float moveSpeed = 2f; // 이동 속도 (SmoothDamp의 maxSpeed 대신 이동속도로 사용)
|
|
public float turnSpeedDegrees = 120f; // 초당 최대 회전 각도 (degree/sec)
|
|
public float arrivalThreshold = 0.05f;
|
|
|
|
// look-ahead: 목표에 가까워질때 다음 포인트 방향으로 미리 보도록 하는 거리
|
|
public float lookAheadDistance = 1.0f;
|
|
|
|
private int currentIndex = 0;
|
|
|
|
private void Start()
|
|
{
|
|
controlObject = transform.Find("Walking_cart").transform;
|
|
tourPoints = transform.GetComponentsInChildren<ObjectTourPoint>().OrderBy(p => p.transform.GetSiblingIndex()).ToArray();
|
|
|
|
if (tourPoints.Length > 0)
|
|
StartCoroutine(MoveTour());
|
|
}
|
|
|
|
private IEnumerator MoveTour()
|
|
{
|
|
while (true)
|
|
{
|
|
yield return StartCoroutine(MoveToTarget(currentIndex));
|
|
|
|
currentIndex = (currentIndex + 1) % tourPoints.Length;
|
|
}
|
|
}
|
|
|
|
private IEnumerator MoveToTarget(int index)
|
|
{
|
|
Transform target = tourPoints[index].transform;
|
|
Transform nextTarget = tourPoints[(index + 1) % tourPoints.Length].transform;
|
|
|
|
while (Vector3.Distance(controlObject.position, target.position) > arrivalThreshold)
|
|
{
|
|
// --- 위치 이동 (SmoothDamp style)
|
|
// SmoothDamp의 maxSpeed 파라미터 대신 단순 MoveTowards 기반으로 안정적 제어
|
|
float step = moveSpeed * Time.deltaTime;
|
|
controlObject.position = Vector3.MoveTowards(controlObject.position, target.position, step);
|
|
|
|
// --- 회전: look-ahead 처리
|
|
float distToTarget = Vector3.Distance(controlObject.position, target.position);
|
|
|
|
// 가까워질수록 다음 포인트를 더 바라보게 보간
|
|
Vector3 desiredLookPos;
|
|
if (distToTarget <= lookAheadDistance)
|
|
{
|
|
// 보간 비율: 0(멀때) -> 1(가까울때)
|
|
float t = Mathf.InverseLerp(lookAheadDistance, 0f, distToTarget);
|
|
Vector3 dirToCurrent = (target.position - controlObject.position).normalized;
|
|
Vector3 dirToNext = (nextTarget.position - controlObject.position).normalized;
|
|
Vector3 blendedDir = Vector3.Slerp(dirToCurrent, dirToNext, t).normalized;
|
|
desiredLookPos = controlObject.position + blendedDir;
|
|
}
|
|
else
|
|
{
|
|
desiredLookPos = target.position;
|
|
}
|
|
|
|
Vector3 dir = (desiredLookPos - controlObject.position);
|
|
if (dir.sqrMagnitude > 0.0001f)
|
|
{
|
|
Quaternion targetRot = Quaternion.LookRotation(dir.normalized);
|
|
|
|
// 초당 회전 한계를 적용 (더 자연스러운 회전)
|
|
float maxDeg = turnSpeedDegrees * Time.deltaTime;
|
|
controlObject.rotation = Quaternion.RotateTowards(controlObject.rotation, targetRot, maxDeg);
|
|
}
|
|
|
|
yield return null;
|
|
}
|
|
|
|
// 도착 후 정확히 위치/회전 정렬 (선택)
|
|
controlObject.position = target.position;
|
|
}
|
|
}
|
|
} |