반응형
struct RotData
{
// 회전 데이터
public float angle; // 회전 각도
public float rotDir; // 회전 방향
}
void CalculateAngle(Vector3 forwardDir, Vector3 rightDir, Vector3 lookDir, out RotData data)
{
// 각도 계산 함수
// 자신의 앞 방향 forwardDir과 바라봐야 할 방향 lookDir 사이의 각도를 구하는 함수
// 1. 각 입력 벡터를 정규화하여 크기를 1로 세팅
// 2. 두 벡터 사이의 각도를 x라고 하면 cos(x)는 자신의 forwardDir의 크기 1과 forwardDir, lookDir의 내적값의 크기 d로 구할 수 있음
// 3. cos(x) = d/1 = d
// 4. 우리가 구해야 할 것은 x이므로 cos의 역함수 acos을 이용해 x = acos(d)로 구할 수 있음
// 5. 자신의 오른쪽 방향 rightDir과 lookDir를 내적했을 때의 값이 양수인지 음수인지 판단하여 회전방향을 결정
// 각 벡터를 정규화
Vector3 NomForwardDir = forwardDir.normalized;
Vector3 NomLookDir = lookDir.normalized;
float dot = Vector3.Dot(NomForwardDir, NomLookDir); // 두 벡터의 정규화된 값을 내적하여 내적값의 크기 d를 구함
float rad = Mathf.Acos(dot); // 내적값 dot를 이용해 두 벡터 사이의 각도 rad을 구함(이 값은 라디안 값임)
data.angle = 180 * (rad / Mathf.PI); // 계산한 각도를 degree 값으로 변경하여 회전데이터에 저장
data.rotDir = 1.0f; // 회전 방향값 -> 오른쪽 회전
// 두 벡터 사이의 각도가 180도 이상인 경우 -> rightDir과의 내적값이 음수인 경우
if (Vector3.Dot(rightDir.normalized, NomLookDir) < 0)
{
data.rotDir = -1.0f; // 회전 방향을 반대로 해줌 -> 왼쪽 회전
}
}
// 코루틴으로 동작
IEnumerator LookTarget()
{
// 회전 데이터 생성
RotData rotData;
// 바라봐야할 방향
Vector3 lookDir = Target.transform.position - this.transform.position;
// 회전해야할 각도 설정
CalculateAngle(this.transform.forward, this.transform.right, lookDir, out rotData);
while (rotData.angle > 0)
{
float Tick = Time.deltaTime * 360; // 얼마나 회전할지를 나타냄
Tick = rotData.angle > Tick ? Tick : rotData.angle;
// 회전
this.transform.eulerAngles += Vector3.up * Tick * rotData.rotDir;
rotData.angle -= Tick;
yield return null;
}
print("rotate end");
}