이 5시간짜리 강의를 하루면 다 들을 수 있다고 생각한 내가 정말 오만했다는 사실을 깨달아버렸다... 주말에 갠프하는 한이 있더라도 오늘까지는 강의를 다 듣고야 말겠다.
목 차
조준(Aim) 시스템
쿼터니언(Quaternion)
Quaternion: 4가지 숫자가 관여하는 개념이며, 라틴어로 직역하면 4개의 수 라는 뜻이다.
x, y, z는 3차원 공간의 좌표에 추가적으로 w는 회전과 관련된 변수이다.
#짐벌 락 문제
이 그림을 보면 pitch 각도(핑크색)을 90도로 회전시켰을 때 남은 롤 축과 요 축(파랑&초록)이 동일해져 버리는 현상을 확인할 수 있다. 이는 곧 독립적인 세 회전축 중 하나를 잃었다는 뜻으로, 특정 방향으로의 회전이 불가능해져 버린다. 더 자세한 걸 알고싶으면 위 이미지의 출처인 아래 링크로 가라.
# Quaternion 관련 Unity 내장 함수
다만, 우리가 x, y, z, w를 직접 조작하려 하면 안된다. 어렵기도 하거니와, 이미 존재하는 내장함수가 있기에 계산할 능력이 있다 하더라도 그 능력을 다른 데에 쓰면 썼지 낭비가 될 수 있기 때문이다. 즉, 수학 잘한다고 나대지 말고 나보다 똑똑한 분들이 미리 만들어둔 기능을 활용하자.
public static Quaternion Euler(float x, float y, float z); //선언1-1
public static Quaternion Euler(Vector3 euler); //선언1-2
Quaternion rotation = Quaternion.Euler(45, 30, 60); //예제1
public static Quaternion LookRotation(Vector3 forward, Vector3 upwards = Vector3.up); //선언2
Vector3 targetDirection = target.position - transform.position;
Quaternion rotation = Quaternion.LookRotation(targetDirection); //예제2
public static Quaternion Slerp(Quaternion a, Quaternion b, float t); //선언3
Quaternion from = Quaternion.Euler(0, 0, 0);
Quaternion to = Quaternion.Euler(0, 90, 0);
Quaternion result = Quaternion.Slerp(from, to, 0.5f); //예제3
- Quaternion.Euler: 오일러 각도를 쿼터니언으로 변환해준다.
- Quaternion.LookRotation: 앞과 위를 특정한 방향으로 하는 회전 쿼터니언을 만들어준다.
- Quaternion.Slerp(에스럴프): 두 쿼터니언 사이의 내분점을 알려준다. (Q1, Q2 사이의 30% 지점 등)
등의 관련 함수가 존재하니 필요하면 활용해보자.
쿼터니언은 직관적인 수체계를 사용하지 않으며, 직접 값을 적용하려면 Quaternion.Identity(회전이 없는 상태의 쿼터니언)만 사용하라.
삼각함수 기초와 아크탄젠트
#삼각함수의 정의
삼각함수: 각도를 통해 각 변의 비율을 알 수 있는 함수
sinθ = 높이/빗변
cosθ = 밑변/빗변
tanθ = 높이/밑변
cosecθ, secθ, cotanθ은 위의 세 값의 분자/분모를 거꾸로 한 것.(=역수)
위의 6개 값 앞에 arc(아크)가 붙으면 값으로 "각도"를 불러오는 것.
* 역수와 역함수를 헷갈리지 말 것!!! (사실 내가 헷갈릴까봐) *
#Unity에서의 활용
- Math.Atan: 단순한 탄젠트 값에 대한 각도를 찾을 때 사용한다.
- Math.Atan2: x, y 자체의 양음을 통해 360도를 구분할 수 있게 해준다. (y, x 순)
= (0,0) ~ (x,y)를 이은 선과 x축 양의 방향에 대한 각도.
반환값은 -π ~ π.(대충 각도의 다른 단위. π라디안 = 180도.)
공격 시스템 구현
프리팹(Prefab)
- 영단어 정의: 조립식.
- 유니티에서의 정의: Unity 게임 엔진에서 사용되는 게임 오브젝트를 재사용 가능하고 관리하기 쉽게 만들기 위한 템플릿, 프리셋.
- 클래스의 객체를 만드는 것마냥 인스턴스 화를 통해 게임 오브젝트로 변환 가능, 모든 설정 복사된다.
- 프리팹을 변경하면 모든 인스턴스에 즉각 반영되므로 일관성 유지 / 일괄 업데이트가 쉬워진다.
- ex) 레벨 디자인, 재사용 가능한 게임요소(캐릭터, 아이템, 장애물 등)의 생성, 프로토타이핑 등.
Instantiate 함수
- Unity에서 제공하는 원본 개체의 복사본을 생성하고 반환하는 메서드.
- 게임 오브젝트 등을 동적으로 게임세계에 추가할 때 사용한다.
- 원본의 모든 컴포넌트 & 프로퍼티를 복사하여 새 게임 오브젝트 생성한다.
- 복사된 게임오브젝트는 독립적이며, 원본에 영향을 주지 않는다.
- 원본의 오브젝트, 위치 및 회전 정보를 인자로 받을 수 있다.
스텟 시스템 Base!
열거형(enum)
4주차 강의 때 나오긴 했지만, 딱히 어려울 것이 없어 정리하지 않은 내용이다.
- 숫자의 추상화.(상수형 값에 의미를 부여해주는 배열)
- 보통 enum 배열은 앞에 e를 붙여주고 "의미"들은 대문자로 써준다.
- 시작값에 특정 숫자 (ex-weapon = 100)을 넣어주면 거기서부터 1씩 커질 수도 있다.
스크립터블 오브젝트(Scriptable Object)
- 데이터를 저장하는 컨테이너.
- 재사용 가능한 데이터 또는 설정을 저장한다.
- 코드와 데이터를 분리하여 코드를 깔끔하게 한다.
(아마 리스트에 일일이 .Add 해주는 대신 .json파일 만든다던 그런거인듯?) - 하나의 스크립터블 오브젝트를 여러 게임 오브젝트에서 참조 / 재사용 가능하다.
- Unity 에디터의 인스펙터 창에서 직접 수정 & 관리할 수 있다.
직접 따라해보기는 하겠지만, 예시가 필요할 것 같아 코드블럭도 들고 왔다.
using UnityEngine;
[CreateAssetMenu(fileName = "DefaultAttackSO", menuName = "TopDownController/Attacks/Default", order = 0)]
public class AttackSO : ScriptableObject
{
// 공격에 대한 기준 데이터를 유니티 에디터 상에서 편하게 관리할 수 있어요.
// SO로 들고 있으면 모두가 이 SO를 바라보게 되어
//중복된 데이터가 여기저기 흘러다니지 않는 장점이 있어요!
[Header("Attack Info")]
public float size;
public float delay;
public float power;
public float speed;
public LayerMask target;
[Header("Knock Back Info")]
public bool isOnKnockback;
public float knockbackPower;
public float knockbackTime;
}
투사체 구현하기
비트 연산자, 레이어 마스크
#비트 연산자
- AND (&) : 두 비트 필드 모두에서 해당 비트가 설정되어 있을 때만 1
특정 레이어의 존재 여부를 확인 - OR (|) : 두 비트 필드 중 하나라도 해당 비트가 설정되어 있으면 1
새로운 레이어를 추가할 때 유용 - XOR (^) : 두 비트 필드에서 해당 비트가 서로 다를 때만 1
두 레이어의 차이를 찾을 때 - NOT (~) : 모든 비트를 반전
특정 레이어를 제외시킬 때 - 비트 시프트 연산(<<) : 1을 N번째 비트 위치로 시프트.(위의 그림 참고)
N번째 레이어를 나타내는 비트마스크 생성.
비트 연산은 물리 충돌, 레이캐스팅, 카메라 렌더링 등을 제어하는데에 사용된다.
- 충돌 검사: 비트마스킹을 사용하여 특정 레이어에 속한 오브젝트만을 대상으로 충돌 검사를 수행한다.
- 레이캐스팅 제어: 레이캐스트가 특정 레이어의 오브젝트에만 반응하도록 비트마스크를 설정한다.
- 카메라 렌더링 설정: 카메라가 특정 레이어의 오브젝트만을 렌더링하도록 설정하여, 게임의 시각적 요소를 세밀하게 제어한다.
쿼터니언과 벡터의 곱셈
쿼터니언을 활용하면 벡터를 회전할 수도 있다.
(여기서 벡터는 Vector3 할 때의 그 벡터다.)
Unity에서 쿼터니언과 벡터의 곱셈을 지원한다. 하지만 반드시 Q * V 의 순서로 곱해야 한다.
부채꼴 화살 코드
// 중간부터 펼쳐지는게 아니라 minangle부터 커지면서 쏘는 것으로 설계했어요!
float minAngle = -(numberOfProjectilesPerShot / 2f) * projectilesAngleSpace + 0.5f
* RangedAttackSO.multipleProjectilesAngle;
for (int i = 0; i < numberOfProjectilesPerShot; i++)
{
float angle = minAngle + projectilesAngleSpace * i;
// 화살 간격을 각각 다르게 하기 위해 randomSpread를 넣었어요!
float randomSpread = Random.Range(-RangedAttackSO.spread, RangedAttackSO.spread);
angle += randomSpread;
CreateProjectile();
}
강의를 듣던 중 이런 코드가 있었는데 이해가 안되어서 송지원 튜터님께 찾아갔었다.
위의 minangle 식에서
-(numberOfProjectilesPerShot / 2f) * projectilesAngleSpace 는 중앙으로부터 내려가야 하는 각도,
0.5f * RangedAttackSO.multipleProjectilesAngle 는 대칭을 맞춰주는 보정 수치이다.
만약 뒤의 보정치가 없다면 위 아래 대칭이 안맞는 상태로 내가 바라보는 방향 기준 한 쪽으로만 발사체가 퍼져나갈 것이다.
또, 그 아래에는 랜덤 간격에 관한 함수가 있었는데 그 랜덤값이 발사체 a~e까지가 있다 했을 때 그 각각의 간격을 의미하는지 아니면 통째로 묶어 전체의 간격이 다같이 변하는 건지도 물어봤는데, for문 안에 있으므로 a 와 b 간격, b와 c 간격 등등이 모두 다르다고 하셨다.
사실 코드만 보면 답해주신 것 자체는 예상이 되었는데 일반적인 게임으로 생각했을 때는 그러는 경우를 못봐서 굳이 랜덤 요소를 왜 넣은건지 이해가 안되었었다. 강의하신 튜터님 본인도 그냥 이 내용을 뺄까 하다가 코드의 다양성 부문에서 알아두면 다른 어디에서나 쓸 수 있기에 그냥 넣으셨다고 했다.
System.Random 과 UnityEngine.Random, Unity.Mathematics.Random
이 랜덤 종류들의 차이는 사실 우리 수준에서 구별하여 사용할 일은 거의 없다고 하셔서 간단하게만 정리해두고 실사용하는건 Unity 환경 기준 거의 UnityEngine.Random이라고 한다.
#System.Random
- .NET 프레임워크의 일부로, Unity에서도 using문만 작성하면 사용 가능하다.
- 게임 개발 외의 일반적인 C# 프로그래밍에서 주로 사용된다.
- 여러 타입의 랜덤 데이터 생성이 가능하며, 시드값을 설정하여 랜덤 시퀀스를 재현할 수 있다.
이 말은 즉, 동일한 시드값은 동일한 순서의 난수를 생성한다는 뜻이다. 이것으로 게임의 예측 가능성을 제어할 수 있다.
#UnityEngine.Random
- Unity 엔진 내부에 내장된 랜덤함수
- 게임 오브젝트와 상호작용하는 데 최적화되어 있으며, 사용하기 쉽다.
- 랜덤 수, 벡터, 색상을 생성할 수 있고 특정 시드를 통해 일관된 랜덤결과를 생성하는 것도 가능하다.
#Unity.Mathematics.Random
- 유니티에서 성능을 최적화하고, 멀티스레드 환경에서 안전하게 사용될 수 있도록 만들어졌다.
- 시스템적인 접근과 최적화가 필요한 상황에서 사용된다.
오브젝트 풀 구현
오브젝트 풀링
빈번하게 생성되는 오브젝트들을 풀에 저장해놓고 재사용함으로써 메모리 할당과 가비지 컬렉션에 따른 성능 저하를 방지할 수 있는 기능이다.
적절히 사용하면 큰 성능개선을 가져올 수 있지만, 불필요한 메모리 사용을 증가시킬 수 있으므로 주의해야 한다.
마무리
이 이후의 강의는 듣기만 하고 TIL로 정리를 하지는 않았다. 우선 눈과 귀로만 빠르게 내용을 숙지하고, 개인 프로젝트를 먼저 완료하고 와서 다시 집중해서 한 번 더 들을 예정이다.
'내일배움캠프 > Unity강의 게임개발입문' 카테고리의 다른 글
[TIL 24.05.14] Unity 게임 개발 입문 강의록(3) (0) | 2024.05.14 |
---|---|
[TIL 24.05.08] Unity 게임 개발 입문 강의록(1) (0) | 2024.05.08 |