https://gall.dcinside.com/mgallery/board/view/?id=game_dev&no=130050&search_head=10&page=1

응애일지 - 장애물 회피(4) - 인디 게임 개발 마이너 갤러리

https://gall.dcinside.com/mgallery/board/view/?id=game_dev&no=129978&search_head=10&page=1 응애일지 - 장애

gall.dcinside.com


4편에서 이어짐.


목표

이번엔 수직벡터를 두 방향으로 만들어서, 장애물의 왼쪽에 가까우면 왼쪽으로, 오른쪽에 가까우면 오른쪽으로 틀게 할 거임.


18b3c42ff1de3da220afd8b236ef203e2776b4655ca5ef

대충 이렇게.

transform.forward 기준으로 180도는 -90도 회전, -180도 까지는 90도 회전하게.


계산법은 외적으로 간단하게 처리했음. 어차피 각도가 필요한 건 아니라서.


18b3c42ff1de3da22ef787fc58c12a3a435b9888af1ebdf079e1

verticalVec = Vector3.Cross(transform.forward, counterVec).normalized.y > 0 ? new Vector3(-counterVec.z, 0, counterVec.x) : new Vector3(counterVec.z, 0, -counterVec.x);


대충 이런 느낌.



39aadf66e1db2aa36dabdfba189f23340cbf76fc645372f51af754ebe83e

: 대충 생각대로 된다.


근데 역시, 간단한 아이디어라 발견하지 못한 문제가 있었음.



2bbcd92af0c03de869b6d09528d5270350e8c3692eee3647

짜잔.

애들이 가까운 쪽으로 안 가고, 먼 쪽으로 가기 시작했음.



2bb2c534a5c637e668b0c3a758d62d3b57f6020a1c6216e8bec9ccaaec

그 때문에 들이박고 헤매고 아주 난리도 아님


문제 원인을 생각해보면, 대충 아래와 같음.



18b3c42ff1de3da22ef782fc58c12a3a7bccb65de589e69ed0bd4e

예상)

transform.forward를 기준으로 함.

이걸 기준으로 장애물과의 카운터 벡터를 계산하면, 장애물 왼쪽에 가까우면 카운터 벡터와의 각도가 180도를 넘어서 오른쪽에 있다고 판단하겠지?


현실)

transform.forward를 기준으로 하기때문에, 유닛의 대가리 기준으로 장애물은 왼쪽에 있다.

설상가상으로, 왼쪽 장애물이 더 가깝게 있기 때문에, 실제로 각도는 180도 이하, 즉 왼쪽에 있다고 판단된다.



18b3c42ff1de3da22ef785fc58c12a3a5e97668b1cc6a4dcd6e546

: 그리고 실제로도 그렇다.


유닛의 각도 때문에 문제라면, 유닛이 수직에 가깝게 장애물에 들이박으면 문제가 안생겨야 함.

3ab2c22df69c3faf689fe8b115ef046f176f81187e84

: 예상대로 됐음. 장애물을 인식할 때의 유닛 각도가 문제인 거임.


그럼 이제 문제 원인을 파악했으니 어케해야될까.

사실 여기서 뇌정지가 잠깐 왔었는데, 일단 대충 두 가지 방법이 떠올랐음.


1. 벡터 성분 쪼개기.

z축으로 이동하는 케이스에서는, 대가리가 오른쪽으로 돌아가있어도 z축을 기준으로 체크를 해야 됨.

그럼 걍 vector3.forward 를 transform.forward 대신 쓰면 된다는 말임.


이걸 어케 일반화 해야될까?


현재 이동중인 방향에 가장 가까운 기저를 비교대상으로 써야 하는데.


그래서 걍 transform.forward의 x, z성분의 크기를 비교해서 더 큰 쪽만 쓰기로 했음.



3bb8d332eac078b57eb3dfa158d62d3b207275130157af8595b7a2855bb7

: 거의 완벽하게 생각대로 동작하는 것 "처럼" 보인다.


하지만 역시나 고민없이 생각한 아이디어는 하자가 있다는 불변의 법칙을 깨지 못하고, 이것도 하자가 있었다.


z축, x축을 기준으로 한 이동은 제대로 동작하나, 대각선 방향으로 이동하는 건 오히려 기존 방식보다 못하다는 것.



3bb8d332eac078b57eb3dfa156d7253474e7a997e941404e1a3b1cada24e5e5e6bb53084b0

: 짜잔. 치고박고 난리났다. 게다가 이번엔 무조건 원하는 방향의 반대로 이동한다.


문제 원인 파악


18b3c42ff1de3da22ef783fc58c12a3ad8db11e1269281b8ae3212

: 장애물은 유닛을 기준으로 우측에 있는 것으로 보이나



18b3c42ff1de3da22ef780fc58c12a3aa33c5512c1c2c8da681371

: 실제로는 왼쪽에 있는 것으로 판정이 이루어진다.

transform.forward의 x, z값을 쪼개면, 기준 벡터가 Vector3.forward가 되기 때문.


이 방식을 유지하면서 저 문제를 해결하려면 4방위가 아니라 8방위, 16방위 등 더 많고 귀찮고 버그 많이생기는 안 좋은 방법을 써야 할 것으로 생각됐다.

그래서 걍 방식을 바꾸기로 했음.


2. 타겟 벡터를 기준으로.

transform.forward 대신 target.position - transform.position을 사용했을 때의 이점은 아래와 같다.



18b3c42ff1de3da22ef781fc58c12a3a9e9b6988394d4e55ab48

유닛 방향이 이상하게 됐더라도, 타겟 벡터는 변하지 않는다.

따라서 기존 방식 대비, 어떤 각도에서 장애물을 만나더라도 일관적인 방향계산이 이루어진다.



39bcc221e0c628a97df1d1bc10f11a39ac2d81006dd89a17aafc

: 완벽하지는 않지만, 기존 방식 대비 확실히 더 효과적인 것을 볼 수 있다.


대충 적당히 굴러간다.


근데 사실 처음부터 생각 없이 transform.forward 쓰지 말고 걍 타겟 벡터 썼으면 삽질할 일도 없었는데.

이래서 샤람은 생각을 하면서 살아야 되는 건가 보다.


응애일지 끝