오늘 학습 키워드
The Stack 클론 코딩, TopDown 클론 코딩
오늘 학습 한 내용을 나만의 언어로 정리하기
The Stack
프로젝트 세팅
카메라
- Perspective : 원근감을 표현하는 3D 카메라
라이트
- Directional Light : 화면에 전역적으로 비춰지는 빛
블록 적층 로직
Lerp
- “Linear Interpolation”의 약자. 선형 보간이라는 뜻
- Unity에서 주로 사용되는 Mathf.Lerp, Vector3.Lerp는 시작 값과 끝 값 사이의 값을 t 비율 (0~1) 로 계산해 반환함
- 기본 공식 : Lerp(a, b, t) = a + (b - a) * t
색
- 색을 코드에서 바꿀 때에는 0~1사이의 값을 사용하기 때문에, 원하는 색을 RGB코드로 바로 넣으면 안되고 다음과 같이 넣어야 함
// 255로 나눠줘야함
Color color = new Color(250f / 255f, 100f / 255f, 48f/ 255f)
- 색은 마테리얼이 담당함.
블록 이동, 배치 로직
핑퐁
- Mathf.PingPong(t, length) : 0부터 지정해 준 사이즈까지 순환
void MoveBlock()
{
blockTransition += Time.deltaTime * BlockMovingSpeed;
float movePosition = Mathf.PingPong(blockTransition, BoundSize) - BoundSize / 2;
// 중심을 기준으로 전체 BoundSize만큼 왔다 갔다 할 수 있는 크기
}
- 핑퐁 함수가 이해가 잘 안가서 챗지피티한테 시간별 분석 시킴… 움직임의 중심축은 0으로 두면서도 진동효과를 주는 방법이라고 함
- 믿지마셈
- 튜터님 피셜 : 아래 그래프가 맞다
파편 만들기
- 기존의 있는 블록을 쪼개는게 아니고, 새로운 블록을 만들어서 눈속임
void CreateRubble(Vector3 pos, Vector3 scale)
{
GameObject go = Instantiate(lastBlock.gameObject);
go.transform.parent = this.transform;
go.transform.localPosition = pos;
go.transform.localScale = scale;
go.transform.localRotation = Quaternion.identity;
go.AddComponent<Rigidbody>(); // 중력 영향 받아서 떨어질 수 있도록
go.name = "Rubble";
}
CreateRubble(
new Vector3(
isNegativeNum
? lastPosition.x + stackBounds.x / 2 + rubbleHalfScale // 마지막 블록의 중심점 + 생성될 블록 중심점 이동
: lastPosition.x - stackBounds.x / 2 - rubbleHalfScale,
lastPosition.y,
lastPosition.z),
new Vector3(deltaX, 1, stackBounds.y));
점수와 콤보
- PlayerPrefs로 저장
연출
게임 오버 시 연출
void GameOverEffect()
{
int childCount = this.transform.childCount; // 하위 오브젝트 개수 (블럭, 러블들)
for(int i = 1; i < 20; i++)
{
if (childCount < i) break;
GameObject go = transform.GetChild(childCount - i).gameObject; // childCount에서 i를 빼는 이유는, 뒤에서부터 순환하려고
if (go.name.Equals("Rubble")) continue;
Rigidbody rigid = go.AddComponent<Rigidbody>();
// 힘 줘서 날려버리기
rigid.AddForce(
(Vector3.up * Random.Range(0, 10f) + Vector3.right * (Random.Range(0, 10f) - 5f)) * 100f);
}
}
파티클 시스템
-
파티클 시스템 : VFX를 구현하는데 사용되는 도구.
-
Start LifeTime : 파티클 하나 하나의 생존 시간 설정
-
Start Speed : 파티클 이동속도 설정
-
Start Size : 파티클 크기 설정
-
Shape : 파티클이 발사되는 모양
포스트 프로세싱
-
포스트 프로세싱 : 게임 렌더링이 완료된 화면에 추가적으로 그래픽 효과를 적용함. 렌더링 파이프라인 마지막 단계에서 이루어짐.
-
사용한 방법
- 빈 오브젝트에 PostProcessVolume 컴포넌트를 붙이고, Add Effect로 원하는 이펙트를 설정
- PostProcess 레이어를 생성해서, 1에서 생성한 오브젝트에 설정해줌
- 메인 카메라로 가서, PostProcessLayer 컴포넌트를 붙이고, Layer를 PostProcess로 설정하면 끝
-
주요 기능
- 블룸
- 색 보정
- 초점 효과
- 모션 블러
- 환경 광 차폐
- 비네트
- 색수차
- 렌즈 왜곡
-
장점
- 시각적 품질 향상
- 감정, 분위기 전달
- 유연성
-
단점/주의점
- 성능 문제
- 과도한 사용 주의
- 효과의 우선순위
TopDown
스프라이트 관리 + 플레이어 이동 구현
스프라이트
- PPU 16으로 한 이유 : 에셋이 하나당 16 * 16이라서 16으로 하면 딱 1 unit에 에셋 하나가 알맞게 들어감
플레이어
- [SerializedField] 를 하면, private여도 유니티 인스펙터 창에서 수정 가능함
- Mathf.Atan2(y, x) : y랑 x 주면 그 사이 각을 구해냄. 그 값은 라디안으로 줌. Degree로 바꿔주는게 편함
- 두 벡터를 빼는 이유 :
// 넉백 구현부분
public void ApplyKnockback(Transform other, float power, float duration)
{
knockbackDuration = duration;
knockback = -(other.position - transform.position).normalized * power;
}
// (other.position - transform.position) : transform이 other를 보는 방향
// -(other.position - transform.position) : 넉백은 보는 방향의 반대로 적용해야 함
// ... normalized : 벡터를 방향은 유지하되, 크기가 1인 단위 벡터로 변환함
// ... * power : 단위벡터 * 밀려나는 힘
Fixed Delta Time과 Delta Time의 차이 Fixed Update와 Update 간의 관계
-
정리 :
- Fixed Delta Time은 Fixed Update 내에서 사용됨.
- Fixed Update 에서는 일반 Delta Time에 접근이 불가능하지만, Update 에서는 Fixed Delta Time에 접근이 가능함.
- 따라서, 그냥 DeltaTime으로 쓰는게 안전하다. (Fixed Update에서 deltaTime = fixedDeltaTime)
-
입력 처리 : Edit > Project Settings > Input Manager > Axes 에서 설정 가능
충돌 처리 및 맵 구성
타일맵
- 타일맵 : 격자 기반 맵을 생성하고 관리할 수 있는 기능. 타일이라는 작은 사각형 조각들을 사용해 게임 맵을 효율적으로 구성할 수 있음
- 주요 구성 요소
- 타일 : 개별 타일 맵을 구성하는 가장 작은 단위
- 타일맵 : 여러 타일이 배치된 2D 격자
- 그리드 : 타일맵을 배치하는 기반 격자 구조
애니메이션 처리
- 문자열 직접 비교보다 숫자 비교가 나음
private static readonly int IsMoving = Animator.StringToHash("IsMove");
private static readonly int IsDamage = Animator.StringToHash("IsDamage");
animator.SetBool(IsDamage, true); // 이런식으로 쓸 수 있음
스탯
// 최소 1에서 100까지 설정 할 수 있다는 의미
[Range(1, 100)][SerializeField] private int health = 10;
원거리 공격
- Animator의 Parameter에서 Trigger는 한 번 켜졌다 알아서 꺼지는 역할임
public override void Attack()
{
base.Attack();
float projectileAngleSpace = multipleProjectilesAngle; // 탄 퍼짐 각도
int numberOfProjectilePerShot = numberOfProjectilesPerShot; // 탄환의 개수
float minAngle = -(numberOfProjectilePerShot / 2f) * projectileAngleSpace; // 최소
for (int i = 0; i < numberOfProjectilesPerShot; i++)
{
float angle = minAngle + projectileAngleSpace * i;
float randomSpread = Random.Range(-spread, spread);
angle += randomSpread;
CreatProjectile(Controller.LookDirection, angle);
}
}
잊지 말자
- PlayerPrefs는 보안 수준이 높지 않다. 비밀번호 같은거 저장하지 마셈
- GetComponentInChildren<>()의 매개변수로, 꺼져있는 오브젝트도 넣을지 말지 하는 bool 값을 넣을 수 있다.
- transform 안에 있는 Find 함수는 경로로 오브젝트를 찾는다.
- Quaternion * vector 는 되지만, 그 반대는 안된다. 교환법칙 성립 안함!
내일 학습 할 것은 무엇인지
내일은 진짜 강의 끝낸다…