티스토리 뷰
오늘은 게임 하나를 완성했다 수업에서 완전히 만들지 않고 과제로 더 발전시켜서 완성시키는 거였다 어제는 유니티를 만지는게 어려웠는데 나름 하루만에 익숙해진 것 같다 ㅎ
💻 Unity
Collider
게임 오브젝트의 물리적 경계를 정의하는 컴포넌트. 충돌 감지와 물리 상호작용의 핵심 요소로 RigidBody와 함께 사용하면 물리 엔진의 영향을 받는다.
Collider 설정과 속성 ⚙️
- Is Trigger: 체크하면 물리적 충돌 없이 충돌 감지만 수행 (한쪽만 Trigger 충돌이 돼있어도 됨)
- Material: 물리적 속성(마찰, 탄성)을 정의하는 Physics Material
- Size/Radius: 콜라이더의 크기 조절
- Center: 콜라이더의 **OnCollisionEnter2D() vs OnTriggerEnter2D()**중심점 조절
충돌 규칙
- 충돌 감지를 위해선 적어도 하나의 Rigidbody가 필요함.
- 둘 다 isTrigger=false면, OnCollisionEnter2D()를 사용해야 함.
- OnTriggerEnter2D()를 사용하려면, 적어도 하나의 Collider2D가 isTrigger=true여야 함.
활용 사례 💡
- 물리 충돌: 캐릭터가 벽과 충돌해 멈추는 등의 물리 반응
- 아이템 획득: 트리거를 사용해 플레이어가 아이템을 획득
- 영역 감지: 특정 구역 진입/이탈 감지 (세이프존, 데미지존 등)
- 레이캐스팅: 콜라이더 대상으로 광선 투사로 물체 감지
- 센서: 적 감지, 시야 범위 구현 등
충돌 감지 이벤트
- 일반 충돌 이벤트 (IsTrigger 활성화)
// 충돌이 시작될 때
void OnCollisionEnter(Collision collision)
{
Debug.Log("충돌 시작: " + collision.gameObject.name);
}
// 충돌 중일 때 (매 프레임)
void OnCollisionStay(Collision collision)
{
Debug.Log("충돌 중");
}
// 충돌이 끝날 때
void OnCollisionExit(Collision collision)
{
Debug.Log("충돌 종료");
}
- 트리거 이벤트 (IsTrigger 비활성화)
// 트리거 영역 진입 시
void OnTriggerEnter(Collider other)
{
Debug.Log("트리거 진입: " + other.gameObject.name);
}
// 트리거 영역 내에 있을 때 (매 프레임)
void OnTriggerStay(Collider other)
{
Debug.Log("트리거 영역 내 체류 중");
}
// 트리거 영역 이탈 시
void OnTriggerExit(Collider other)
{
Debug.Log("트리거 이탈");
}
OnCollisionEnter2D() vs OnTriggerEnter2D()
특성 | OnCollisionEnter2D | OnTriggerEnter2D |
콜라이더 설정 | IsTrigger = false | IsTrigger = true |
물리적 충돌 | ✅ 있음 (반발, 밀림) | ❌ 없음 (통과) |
물리력 정보 | Collision2D 객체 제공 | 제공하지 않음 |
성능 영향 | 물리 계산 필요 | 단순 감지만 수행 |
Prefab
재사용 가능한 게임 오브젝트로 한 번 만들고 여러 번 사용할 수 있다. 프로젝트 창에서 파란색 큐브 아이콘으로 표시된다.
Prefab 사용 방법
- 게임 오브젝트를 씬에 만들고 필요한 컴포넌트 추가
- 하이어라키에서 프로젝트 창으로 드래그
활용 사례 💡
- 적 캐릭터: 동일한 적을 여러 위치에 배치
- 총알/발사체: 반복적으로 생성되는 게임 요소
- 환경 요소: 나무, 바위, 건물 등 레벨 디자인 요소
- UI 요소: 버튼, 패널 등 동일한 스타일의 UI
- 파티클 효과: 폭발, 연기 등의 특수 효과
Prefab 인스턴스 생성
// 인스펙터에서 할당할 변수
public GameObject enemyPrefab;
// 런타임에 프리팹 생성
void SpawnEnemy(Vector3 position)
{
Instantiate(enemyPrefab, position, Quaternion.identity);
}
Coroutine
시간이 걸리는 작업을 처리하기 위한 함수. 일반 함수와 달리 실행을 일시중지 했다가 나주에 재개할 수 있다
void Start()
{
StartCoroutine(MyCoroutine());
}
IEnumerator MyCoroutine()
{
Debug.Log("시작!");
yield return new WaitForSeconds(2f); // 2초 대기
Debug.Log("완료!");
}
// 코루틴 중지하기
void StopMyCoroutine()
{
StopCoroutine(MyCoroutine());
// StopAllCoroutines(); // 모든 코루틴 중지
}
활용 사례 💡
- 캐릭터 애니메이션 시퀀스
- 시간 기반 이벤트와 타이머
- UI 페이드 인/아웃 효과
- 점진적인 값 변경 (부드러운 움직임)
- 게임 데이터 로딩
특징 | 코루틴 | 일반 함수 |
반환 타입 | IEnumerator | void, int 등 |
실행 방식 | 중간에 일시정지 가능 | 한 번에 모두 실행 |
호출 방법 | StartCoroutine() | 직접 호출 |
시간 지연 | yield 문으로 가능 | 불가능 (UI 차단) |
🕹️ 게임 실습
DragonFlight
Player
- Player 태그
- Circle Colider 2D 추가 후 충돌 범위 설정
- Rigidbody 2D 중력 줄 필요 X > Gravity Scale 0
public float moveSpeed = 5.0f;
void FixedUpdate()
{
moveControl();
}
void moveControl()
{
float distanceX = Input.GetAxis("Horizontal") * moveSpeed * Time.deltaTime;
transform.Translate(distanceX, 0, 0);
}
Wall
- Box Colider 2D 추가
Enemy
- Circle Colider 2D 추가 후 IsTrigger 체크 > player와 부딪혀도 그냥 지나가게 함 (충돌 감지만 트리거만 수행하고 물리적 충돌을 일으키지 않음)
- Project에 드래그해 Prefab으로 만듦
- Enemy 태그
public float moveSpeed = 2.0f;
void Update()
{
float distanceY = moveSpeed * Time.deltaTime;
transform.Translate(0, -distanceY, 0);
}
private void OnBecameInvisible() // 카메라에서 보이지 않으면 호출
{
Destroy(gameObject); // 오브젝트 삭제
}
Bullet
- Order in layer 1로 설정
- Box Collider 2D 추가 후 IsTrigger 체크
- Rigidbody 추가 후 Gravity Scale 0
public float moveSpeed = 1.8f;
public GameObject explosion; // Explosion B 연결
void Update()
{
transform.Translate(0, moveSpeed * Time.deltaTime, 0);
}
private void OnBecameInvisible()
{
Destroy(gameObject);
}
private void OnTriggerEnter2D(Collider2D collision) // 충돌 트리거
{
if (collision.gameObject.CompareTag("Enemy"))
{
// 폭발 이펙트 생성
Instantiate(explosion, transform.position, Quaternion.identity);
SoundManager.Instance.PlayDieSound();
// 적과 자신 지우기
Destroy(collision.gameObject);
Destroy(gameObject);
GameManager.Instance.AddScore(10);
}
}
Launcher
- Player 하위에 Empty Object 생성
public GameObject bullet; // bullet 연결
void Start()
{
// InvokeRepeating(함수 이름, 초기 지연시간, 지연할 시간)
InvokeRepeating("Shoot", 0.5f, 0.5f);
}
void Shoot()
{
// 미사일 프리팹, 런처 포지션, 방향값 안줌
Instantiate(bullet, transform.position, Quaternion.identity);
SoundManager.Instance.PlayBulletSound();
}
SpawnManager
- Empty Object 생성
public GameObject enemy; // samll_enemy 연결
void Start()
{
InvokeRepeating("SpawnEnemy", 1.0f, 0.5f);
}
void SpawnEnemy()
{
float randomX = Random.Range(-2f, 2f);
Instantiate(enemy, new Vector3(randomX, transform.position.y, 0f), Quaternion.identity);
}
SoundManager
- Audio Source 추가
public static SoundManager Instance { get; set; }
AudioSource myAudio; // AudioSource 컴포넌트
public AudioClip BulletSound; // se_attack 연결
public AudioClip DieSound; // baby_dragon_die 연결
private void Awake()
{
if (SoundManager.Instance == null)
{
SoundManager.Instance = this;
}
}
void Start()
{
myAudio = GetComponent<AudioSource>();
}
public void PlayBulletSound()
{
myAudio.PlayOneShot(BulletSound);
}
public void PlayDieSound()
{
myAudio.PlayOneShot(DieSound);
}
UI / GameManager
- UI > Legacy > Text 오브젝트 추가
- GameManager 오브젝트 추가
public static GameManager Instance { get; set; }
public Text scoreText;
public int Score { get; set; }
private void Awake()
{
if (GameManager.Instance == null)
{
GameManager.Instance = this;
}
}
public void AddScore(int num)
{
Score += num;
scoreText.text = $"Score : {Score}";
}
💫 Tip!
Anchor Presets

Alt 누르면 붙일 수 있도록 변경됨
📝 과제
DragonFligh 완성
https://github.com/yh97yhyh/likelion-unity-study/tree/main/DragonFlight
'Unity > 멋쟁이사자처럼' 카테고리의 다른 글
멋쟁이 사자처럼 부트캠프 유니티 게임 개발 4기 15일차 회고 (0) | 2025.03.13 |
---|---|
멋쟁이 사자처럼 부트캠프 유니티 게임 개발 4기 14일차 회고 (0) | 2025.03.12 |
멋쟁이 사자처럼 부트캠프 유니티 게임 개발 4기 12일차 회고 (0) | 2025.03.11 |
멋쟁이 사자처럼 부트캠프 유니티 게임 개발 4기 11일차 회고 (0) | 2025.03.07 |
멋쟁이 사자처럼 부트캠프 유니티 게임 개발 4기 10일차 회고 (0) | 2025.03.07 |