목차
※ Editor 새로 설치 (2022.3.57f1)
>> 강사님의 자그마한 조언
- Unity 6도 조금씩 써봐야 한다.
- 점차 URP 방식으로 바뀔 것이기 때문에 Bulit-In 방식도 나중에는 안 쓰이게 될 것이다.
※ 유니티를 켤 때 화면 윗 부분에 검은색 줄이 생기는 고질적인 버그 해결 방법
: 작업 관리자를 열어서 Unity를 전부 종료하고 다시 켜면 해결
※ Scene 전환 및 관리에 도움이 되는 레딧 글 (다른 수강생분의 팁 공유)
https://www.reddit.com/r/Unity3D/s/FThM1Mjfl6
From the Unity3D community on Reddit: How do you navigate scenes?
Explore this post and more from the Unity3D community
www.reddit.com
2D 게임 만들기
25.02.11
Animation
1. 강사님이 공유해주신 Sprite들 추가 및 설정
--> altas는 여러 Image가 있기 때문에 Sprite Mode를 Multiple로 설정
2. Sprite Editor
>> Slice
>> Idle Animation으로 활용하기 위해 머리를 한 칸 낮춘 Image기 때문에 Position Y를 1 높여줌
3. Animation 자동 생성
--> character-atlas_1 ~ 3 을 묶어서 walk animation도 추가
4. Animator 설정
--> walk -> idle은 less 0.01으로 설정
5. 움직일 때와 멈출 때 Animation이 바로 적용되지 않고 밀리는 현상 수정
- Has Exit Time : 조건상 전환해야 하지만, 남은 시간만큼 Animation을 재생하고 넘기도록 설정해주는 것 --> 체크 해제
- Transition Duration : 서서히 전환되도록 전환에 걸리는 시간을 설정해주는 것 --> 0으로 설정
--> walk -> idle도 마찬가지로 설정
Script
>> PlayerController.cs 생성
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(SpriteRenderer))]
[RequireComponent(typeof(Animator))]
public class PlayerController : MonoBehaviour
{
// string 타입에서 오타가 발생하면 찾기 어렵기 때문에
private static readonly int Speed = Animator.StringToHash("Speed");
public float moveSpeed = 5f; // 이동 속도를 조정할 수 있는 변수
private SpriteRenderer _spriteRenderer;
private Animator _animator;
private void Awake()
{
_spriteRenderer = GetComponent<SpriteRenderer>();
_animator = GetComponent<Animator>();
}
private void Update()
{
// WASD 입력값 가져오기
float horizontal = Input.GetAxis("Horizontal"); // A, D 또는 화살표 좌우
float vertical = Input.GetAxis("Vertical"); // W, S 또는 화살표 위/아래
// 이동 방향 계산
Vector3 moveDirection = new Vector3(horizontal, vertical, 0f);
// 대각선 이동 속도 균등화
moveDirection = moveDirection.normalized;
// 캐릭터 이동
transform.Translate(moveDirection * (moveSpeed * Time.deltaTime), Space.World);
// Sprite 방향 처리
if (horizontal < 0)
{
// 왼쪽으로 이동 중
_spriteRenderer.flipX = true;
}
else if (horizontal > 0)
{
// 오른쪽으로 이동 중
_spriteRenderer.flipX = false;
}
// Animator에 이동 속도를 전달
_animator.SetFloat(Speed, moveDirection.magnitude);
}
}
>> Hierarchy에 배치한 Sprite에 추가
자연스러운 카메라 이동
: 코드로 작성하는 방법과 Cinemachine을 사용하는 방법이 있다. --> 지금은 Cinemachine을 사용함
1. CameraController.cs 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
public Transform target; // 따라갈 대상, 보통 Player의 Transform
public float smoothSpeed = 0.125f; // 카메라의 부드러운 이동 속도
private void LateUpdate()
{
if (!target) return; // 대상이 없을 경우 아무것도 하지 않음
// 목표 위치 계산
Vector3 desiredPosition = new Vector3(target.position.x, target.position.y, transform.position.z);
// 부드러운 카메라 이동 (Lerp 사용)
Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
// 카메라 위치 업데이트
transform.position = smoothedPosition;
}
}
>> MainCamera에 추가 및 바인딩
--> 테스트만 하고 다시 삭제함
2. Cinemachine을 활용
>> Hierarchy에 추가
>> Follow에 바인딩
: 따라다닐 요소 추가
※ Game Scene에서 보이는 카메라 범위 설정
Tilemap
>> Ground
>> 추가 및 설정
>> Sprite Editor - Slice
>> Tilemap 생성
>> Palette 열기
>> Create New Palette
--> 이름 : New Palette
>> 생성한 Palette에 'Ground' 추가
>> Scene에 그리기
>> Wall
>> 추가 및 설정
>> Sprite Editor - Slice
>> 팔레트에 Wall 추가
>> Tilemap을 더 추가하면 Tile을 중첩하여 그릴 수 있음
: Order in Layer를 설정해서 위에 나오게 설정
>> Layer 설정
: Layer 순서가 더 위에 있으면 아래에 깔린다
--> 'character-atlas_0'과 'Tilemap', 'Tilemap (1)'에 각각 Sorting Layer 설정
>> Collider
: 캐릭터가 벽을 뚫고 가지 않도록
1. 캐릭터에 Capsule Collider 2D, Rigidbody 2D를 추가
--> 중력의 영향을 받지 않도록 Gravity Scale을 0으로 설정
--> 충돌 시, 넘어지듯 회전하지 않도록 Freeze Rotation Z 체크
2. 벽에 Tilemap Collider 2D, Composite Collider 2D를 추가 (Rigidbody 2D는 자동으로 붙는다)
: Composite Collider 2D를 추가하면 타일별로 각각 분리되있던 Collider를 하나로 합칠 수 있음
--> Tilemap Collider 2D의 Used By Composite 체크
--> Rigidbody 2D의 Body Type을 Static으로 설정하여 중력에 의해 떨어지지 않도록 만듦
3. Tilemap의 Collider를 좀 더 자세하게 설정
1. Wall의 Sprite Editor - Custom Physics Shape
2. 수정하고자 하는 타일을 누르고 Generate를 눌러 Collider 수정
※ 예시
--> 필요없는 Point는 'Delete'를 눌러서 삭제
--> 전부 설정한 다음 Apply
버그 현상
>> 캐릭터를 벽에 비비면 진동하는 현상
: 지금 채택한 이동 방식은 Rigidbody를 이용한 충돌을 고려한 이동이 아닌 강제로 캐릭터의 위치를 업데이트 하는 방식을 쓰고 있기 때문에, 캐릭터가 해당 위치로 순간이동 하고 Collider에 의해 다시 밖으로 나오는 과정이 Update문에서 빠르게 반복되고 있기 때문
퀴즈 게임 만들기
Quiz Game Project
- Unity 버전 : 2022.3.57f1
- 템플릿 : 2D (Built-In Render Pipeline) --> 이번 Project에는 따로 URP를 사용할 일이 없기 때문
- Connect to Unity Cloud 체크 해제
- 이름 : quiz-game
※ 참고사항
- 전체적으로 UI를 다루기 때문에 UI를 심도있게 살펴보자
- 플랫폼이 모바일이기 때문에 광고로 수익을 얻는 것에 목적이 있다. --> 우선 이 게임을 광고해야한다.
그래픽 리소스 추가
: 공유해주신 퀴즈 리소스는 회사 자산이므로 Git을 Private로 설정
└ 준비하기
Google Play Console (선택)
: 개발자를 위한 콘솔 --> 유료 (있으면 좋고 없으면 그냥 보기)
https://developer.android.com/distribute/console?hl=ko
Google Play Console | Android Developers
Google Play Console로 앱과 게임을 게시하고 Google Play에서 비즈니스를 성장시키세요. 앱 품질 개선, 잠재고객 참여 유도, 수익 창출 등에 도움이 되는 기능을 활용할 수 있습니다.
developer.android.com
AdMob
: 인앱 광고 넣기 --> 무료인데, credit card는 등록해야함
https://admob.google.com/intl/ko/home/
Google AdMob: 모바일 앱 수익 창출
인앱 광고를 사용하여 모바일 앱에서 더 많은 수익을 창출하고, 사용이 간편한 도구를 통해 유용한 분석 정보를 얻고 앱을 성장시켜 보세요.
admob.google.com
--> 가입하자
※ IOS
1. 앱스토어에서 xcode 설치
2. Account 추가 --> developer.apple.com 에서 개발자 아이디 생성
Package Manager -> My Assets -> DOTween 설치
: 없으면 Asset Store에서 추가 --> Free 버전
Build Settings
: Android로 Switch Platform
└ Github 연결 (Clone X)
>> repository 생성
- 이름 : quiz-game
- README 생성 X
- Ignore : None
>> gitignore 직접 생성
: gitignore.io
https://www.toptal.com/developers/gitignore
gitignore.io
Create useful .gitignore files for your project
www.toptal.com
--> unity, rider 추가 및 생성, 이후 나온 사이트 전체 선택 및 복사
>> '.gitignore' 생성 후 복사한 것 붙여넣기
--> 파일 이름을 정확히 '.gitignore'로 생성
>> Git Bash
1. 프로젝트를 만든 폴더로 가서 우클릭하여 Git Bash 실행
2. 명령어 입력 --> Github에 나오는 Quick setup을 그대로 진행 (README.md 파일을 안 만들어야 Quick setup이 나옴)
: README.md 는 생략해도 됨
- git init
- git add .
- git commit -m "first commit"
- git branch -M main
- git remote add origin (Github Repository 주소) --> Git Bash의 붙여넣기는 Shift + Insert
- git push -u origin main
※ Rider에서도 Github에 연결 및 관리가 가능하다.
└ 게임 구조 설계
- SinglePlay로 만들 예정
- Title : 팝업 화면 처리
- Game : 게임 카드 처리, 파일 읽기
- Quiz File : csv파일, 텍스트와 쉼표(,)
- 공통 : 설정창, GPGS, 광고
※ 공통
- Google Play Game Service(GPGS) --> 업적, 리더보드(랭킹), 로그인(업적과 랭킹을 위한 로그인)
- 광고 --> Unity (Iron Source), AdMob (Mediation : 다른 플랫폼의 광고를 가져와서 사용 가능)
>> 구조에 맞춰 Script 생성
: 생성만 했고, 내용은 작성하지 않음
- GameManager.cs
- AdmobAdsManager.cs
- CSVFileManager.cs
- CardController.cs
- Card.cs
- SettingsPanelController.cs
- ShopPanelController.cs
- StagePanelController.cs
C# 단기 교육 보강
6일차
Monster Wave
※ Unity Asset Store에서 무료 에셋 추가
https://assetstore.unity.com/packages/3d/props/props-3d-221035
Props 3D | 3D 소품 | Unity Asset Store
Elevate your workflow with the Props 3D asset from Sigmoid Button Assets. Find this & other 소품 options on the Unity Asset Store.
assetstore.unity.com
>> 버그 수정
1. Turret이 Target을 보고 총알을 쏠 때, 총알도 그 방향대로 회전되어 나가야하는데, 그대로 나가는 버그
: Turret.cs에서 Bullet을 생성할 때, 회전값 조정
private void CreateBullet()
{
GameObject bulletObj = Instantiate(bulletPrefab, shootTransform.position, shootTransform.rotation);
bulletObj.GetComponent<Rigidbody>().AddForce(shootTransform.forward * 50f, ForceMode.Impulse);
}
2. 중력 때문에 Bullet의 낙차가 발생
: Bullet Prefab의 Rigidbody에서 Use Gravity 체크 해제
※ 정말 빠르게 지나가면 Collider Event가 감지를 못하는 문제가 발생한다.
>> 여러 해결 방법
1. 낙차가 있으면 닿는 면적이 줄기 때문에 낙차 삭제 --> Gravity 끄기
2. Collider 자체의 크기를 키우기
3. Project Settings - Time - Fixed Timestep의 값을 줄이기
--> 물리와 관련된 FixedUpdate나 Event의 Check 주기를 줄여준다. (너무 낮추면 PC에 무리가 가므로 주의)
3. Monster가 죽고 나서도 움직이는 버그
: Monster.cs의 Hit 함수에서 Invoke 때문에 발생
--> hit Animation을 재생하고 0.5초 뒤에 다시 이동하는데, 그 사이에 더 맞아서 dead 상태가 된다면 죽은 상태로 이동하게 되는 것
>> 공격 받았을 때, Invoke가 실행 중이라면 Invoke를 취소하는 기능 추가 --> CancelInvoke("함수명")
protected virtual void Hit(float damage)
{
CancelInvoke("DelayMove");
hp -= damage;
isMove = false;
if (hp <= 0)
{
_anim.SetTrigger("dead");
this.GetComponent<Collider>().enabled = false;
_turret.SetTarget(this.transform); // Monster가 죽었을 때, 새로 Target 설정
Destroy(gameObject, 5f);
}
else
{
_anim.SetTrigger("hit");
Invoke("DelayMove", 0.5f); // Invoke("함수명", 시간) : 지연 호출 함수
}
}
>> Target 관련하여 Script 수정
└ Interface를 활용하여 Item 구현
>> IMove.cs 생성
>> IItem.cs, ItemManager.cs 생성 및 Monster.cs 수정
: Monster가 죽었을 때 Item을 랜덤으로 생성하도록
--> 각 Item의 Script도 생성
>> 다운 받은 에셋에서 마음에 드는 Item을 3개 골라 맵에 잘 보이게 임의로 배치
>> 각 Item에 Script 추가
: RequireComponent로 Rigidbody 자동 생성
※ Mesh Collider와 Rigidbody를 같이 사용하면 부하가 심해서 에러가 발생한다.
: Convex로 Collider를 최적화해야 된다. --> Mesh Collider의 Convex를 체크
--> Item 셋 다 체크
>> Item들의 기존 Prefab을 해제한 후, 개인 Prefab화
: 일반적으로 Asset으로 받은 리소스는 크기가 크기 때문에 쓰는 리소스만 복사해서 쓰고 나머지는 정리하면 된다.
--> 이후 Hierarchy에서 Item들 삭제
>> 빈 게임 오브젝트로 ItemManager 생성 후, ItemManager.cs 추가 및 바인딩
--> Transform Reset
>> Spawn 되는 Item이 랜덤한 방향과 회전으로 나오도록 코드 수정
>> 떨어진 Item을 클릭하여 줍도록 코드 수정
※ 프로퍼티 (Property)
- 캡슐화 : 외부로부터 데이터 접근 및 수정을 보호하는 방법
'Development > C#' 카테고리의 다른 글
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 54일차 (0) | 2025.02.13 |
---|---|
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 53일차 (0) | 2025.02.12 |
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 51일차 (0) | 2025.02.10 |
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 50일차 (0) | 2025.02.07 |
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 49일차 (0) | 2025.02.06 |