Mathf.Acos
- 코사인(각도)에서 (각도)만 따로 반환해주는 수식이다.
- 실제 수식에서도 Cos(세타)에 Acos를 나누면 (세타)만 남는다.
Mathf.Rad2Deg
- 라디안 : 180도
- rad → deg ⇒ 180 / 파이 ⇒ r = 57.~을 라디안에 곱해주면 디그리가 나온다. → D
- deg → rad ⇒ 파이 / 180 ⇒ 0.017을 디그리에 곱하면 라디안이 나온다.
내적
- 좌우 상관이 없어서 정면을 기준으로 하면 왼쪽 오른쪽 모두 양수로 나와서 좌우 구별이 안간다.
- 아래 코드가 뭔 기능인지 녹음 10분에 나온다.
float dot = Vector3.Dot(forward, direction); //전방 벡터와 타겟을 바라보는 방향의 내적
float angle = Mathf.Acos(dot) * Mathf.Rad2Deg; //아크코사인은 코사인(각도)에서 (각도)만 따로 빼주는 수식이다. / Rad2Deg : 라디안 투 디그리 라는 뜻이다.
Vector3 cross = Vector3.Cross(forward, direction);
angle *= Mathf.Sign(Vector3.Dot(cross, Vector3.up)); //y값만 남는다. / Sign : 양수면 1, 음수면 -1을 반환한다.
승수 표
- 10-6f : 10의 -6승 = 0.000001
- 2e +7f : 20의 7승
타겟팅 순서도
- 타겟 대상 재선정
- 플레이어와 타게팅의 방향은 일치
- dot(플레이어와 타게팅의 방향, 다른 플레이어와의 방향)
- 방향을 찾아내야함
- 외적 방향을 이용, 오른쪽에 있는 적들만 내적 수행
Collider[] colliders = Physics.OverlapSphere(transform.position, radius, layerMask.value);
Dictionary<float, GameObject> candidateTable = new Dictionary<float, GameObject>(); //float : 내적값, GameObject : 내적값에 대한 오브젝트
foreach(Collider collider in colliders)
{
if(targetObject == collider.gameObject) //이미 선정된 타겟이니 할 필요 없다.
{
continue;
}
Vector3 vec1 = collider.transform.position; //게임오브젝트와 트랜스폼은 1대1이니 생략할 수 있다.
Vector3 vec2 = transform.position;
Vector3 direction = vec1 - vec2;
Vector3 cross = Vector3.Cross(transform.forward, direction.normalized); //외적
float distance = Vector3.Dot(cross, Vector3.up); //외적 : 기준측과의 거리와 수직의 거리는 같다. / 즉, 두 벡터에서 수직간 거리는 두 벡터의 거리와 같다. / 이 내적은 y값만 뺴올려는 내적이다.
candidateTable.Add(distance, collider.gameObject);
}
- 작업이나 코드작성이 어렵다면 순서도를 작성해봐라
LayerMask
- 시리얼라이즈 필드로 인자를 2개로하면 OR연산으로 값이 반환된다.
타겟 변경 순서도
- 타겟 재선정
- 재선정 이유 : ~~
- 수직간거리 = Cross(플레이어 전방, 적 방향)
- 수직간거리가 가장 작은 적을 찾아 저장
- 양 / 음의 방향 비교 후 가장 작은 적을 대상으로 선정
- 타겟 교체
float minimum = float.MaxValue; //최소는 플롯의 가장 큰 값이 들어간다.
GameObject candidate = null;
foreach(float distance in candidateTable.Keys) //키에 디스턴스를 넣어놨다.
{
if(Mathf.Abs(distance) < minimum)
{
if(bRight && distance > 0.0f) //우측방향이고 거리가 0보다 크다면
{
minimum = Mathf.Abs(distance);
candidate = candidateTable[distance];
}
if (bRight == false && distance < 0.0f) //좌측방향이고 거리가 0보다 작다면 / 0을 안찾는 이유는 타겟이 0(기준측)이기 때문이다.
{
minimum = Mathf.Abs(distance);
candidate = candidateTable[distance];
}
}//if(Mathf.Abs(distance) < minimum)
}
ChangeTarget(candidate);