새로 생성한 스크립트
라이플 프리펩 캐릭터에 붙이기
- 프리펩 파일 자체를 사용하기보다는, 스크립트로 프리펩을 다루는게 사용하기 좋다.
- Hips를 타고 내려가면 Spine2가 나오는데 여기가 오른쪽 어깨와 가깝다
- 이 밑에 마우스 우클릭 → Create Empty → Helster_Rifle로 이름변경
- 홀스터가 생겼으면 거기에 잠시 프리펩 파일을 놓고 홀스터의 위치를 직접 변경한다.
- 홀스터 위치에 프리펩을 소환하면 준비가 완료되었다.
[SerializeField]
private GameObject rifle;
[SerializeField]
private Transform holster;
if(rifle != null)
{
rifleDestination = Instantiate(rifle, holster);
}
그래픽스 렌더링 파이프라인
- 오브젝트를 씬에 하나하나 그리는 절차
- 3D로 만들어진 모델을 2D에 투영하는 렌더링 과정의 프로세스를 자세하게 표현한 것이다.
- 즉, CPU에서 렌더링을 수행할 도형의 정점 정보들을 정점 버퍼라는 자료구조에 담아 GPU로 운반한다.
- 위치, 노말, 색상, uv 값들을 담고 있고, 이 값들은 구조체가 아닌 직렬화된 형태(배열)로 담겨 있다.
- 삼각형은 모든 도형의 기초가 된다.
- 오브젝트의 트리 삼각형으로 이루어져있다.
- 이게 쭉 이어져있다고 해서 ‘메쉬’라고 하낟.
- IA(Input Assemble) : 삼각형의 배열 데이터와 어떤 방식으로 그릴건지가 여기에 담겨져 있다.
- 입력 데이터(배열, Vector3(), ~ )
- Line(선이냐), Triangle(아니면 삼각형이냐)를 지정한다.
- CPU에서의 데이터 처리는 C#에서 하지만, GPU에서는 Shader를 사용해서 연산을 수행한다.(VS 역할)
- VS (Vertex(정점) Shader)
- Input Assembler 단계에서 정점 데이터를 입력 받아 공간 좌표계를 변환해준다.
- 도형의 꼭짓점을 점점(Vertex)라고 부른다.
- 기본적으로 도형들은 자신만의 좌표계인 Local Space의 좌표를 가지는데, 모든 물체들이 하나의 월드에 위치하도록 Local Space에서 World Space로 변환하고, 실제 플레이어가 바라보는 카메라가 중심이 되는 공간인 View Space로 변환해준다.
- 정점에서 MVP 연산이 이루어진다.
- M(Model) : 상대 좌표를 월드 좌표로 바꿔준다. (커피컵을 월드라고하고
- V(Veiw) : 카메라를 생각하면 된다.
- P (Projection) :
- 직교투영(Orthographic) : 멀리있든 가까이있는 크기가 일정하게 보인다. VP의 모양이 직육면체로 보인다.
- 원근투영 (perpective) : 멀리있는건 작게 보이고 가까이 있는건 크게 보인다. VP의 모양이 피라미드로 생겼다.
- near / far
- 피라미드 모양으로 시야의 설정을 조절할 때 사용한다.
- near :
- far : 멀리있는게 얼마만큼의 거리로 보이는가
- RS (Rasterizer stage)
- NDC : 2D 처럼 보이는 공간
- RS는 3D 공간을 NDC같이 2D의 공간으로 보여주는 기능을 의미한다.
- VP (View Port) : 우리의 화면에 비춰질 영역
- RS는 VP를 연산한다.
- PS (Pixel Shader)
- 화면을 이루는건 픽셀이다.
- 이 픽셀을 처리해 주는게 shader다.
- for문으로 1920 * 1080의 픽셀을 계산하려면 어마어마한 계산을 처리해야한다.
- GPU는 여러 작업을 한번에 처리하기 떄문에 이 작을을 Shaeder가 처리한다.
- DSV, RTU도 PS처럼 RS에서 받아서 비슷한 순서로 처리된다.
- OM : 최종 결과를 하나로 합친다.
월드변환
- 월드변환 : 로컬 좌표에 있는 3D 오브젝트의 각 정점을 월드 좌표로 변환한다.
- 정리 : 3D 오브젝트의 각 정점은 로컬좌표로 저장되어 있다.
- 각 정점의 로컬좌표를 월드 좌표계로 변환하는 것.
- 회전은 오일락 변환과 쿼터니온이 있는데, 쿼터니온을 주로 사용한다.
- 쿼터니온 사용이유
- 짐벌락문제 방지
- 행렬은 계산이 많기 때문에 연산량 감소를 위해 사용한다.
선형보간 (Lerp)
- (1 - t) * A + (t * B)
- (10, 0, 0) (40, 0, 0)이 있는데 25%만 갔다면?
- (1-0.25) * 10 + 0.25 * 40 = 7.5 + 10 = 17.5
메시 콜라이더
- 삼각형 단위로 충돌을 검사한다.
- 연산량이 너무 많아 게임 플레이가 사실상 어려움(불가능하다)
가변형 배열
- 데이터의 전체 크기를 알 수 없을 때 사용한다.
가상 함수
- 부모 클래스에 정의되어 있는 함수를 재정의하는 함수
벡터 특성 정리
- x, y, z, w (PS는 2D이기에 동차가 나오지만, VS는 3D를 나타내기 때문에 위치(1이면, 즉 position까지 계산한다.) 혹은 방향(0이면)이다.
- x y z | w ⇒ 여기서 x는 Position x를 나타낸다
- x y z | w ⇒ 여기서 x y z는 Position y를 나타낸다
- x y z | w ⇒ 여기서 x y z는 Position z를 나타낸다
- x y z | w ⇒ 여기서 x y z는 Position을 나타낸다
- A위치 + B위치 = A → B 위치
- A위치 - B위치 = B → A 방향벡터 (거리(방향과 크기)를 나타낸다)
- A위치 + (B방향 * 거리(A위치 - B위치)) = B의 방향으로 거리만큼 A를 이동시킨 위치 벡터
- 노멀라이즈 : 방향벡터를 1로 만들어 사용하는것을 의미한다.
- 크기를 1로 만들면 내가 갈 거리만 곱하면 간 거리가 나오니 계산이 편해진다.
내적 (Dot)
- 내부의 각도를 본다
- A ‘ B → (A’x * B’x) +(A’yB’y) + (A’zB’z) → |A|(방향벡터) * |B| * cos(세타) ⇒ 두 방향벡터를 노멀라이즈에서 1로 만들면 cos(세타)(=라디안 Radian)만 남는다 ⇒ 두 방향의 사잇값을 알아내려할떄 이 식을 사용한다.
- 파이(3.14 기호)는 180도다.
- 내적의 문제점
- cos(theta) 갑의 범위, 0 ~ 180 까지만 판단할 수 있다.
- 그래서 좌 / 우를 판단할 수 없다.
- 해결방법 : 방향 판단은 외적으로 가능하다.
- 노멀 벡터 : 면에 수직인 선
- 쓰이는 용도 : 해같은 광원의 방향과 면에 수직인 벡터를 구해 음영이 나타나는 부분을 찾기위해 사용하낟.
외적
- 위는 1, 오른쪽 90도는 0, 아래는 -1, 왼쪽 90도는 0이다. (호도법)
- 이것도 식을 알아놓아야 한다.
- 기준선으로 이동하면 기즈모는 거의 변화가 없다
- 기준선에서 왼쪽과 오른쪽을 구별할떄 사용한다.
- 기즈모의 녹색 기준선 선의 y축 길이와 오브젝트의 x방향 벡터가 연결되어있어 오브젝트가 오른쪽으로 멀어지면 기준선은 y는 +방향으로 길어지고, 오브젝트가 왼쪽으로 멀어지면 기준선은 -방향(플레인 바닥부분)으로 길어진다
- (위치벡터A - 위치벡터 B)
- B위치벡터가 A위치벡터를 바라보는 방향벡터(크기 : 거리)
타격감이 나타나는 요소
- 타격 피격 모션
- 사운드
- 경직 (hit stop)
- 맞은 효과
- 패드 진동
- 콤보를 넣을때 타격 모션이 어긋나지않게하기 위해 공격하는 적을 향해 카메라가 고정된다. (이떄 외적을 쓴다.)
- 내적은 적의 위치를 찾아준다.
- 내 카메라에 가장 정면에 있는 적을 찾을 때, 내적각이 가장 1에 가까울 때가 내 정면에 있는 것이다..
- 외적은 타겟팅 만들때 사용한다.
- 타겟팅한 적을 다른 적으로 옮길 떄 현재 타겟팅된 적을 기준으로 얘 오른쪽에 있냐 왼쪽이냐를 판단할 떄 외적을 쓴다.
- 콤보가 끊기지 않기위해 조금씩 밀려나게 한다.
충돌(Collider)
메모리 단편화
- 메모리공간에 빈공간이 생겼지만 최대 크기보다 큰 메모리가 못들어가 빈공간이 생기는 현상
- 해결방법 : 메모리 풀(배열을 쓰고 대체적으로 가변형 배열로 쓴다) : 이 맵에 들어갈 몹의 최대 겟수를 메모리 풀에 미리 생성한다
- 이걸 출현하는 위치에 소환해서 초기화하고, 죽으면 안나타나게 끈다.
메모리 풀
- 사용이 예상되는 객체의 수 만큼 미리 생성한다.
- 메모리 소모 감소, 메모리 단편화 예방
- 배열 또는 리스트로 구현한다.
콤보 구현
- 큐로 구현한다. (들어가는 순서대로 처리한다)
- 근데, 실제로는 이걸로 안된다. (콤보 취소가 안되기 때문)
- 우선순위 큐로 구현한다.
알고리즘 복잡도
- 복잡도 (시간과 공간으로 이루어진다.)
- 시간복잡도 : 최선의 상황, 평균, 최악일떄 수행되는 시간
- 시간복잡도 : O(1) → O(log n)(이진트리에서 반씩 버려가면서 탐색하는 것) → O(n)(for문) → O(n*log n) → O(n제곱)(이중for문) (빅오 표기법)
- n을 찾을때 최악은 순차탐색이 n까지 하나씩 찾아보는 것이 가장 오래걸린다.
- 최선은 한번에 찾는거
- 공간복잡도 : 알고리즘이 문제를 해결하기 위해 필요한 메모리 양
- 최악의 알고리즘 수행시간
- 벡터 내적식, 두가지
- (a.x * b.x) + (a.y * b.y) + (a.z * b.z) = |A|(A크기) * |B| * cos(theta)
- 구 충돌
- r1, r2 - 반지름
- c1, c2 - 중심점
- (r1 + r2) ≥ (c1과 C2사이의 거리) (가 같다면 충돌이 일어났다는 것이다.)
플래그
- 01010010 & 00010000 ⇒ 결과가 0보다 크면 플래그 세팅이 되어 있는것이다.
AABB (Access Around Bounding Box)
- 축이 정렬되어있는 충돌
- 구와 박스가 있을때 충돌은 구의 중심과 꼭짓점을 확인한다.
- 각 꼭짓점 중 하나와 원의 중심점과의 거리를 계산했을때, 원의 반지름보다 작다면 충돌로 간주한다.
OBB (Oriented BOunding Box)
이진트리
- 2진트리, 완전 이진 트리, 포화 이진 트리, 경사형 트리, 균형 이진 트리
- 딕셔너리에서 키값 관리를 균형 이진트리로 한다.
- 경사형 트리 : 트리의 밸런스가 무너진 상황, 시간복잡도 O(n)
- 해결 방법 : 균형 이진트리를 이용, 노드의 삽입과 삭제시에 균형을 유지해 준다.
백페이스 컬링
- 앞면은 면이 있고 뒷면은 투명해서 통과되어 보이는 그래픽(플레인, 붜드)
- 삼각형의 앞면과 뒷면을 구분해야한다.
- 삼각형의 노멀 벡터와 카메라 방향 벡터의 사이각이 90도 이상이면 앞면이 카메라에 렌더링되어 비춰진다.
- 정점 v1, v0, 02 가있다
- e1 = (v1 - v0)
- e2 = (v2 - v0)
- cross(e1, e2) → 노멀벡터를 만드는 식
프러스텀 (절두체)
- 카메라가 렌더링할 영역
- 이것을 벗어나면 렌더링 되지 않는다. (우리 눈에 보여지지 않는다)
그래프
- 게임에서 최단거리를 찾기 위해 사용한다.
- 다익스트라, 에이 스타, 벨만포드, 워셔
정렬
- n log n - 2가지 (얘들을 주로 쓴다.)
- n 제곱 - 3가지(거의 안쓴다, 느려서)
버블 정렬
- 인접한 두 수를 비교해서 작으면 왼쪽 크명 오른쪽으로 놓는다.
- 한칸 옆으로 가서 다시 인접한 두 수를 비교한다.
- 끝날때까지 반복
- 한줄이 끝나면 처음으로 돌아가서 처음 행동을 다시 반복
- 정렬이 되더라도 인자의 갯수만큼 계속 반복한다.
해싱
- 해싱되어있는 값이 저장되어있는 공간 = 해싱 테이블
- 주소가 저장되어있고 이 주소에 데이터가 저장되어있다.
- 어떤 문자를 해싱하면 주소가 나와서 해싱테이블로 접근하고 그것으로 데이터를 가져올 수 있다.