좀비가 플레이어를 인지하는 범위가 마치 사람이 보는 시야의 각처럼 시야각안에 들어와야지만 인지가 되는것이 3D에서 훨씬 자연스럽다. 그 시야각을 구현하기 위한 기술(?)이다.
Vector3.Angle은 두 벡터 사이의 각도(Degree)를 계산하기에 직관적으로 이해하기 편하고 시인성이 좋지만, 내부적으로 ArcCos함수를 사용하여 계산하므로 연산비용이 비교적 높다.
나의 경우는 Behavior Tree에서 트리가 매 프레임마다 순회를 돌고있고, 좀비가 플레이어를 감지하는 로직의 노드는 매우 자주일어나는 연산이기에 이 부분에서는 최대한 최적화를 진행해주는 것이 좋겠다고 생각하였다.
그래서 생각중인 방식이 Vector3.Dot인데, Vector3.Dot은 두 벡터의 내적을 계산하기에 두 벡터의 길이와 각도(Cos)에 의해서 결정된다. 그래서 Angle보다 연산 비용이 낮다. "참고로 벡터의 내적은 스칼라(Scaler, 방향 x 크기만 존재)"
또는 아예 벡터를 이용해 직접 각을 라디안으로 구하여 비교할지도 고민중이다.
출저 - 나무위키
벡터의 덧셈 : a벡터 + b벡터라면 a와 b벡터가 서로 벡터만큼 (ax + bx) + (ay + by) 하면 평행사변형이 나오는데 그 두 벡터의 중심으로 나가는 방향 길이는 두 벡터의 합만큼 나온다.
벡터의 뺄셈 : a벡터 + (-b)벡터라면 b벡터에서 a벡터로 향하는 방향이 나온다. (벡터의 덧셈에서 평행사변형이 반대편에서 이루어지는 걸로 보면 쉽다.)
magnitude : 벡터의 길이(힘|속력|거리)만 남긴다.
normalized : 벡터의 방향만 남긴다.
π = 3.14 , 원주율
원의 지름이 1 일 때, 한바퀴 굴렀을때의 거리 : 3.14
출저 - 유니티지현쨩
Mathf.Rad2Deg : Radian -> Degree
Mathf.Deg2Rad : Degree -> Radian
출저 - 유니티지현쨩
삼각함수의 Sin과 Cos을 합치면 원이 된다. (Sin을 y축으로, Cos을 x축으로 두고 서로 그래프를 그리면 원이 된다.)
Sin이 클 수록 Cos은 작아지고, Cos이 클 수록 Sin은 작아진다.
Sin이 y축으로 움직이는 동시에 Cos이 x축으로 움직이면서 원이 그려진다.
빗변이 1이라고 하였을 때, (normalize, 정규화 하여 방향만 남음)
Cos𝜽 = 밑변/빗변(=1)을 하면 밑변이 나오는데 그 밑변의 길이가 x축 즉 Cos𝜽가 된다.
Sin𝜽는 높이/빗변(=1)을 하면 높이가 나오는데 그 높이의 길이가 y축 즉 Sin가 된다.
출저 - 유니티지현쨩
출저 - 유니티지현쨩
벡터 a, b가 normalize(정규화)되어서 둘 다 방향만 남아 길이가 1인 경우, a 와 b벡터의 내적은 Cos𝜽이다.
그러면 두 벡터가
같은 방향을 바라본다면, 1
수직인 경우, 0
반대 방향인 경우는, -1
출저 - 유니티지현쨩
BTActionNode.cs
클래스를 생성하여 각각의 행동을 구현할 수 있습니다.PlayerFSM.cs
내에서 특정 상태에서 BT를 실행하는 방식으로 구현할 수 있을겁니다. BT 실행 로직은 ExecuteUpdate
메서드 내에서 호출하면 되겠죠?BehaviorTreeAsset.cs
라는 Scriptable Object 클래스를 생성하고, 이를 통해 트리의 구조와 노드의 설정을 관리하는 형태가 되겠죠? BT 설정을 쉽게 조정할 수 있다는 장점이 있어서 개발 효율성이 높아진다는 장점이 있긴한데, 꼭 반드시 구현해야만하는 것은 아니니까 시간이 된다면 한번 도전해보세요.EnemyAI.cs
에서 플레이어의 위치 변화나 환경 변화에 따라 BT를 업데이트하도록 할 수 있습니다.EnemySight.cs
에서 OverlapSphere
로 플레이어를 감지한 후, Raycast를 사용하여 시야 내에 플레이어가 있는지 확인할 수 있겠네요.EnemyAnimator.cs
에서 상태에 따른 애니메이션 전환 로직을 구현하고, 외부에서 애니메이션 파라미터를 조절할 수 있도록 해보세요.BT의 노드들을 별도의 클래스로 분리하여 각 노드별로 책임을 명확히 하는 것이 좋습니다. 현재 Func
을 사용하여 행동을 정의하는 부분을 각기 다른 클래스로 분리합니다. 예를 들어, ActionNode
, SequenceNode
, SelectorNode
등으로 나눌 수 있을겁니다.
BT의 업데이트 메커니즘을 매 프레임마다 전체 트리를 순회하는 대신, 이벤트 기반으로 변경하여 필요할 때만 트리의 일부를 업데이트하고 순회하도록 하면 좋을듯해요.
일단 FOV기능을 완성 시키고, 자잘한 버그를 잡은 뒤에 튜터님이 말씀해주신 부분에 대해서 리팩토링을 진행할 예정이다. (노드 클래스 분할, 업데이트 지향 이벤트 사용, 애니메이터 따로 클래스 관리)
차근차근 빠르면서 천천히 하나씩 해보도록 하겠다.
바쁘신 와중에 이렇게 자세하고 뼈와 살이 되는 피드백을 주신 튜터님에게 너무 감사하다.