no image
내일배움캠프 21일차 TIL [Unity 생명주기와 C# 알고리즘 핵심 복습]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 11:00 : GitHub 과제 업로드, 제출 및 README.md 정리🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 17:00 :Unity 학습 내용 복습 (라이프사이클, 코루틴, Instantiate 등)스파르타 메타버스 개인 과제 해설 영상 시청 및 정리✅ 저녁 전17:00 ~ 18:00 : 스파르타 코딩클럽 밍글데이 (미니게임 참여)🍽️ 저녁시간18:00 ~ 19:00 : 저녁시간✅ 저녁19:00 ~ 21:00 :C# 제너릭 싱글톤 패턴 학습주요 알고리즘 핵심 개념 정리(DP, Greedy, Divide and Conquer, Backtracking, Union-Find, Disjoint Set, DFS, BFS)팀원들과 회의 ..
2025.07.28
no image
Unity - Unity Instantiate() 오버로드 정리 & 자식으로 설정할 때의 차이
🧱 Unity Instantiate() 오버로드 정리 & 자식으로 설정할 때의 차이Unity에서 동적으로 오브젝트를 생성할 때 가장 많이 사용하는 함수는 Instantiate()다.하지만 부모를 지정하는 방식, 월드 좌표 유지 여부, 그리고 스케일/포지션의 차이까지 제대로 이해하지 않으면 예기치 못한 결과가 발생할 수 있다.이번 포스트에서는 Instantiate()의 다양한 오버로드 버전과, 다음과 같은 코드 두 개의 차이점을 중심으로 정리한다:🔍 예시private void FirstSpawn(){ Instantiate(obj, transform);}private void SecondSpawn(){ GameObject newObj = Instantiate(obj); newObj.tra..
2025.07.28
no image
Unity - Invoke() vs Coroutine 비교 정리 & InvokeRepeating()
⏰ Unity Invoke() vs Coroutine 비교 정리Unity에서 일정 시간 이후에 어떤 작업을 수행하려면 보통 Invoke()나 Coroutine을 사용한다.둘 다 **시간 지연(delay)**을 다룰 수 있지만, 구조와 활용도에는 큰 차이가 있다.이 글에서는 두 방법의 차이점, 장단점, 실제 사용 예시를 함께 정리한다.🔹 1. Invoke()란?Invoke()는 지정한 시간 후에 단 한 번 특정 함수를 호출하는 Unity 내장 함수다.✅ 사용법void Start(){ Invoke("DelayedFunc", 2f); // 2초 후 DelayedFunc 실행}void DelayedFunc(){ Debug.Log("2초 후 실행됨");}🔹 2. Coroutine이란?Coroutin..
2025.07.28
no image
Unity - Unity Coroutine(코루틴)
📌 Coroutine이란?**코루틴(Coroutine)**은 Unity에서 제공하는 특별한 함수로, 작업의 흐름을 중간에 일시정지하고, 조건이 충족되면 다시 이어서 실행할 수 있다.코루틴은 IEnumerator 반환형을 가지며, StartCoroutine() 함수를 통해 실행된다.IEnumerator ExampleCoroutine(){ Debug.Log("1초 대기 전"); yield return new WaitForSeconds(1f); Debug.Log("1초 대기 후");}StartCoroutine(ExampleCoroutine());⚙️ Coroutine 실행 흐름코루틴은 Update() 함수가 끝난 뒤 실행된다.즉, 모든 Update() 함수가 호출된 이후, 코루틴이 yield..
2025.07.28
no image
Unity - Unity MonoBehaviour 생명주기 (Lifecycle) 정리
🌀 Unity MonoBehaviour 생명주기 (Lifecycle) 정리Unity는 MonoBehaviour 기반의 스크립트를 일정한 순서로 호출하며, 게임 오브젝트의 생성부터 종료까지 다양한 이벤트 함수를 실행한다. 아래는 각 단계별로 정리한 생명주기 흐름이다. 🔹 1. 초기화 (Initialization)이벤트함수설명Awake()오브젝트가 인스턴스화된 직후 호출. 스크립트 간 참조 연결에 자주 사용. Start()보다 먼저 호출됨.OnEnable()오브젝트가 활성화될 때마다 호출. 컴포넌트가 켜지거나 오브젝트가 활성화되면 호출됨.Reset()에디터에서 컴포넌트를 추가할 때 자동 호출됨. 기본값 초기화 목적.Start()스크립트가 활성화된 상태일 때, 첫 번째 프레임 전에 단 한 번 호출됨. - ..
2025.07.28
no image
WIL - 본 캠프 4주차(25.07.21~07.25)
🌈 2025년 7월 넷째 주 WIL1. 이번 주 가장 인상 깊었던 배움은 무엇이었나요?이번 주는 Unity를 활용해 다양한 게임 장르와 기능을 직접 구현하면서,게임 구조 설계와 시스템 간 연동의 중요성을 체감한 한 주였다.가장 기억에 남는 배움은 다음과 같다:Flappy Bird 스타일 게임을 만들며점프 로직, 장애물 재배치, 반복 배경, 점수 시스템 등단순하지만 타이트한 게임 흐름 제어를 익혔다.The Stack 블록 쌓기 게임에서는타이밍 기반 블록 정렬, 오차 계산, UI 상태 전환 등의 로직을 구현하며반복 플레이에 중독성을 주는 디자인 요소를 경험했다.또 하나 인상 깊었던 것은,NPC와의 상호작용을 통한 메타버스 느낌의 미니게임 씬 전환 시스템을 만든 것이다.NPC와 대화하는 과정에서 F 키를 눌..
2025.07.27
no image
내일배움캠프 20일차 TIL [메타버스 게임]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:30 : EnemyManager 수정하드/이지 난이도에 따라 다른 적 프리팹이 생성되도록 구조 변경GameManager.CurrentDifficulty 값 사용 확인 및 디버깅 완료10:30 ~ 13:00 : 씬 전환 시 난이도 정보 유지 문제 해결EasyStartGame(), HardStartGame() 함수 점검씬 로드 후 난이도 정보가 사라지는 이슈 해결🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 15:30 : InteractionButton 기능 구현GameType(EasyGame, TheStackGame) 기반 분기NPC와 상호작용 시 F 키로 게임 시작 가능하게 처리한때 말풍선으로 힌트 출력 시도 → 결과적으로 사용 안..
2025.07.25
no image
Unity - Collider2D의 Layer Overrides(Include Layers, Exclude Layers) 알아보기
✍️ 본문최근 Unity에서 OnTriggerEnter2D가 도무지 작동하지 않아 시간을 꽤 허비했습니다.알고 보니 Collider2D의 "Layer Overrides" 설정이 원인이었습니다.이번 글에서는 이 기능이 무엇인지, 왜 문제가 생기는지, 어떻게 설정해야 하는지를 정리해봅니다.🧩 Layer Overrides란?Unity 2020.3부터 Collider2D에는 Layer Overrides 기능이 추가되었습니다.이는 기존의 Physics 2D → Layer Collision Matrix 설정을 무시하고,Collider 개별 객체 단위에서 충돌 대상을 지정할 수 있는 기능입니다.💡 간단히 말해, Collider 자신만의 충돌 필터를 설정할 수 있게 된 것이죠.⚙️ 구성 요소 설명항목설명Includ..
2025.07.25
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 11:00 : GitHub 과제 업로드, 제출 및 README.md 정리

🍽️ 점심시간

  • 13:00 ~ 14:00 : 점심시간

✅ 오후

  • 14:00 ~ 17:00 :
    • Unity 학습 내용 복습 (라이프사이클, 코루틴, Instantiate 등)
    • 스파르타 메타버스 개인 과제 해설 영상 시청 및 정리

✅ 저녁 전

  • 17:00 ~ 18:00 : 스파르타 코딩클럽 밍글데이 (미니게임 참여)

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁시간

✅ 저녁

  • 19:00 ~ 21:00 :
    • C# 제너릭 싱글톤 패턴 학습
    • 주요 알고리즘 핵심 개념 정리
    • (DP, Greedy, Divide and Conquer, Backtracking, Union-Find, Disjoint Set, DFS, BFS)
    • 팀원들과 회의 진행

✅ 오늘 학습 키워드

  • Unity MonoBehaviour 라이프사이클
  • Coroutine 동작 방식
  • Invoke vs Coroutine 비교
  • InvokeRepeating 개념 정리
  • Instantiate 오버로드 & 부모 설정 차이
  • C# 제너릭 싱글톤 패턴
  • 알고리즘 핵심 개념 정리
  • (DP, Greedy, Divide and Conquer, Backtracking, Union-Find, Disjoint Set, DFS, BFS)
  • 메타버스 개인 과제 해설 영상 리뷰

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

 

Unity - Unity MonoBehaviour 생명주기 (Lifecycle) 정리

🌀 Unity MonoBehaviour 생명주기 (Lifecycle) 정리Unity는 MonoBehaviour 기반의 스크립트를 일정한 순서로 호출하며, 게임 오브젝트의 생성부터 종료까지 다양한 이벤트 함수를 실행한다. 아래는 각 단계별

dev-jen.tistory.com

 

Unity - Unity Coroutine(코루틴)

📌 Coroutine이란?**코루틴(Coroutine)**은 Unity에서 제공하는 특별한 함수로, 작업의 흐름을 중간에 일시정지하고, 조건이 충족되면 다시 이어서 실행할 수 있다.코루틴은 IEnumerator 반환형을 가지며, S

dev-jen.tistory.com

 

Unity - Invoke() vs Coroutine 비교 정리 & InvokeRepeating()

⏰ Unity Invoke() vs Coroutine 비교 정리Unity에서 일정 시간 이후에 어떤 작업을 수행하려면 보통 Invoke()나 Coroutine을 사용한다.둘 다 **시간 지연(delay)**을 다룰 수 있지만, 구조와 활용도에는 큰 차이가

dev-jen.tistory.com

 

Unity - Unity Instantiate() 오버로드 정리 & 자식으로 설정할 때의 차이

🧱 Unity Instantiate() 오버로드 정리 & 자식으로 설정할 때의 차이Unity에서 동적으로 오브젝트를 생성할 때 가장 많이 사용하는 함수는 Instantiate()다.하지만 부모를 지정하는 방식, 월드 좌표 유지

dev-jen.tistory.com

🔹 Unity 생명주기 & 이벤트 흐름 정리

  • Unity는 MonoBehaviour 기반으로 Awake → OnEnable → Start → Update → LateUpdate → OnDisable → OnDestroy 순서로 흐름이 이어진다.
  • Invoke()는 단순 딜레이용으로 적합하지만, Coroutine은 흐름을 끊고 이어갈 수 있어 더 유연하다.
  • InvokeRepeating()은 간단한 반복 호출이 필요할 때 매우 유용하지만, 조건 제어나 흐름 변화에는 Coroutine이 더 적합하다.
  • Instantiate() 시 부모를 지정하는 방식에 따라 로컬 좌표가 달라질 수 있다. SetParent(transform, false)처럼 두 번째 인자를 명시해야 위치/회전이 부모 기준으로 정확히 맞는다.

🔹 C# 제너릭 싱글톤 패턴

  • 제너릭 싱글톤은 여러 매니저 클래스에서 중복 없이 간결하게 싱글톤 패턴을 구현하는 데 유용하다.
  • where T : MonoBehaviour 제약을 통해 Unity 컴포넌트만 상속 가능하게 제한할 수 있다.

🔹 알고리즘 핵심 개념 복습

  • DP (Dynamic Programming): 작은 문제를 해결한 결과를 저장하며 반복을 줄이는 방식.
  • Greedy: 매 순간 최선의 선택이 전체 최적이라는 확신이 있을 때 사용.
  • Divide and Conquer: 문제를 나누고 합쳐서 푸는 방식 (예: 병합정렬).
  • Backtracking: 모든 경우를 탐색하되 조건을 만족하지 않으면 돌아가는 방식 (예: N-Queen).
  • Union-Find / Disjoint Set: 집합 간 연결성을 추적할 때 사용. 대표적인 사용처는 크루스칼 알고리즘.
  • DFS/BFS: 그래프 탐색의 기본. DFS는 스택, BFS는 큐를 활용하며 각각의 탐색 특징이 다름.

🔹 메타버스 개인 과제 해설 영상

  • 과제 흐름과 포인트를 다시 보며 로직 이해도가 높아졌고, 실제 실습에 어떻게 녹여야 할지 감이 잡혔다.
  • 다양한 기능 구현 방식과 코드 구조를 비교하면서 나의 코드에 개선할 점도 떠올랐다 다음 프로젝트에 적용해볼생각!

🧩 학습하며 겪었던 문제점 & 에러

❌ 1) Instantiate + SetParent() 사용 시 위치/스케일 꼬임 문제

  • 문제정의예상한 위치나 스케일이 깨지고 의도한 위치에 생성되지 않음.
  • 오브젝트를 Instantiate한 뒤 SetParent(transform)으로 부모를 설정했더니
  • 문제 코드 예시
GameObject newObj = Instantiate(obj);   // 월드 기준 생성
newObj.transform.SetParent(transform);  // 부모 설정 (기본은 worldPositionStays = true)
  • 해결 코드 예시
GameObject newObj = Instantiate(obj);
newObj.transform.SetParent(transform, false); // 🔧 로컬 기준으로 정확히 부모에 배치됨
  • 새롭게 알게 된 점따라서 부모 설정 시 월드 좌표를 유지하려고 하기 때문에 로컬 위치가 틀어질 수 있다.
  • SetParent()의 두 번째 인자인 worldPositionStays를 명시하지 않으면 기본값은 true.
  • 다시 만나게 된다면아니면 Instantiate(obj, parent, false)를 사용하면 더 간결하고 명확하다.
  • 자식으로 넣을 때는 항상 SetParent(..., false)를 사용하는 습관을 들이자.

❌ 2) Coroutine vs Invoke 차이 혼동

  • 문제정의제어 흐름과 활용 방식이 완전히 달랐다.
  • Coroutine과 Invoke() 모두 딜레이 기능이 있어서 같은 역할인 줄 알았는데
  • 문제 코드 예시 (Invoke)
void Start()
{
    Invoke("Attack", 3f);
}

void Attack()
{
    Debug.Log("공격!");
}
  • 문제 코드 예시 (Coroutine)
void Start()
{
    StartCoroutine(AttackRoutine());
}

IEnumerator AttackRoutine()
{
    yield return new WaitForSeconds(3f);
    Debug.Log("공격!");
}
  • 차이점 요약
    • Invoke()는 단 한 번, 정해진 시간 후에 딱 한 함수만 실행 가능.
    • Coroutine은 조건, 반복, 다단계 처리 모두 가능하며 유연함.
  • 새롭게 알게 된 점
  • 코루틴은 흐름 제어를 위한 도구이고, Invoke는 단발성 딜레이 호출용으로 훨씬 간단하다.
  • 다시 만나게 된다면
  • 간단한 타이머면 Invoke(), 여러 조건이나 단계가 있다면 무조건 Coroutine 사용.

📝 메모

오늘 복습을 하다 보니 그동안 그냥 넘겼던 부분들이 연결되면서

‘아, 이게 이런 의미였구나’ 하고 퍼즐이 맞춰지는 기분이었다.

특히 Instantiate의 부모 설정과 Coroutine vs Invoke의 차이를

눈으로 보고 직접 실험해보며 이해하니까 훨씬 머리에 잘 남는다.

그냥 문서로만 봤을 땐 “이해한 것 같았는데...” 실제론 헷갈렸던 부분들이었다.

알고리즘 핵심 개념들도 다시 정리하면서

‘내가 생각보다 깊게는 이해하지 못했구나’ 하는 반성도 들었고,

하지만 이런 시간을 통해 조금씩 더 단단해지고 있다고 느낀다.

오늘도 팀원들과 회의를 하며 서로의 프로젝트를 나눌 수 있어서 좋았고,

혼자보다 함께 같이 나아갈 기분이 들어 든든했다.

앞으로도 “잘 모르겠는 건 부끄러운 게 아니라,

그걸 놓치고 넘어가는 게 더 위험하다”는 마음으로

하나하나 꼼꼼히 쌓아가야겠다는 다짐을 다시 해본다.

내일도 화이팅!!!!💪

반응형
반응형

🧱 Unity Instantiate() 오버로드 정리 & 자식으로 설정할 때의 차이

Unity에서 동적으로 오브젝트를 생성할 때 가장 많이 사용하는 함수는 Instantiate()다.
하지만 부모를 지정하는 방식, 월드 좌표 유지 여부, 그리고 스케일/포지션의 차이까지 제대로 이해하지 않으면 예기치 못한 결과가 발생할 수 있다.

이번 포스트에서는 Instantiate()의 다양한 오버로드 버전과, 다음과 같은 코드 두 개의 차이점을 중심으로 정리한다:


🔍 예시

private void FirstSpawn()
{
    Instantiate(obj, transform);
}

private void SecondSpawn()
{
    GameObject newObj = Instantiate(obj);
    newObj.transform.SetParent(transform);
}

❓ 차이점은?

  • FirstSpawn()은 Instantiate 시점에 부모(transform)를 직접 지정한다.
  • SecondSpawn()은 Instantiate 후에 SetParent()로 부모를 설정한다.

⚠️ 결정적 차이: 위치와 스케일의 기준

항목 FirstSpawn SecondSpawn
부모 지정 시점 즉시 (Instantiate 내에서) 나중에 (SetParent로 나중에 지정)
로컬 위치/회전 유지 ✅ 유지됨 ❌ 월드 좌표 기준으로 설정됨
부모 스케일의 영향 ✅ 즉시 반영 ❌ SetParent 시점에 적용 방식 다름
 

즉, 동일한 결과를 원한다면 SecondSpawn 쪽에서 아래와 같이 써야 한다:

newObj.transform.SetParent(transform, false); // worldPositionStays = false

false를 전달하면 로컬 기준으로 배치되어 FirstSpawn과 동일한 결과가 됨.


🧪 Instantiate() 오버로드 총정리

Unity는 다양한 방식으로 Instantiate()를 오버로드하고 있다:

Instantiate(obj); // 기본 복제
Instantiate(obj, transform); // 부모 지정
Instantiate(obj, transform, true/false); // 부모 + 월드/로컬 기준 설정
Instantiate(obj, position, rotation); // 위치/회전 지정
Instantiate(obj, position, rotation, parent); // 위치/회전/부모 모두 지정

함수 설명
Instantiate(original) 원본 위치/회전 그대로 복제
Instantiate(original, parent) 부모 지정, 기본적으로 로컬 좌표 기준
Instantiate(original, parent, bool worldPositionStays) 부모 지정 + 월드 좌표 유지 여부 선택
Instantiate(original, pos, rot) 위치/회전 지정하여 복제
Instantiate(original, pos, rot, parent) 위치/회전/부모까지 모두 설정 가능
 

📌 worldPositionStays란?

Instantiate(obj, parent, true);  // 현재 위치 유지하며 부모만 설정 (월드 기준)
Instantiate(obj, parent, false); // 부모 기준으로 위치 재조정 (로컬 기준)

의미
true 월드 위치/회전 유지, 부모의 로컬 기준 무시
false 부모의 로컬 위치/회전 기준으로 재배치
 

🧠 정리 요약

구분 설명
Instantiate(obj, parent) 로컬 기준으로 부모 설정됨
SetParent(transform) 월드 기준 위치로 이동됨 (스케일 왜곡 주의)
SetParent(transform, false) 로컬 기준으로 부모 설정 (추천)
Instantiate(obj, pos, rot, parent) 원하는 위치/회전 + 부모까지 완벽 지정 가능
transform.localScale 영향 부모 지정 시 즉시 반영됨, 특히 SetParent() 시 의도치 않은 스케일 왜곡 주의
 

📚 참고 링크

반응형
반응형

⏰ Unity Invoke() vs Coroutine 비교 정리

Unity에서 일정 시간 이후에 어떤 작업을 수행하려면 보통 Invoke()나 Coroutine을 사용한다.
둘 다 **시간 지연(delay)**을 다룰 수 있지만, 구조와 활용도에는 큰 차이가 있다.

이 글에서는 두 방법의 차이점, 장단점, 실제 사용 예시를 함께 정리한다.


🔹 1. Invoke()란?

Invoke()는 지정한 시간 후에 단 한 번 특정 함수를 호출하는 Unity 내장 함수다.

✅ 사용법

void Start()
{
    Invoke("DelayedFunc", 2f); // 2초 후 DelayedFunc 실행
}

void DelayedFunc()
{
    Debug.Log("2초 후 실행됨");
}

🔹 2. Coroutine이란?

Coroutine은 시간의 흐름에 따라 동작을 일시정지하고 다시 재개할 수 있는 기능이다.
IEnumerator를 반환하고, yield return을 통해 흐름을 제어한다.

✅ 사용법

void Start()
{
    StartCoroutine(DelayedCoroutine());
}

IEnumerator DelayedCoroutine()
{
    yield return new WaitForSeconds(2f);
    Debug.Log("2초 후 실행됨 (코루틴)");
}

🔍 차이점 비교

항목 Invoke() Coroutine()
기본 개념 일정 시간 후 한 번 함수 호출 흐름을 일시정지하고 재개
지연 시간 제어 고정된 1회성 딜레이 반복/조건 기반 다양하게 제어 가능
정지 조건 CancelInvoke() 호출 시 StopCoroutine() 호출 시
복잡한 로직 처리 ❌ 불가능 ✅ 가능 (반복, 조건대기 등)
가독성 간단한 작업에 유리 반복 동작일 땐 더 명확함
타이밍 유연성 낮음 높음
Time.timeScale 영향 ✅ 받음 ✅ 받음 (WaitForSeconds)

🛑 Invoke 정지 예시

▶ 전체 코드

using UnityEngine;

public class InvokeStopExample : MonoBehaviour
{
    void Start()
    {
        // 5초 후에 GameOver()를 실행하려고 예약
        Invoke("GameOver", 5f);

        // 2초 뒤에 취소
        Invoke("CancelGameOver", 2f);
    }

    void GameOver()
    {
        Debug.Log("🟥 Game Over!");
    }

    void CancelGameOver()
    {
        Debug.Log("🟨 Game Over 예약 취소");
        CancelInvoke("GameOver");
    }
}

📝 요약

  • Invoke("GameOver", 5f)로 예약 
  • 2초 후 CancelInvoke("GameOver")로 중단
  • 결국 GameOver()는 실행되지 않음

🛑 Coroutine 정지 예시

▶ 전체 코드

using UnityEngine;
using System.Collections;

public class CoroutineStopExample : MonoBehaviour
{
    private Coroutine attackRoutine;

    void Start()
    {
        attackRoutine = StartCoroutine(DelayedAttack());
        Invoke("StopAttack", 2f); // 2초 후 코루틴 중단
    }

    IEnumerator DelayedAttack()
    {
        Debug.Log("🟢 공격 준비...");
        yield return new WaitForSeconds(5f); // 5초 대기
        Debug.Log("🔴 공격 실행!");
    }

    void StopAttack()
    {
        if (attackRoutine != null)
        {
            StopCoroutine(attackRoutine);
            Debug.Log("🟨 공격 중단됨");
        }
    }
}

 

📝 요약

  • 5초 후 공격을 하려는 코루틴 실행
  • 2초 후 StopCoroutine()으로 중단
  • 결국 🔴 공격 실행!은 출력되지 않음

✅ 핵심 요약

항목 정지 방법
Invoke CancelInvoke("함수이름")
Coroutine StopCoroutine(코루틴변수) 또는 StopAllCoroutines()
 
오.. 지금 처음 알게된게 코루틴도 변수처럼 쓸수있는걸 처음 알았다...

🧪 예시 비교

🎯 예: 3초 후 공격 애니메이션 시작

✅ Invoke 방식

void Start()
{
    Invoke("StartAttack", 3f);
}

void StartAttack()
{
    animator.SetTrigger("Attack");
}

✅ Coroutine 방식

IEnumerator StartAttackCoroutine()
{
    yield return new WaitForSeconds(3f);
    animator.SetTrigger("Attack");
}

void Start()
{
    StartCoroutine(StartAttackCoroutine());
}

✅ 언제 어떤 걸 써야 할까?

상황 추천방식
단순하게 일정 시간 후 함수 실행 Invoke()
반복/조건 기반 대기 필요 Coroutine
시간 흐름에 따라 여러 동작을 연결해야 할 때 Coroutine
가독성이 중요한 짧은 로직 Invoke()
 

🧠 Tip: InvokeRepeating()도 있다!

InvokeRepeating()을 사용하면 일정 시간 간격으로 반복 실행도 가능하다.

InvokeRepeating("SpawnEnemy", 1f, 5f); // 1초 후부터 5초 간격으로 반복 실행

이 역시 코루틴의 while(true) + WaitForSeconds()로 대체 가능하지만, 매우 간단할 때는 편리하다.


🏁 결론

한 줄 요약
간단한 타이머 → Invoke() / 유연한 시간 흐름 제어 → Coroutine
 

Invoke()는 빠르고 간단하지만 제어력이 낮고, Coroutine은 더 복잡하지만 강력하다.
상황에 따라 적절히 선택하면 효율적인 Unity 개발이 가능하다.

 

🔁 Unity InvokeRepeating() 간단 정리

✅ 개념

InvokeRepeating()은 지정한 시간 후부터 일정 간격으로 함수를 반복 실행하는 Unity 내장 함수다.
Update()나 Coroutine 없이도 정기적인 타이머 기반 로직을 구현할 수 있다.


🧪 사용 예시

using UnityEngine;

public class RepeatExample : MonoBehaviour
{
    void Start()
    {
        // 2초 후부터 시작해서, 1초마다 Attack() 실행
        InvokeRepeating("Attack", 2f, 1f);
    }

    void Attack()
    {
        Debug.Log("🔥 공격 실행!");
    }
}

 


🛑 반복 중단

 
void StopAttack()
{
    CancelInvoke("Attack");
}

📌 요약 표

항목 설명
사용 함수 InvokeRepeating("함수이름", 지연시간, 반복간격)
중지 방법 CancelInvoke("함수이름") 또는 CancelInvoke()
실행 조건 MonoBehaviour가 활성화된 상태여야 실행됨
장점 매우 간단한 반복 호출에 적합
단점 복잡한 흐름 제어나 조건 분기에는 불리
 

✅ 언제 사용하면 좋을까?

사용 상황 적합 여부
단순한 반복 로직 (ex. 1초마다 이펙트 생성) 👍 매우 적합
조건에 따라 반복 중단/재개 👍 사용 가능 (with CancelInvoke)
복잡한 흐름 제어가 필요한 경우 ❌ Coroutine이 더 적합
 

🏁 결론

InvokeRepeating()은 초간단 반복 타이머를 구현할 때 매우 유용한 도구다.
단, 조건 제어나 흐름 조절이 필요하면 Coroutine으로 전환하는 것이 좋다.

 

원래 3개는 다 알고있었지만 쓰기만하고 잘 알지는 못했었다. 이번 기회로 더 잘 사용하고 언제 사용할지에대해 알게된거같다!! 실제로 많이 써봐야지..그래야 실력이 늘지 ㅠㅜ

반응형
반응형

📌 Coroutine이란?

**코루틴(Coroutine)**은 Unity에서 제공하는 특별한 함수로, 작업의 흐름을 중간에 일시정지하고, 조건이 충족되면 다시 이어서 실행할 수 있다.

코루틴은 IEnumerator 반환형을 가지며, StartCoroutine() 함수를 통해 실행된다.

IEnumerator ExampleCoroutine()
{
    Debug.Log("1초 대기 전");
    yield return new WaitForSeconds(1f);
    Debug.Log("1초 대기 후");
}
StartCoroutine(ExampleCoroutine());

⚙️ Coroutine 실행 흐름

코루틴은 Update() 함수가 끝난 뒤 실행된다.
즉, 모든 Update() 함수가 호출된 이후, 코루틴이 yield return한 지점부터 재개된다.


⏱️ 다양한 YieldInstruction 종류

YieldInstruction 설명
yield return null 다음 프레임까지 대기 후 이어서 실행
yield return new WaitForSeconds(x) x초 후에 이어서 실행
yield return new WaitForFixedUpdate() 모든 FixedUpdate() 이후에 실행됨
yield return new WaitUntil(() => condition) 주어진 조건이 true가 될 때까지 대기
yield return new WaitWhile(() => condition) 주어진 조건이 false가 될 때까지 대기
yield return www WWW 요청(웹 요청)이 완료될 때까지 대기 (UnityWebRequest 권장)
yield return StartCoroutine(Other()) 다른 코루틴이 완료될 때까지 대기
 

🔁 Coroutine 중단 및 종료

  • 중단: StopCoroutine("함수이름"), StopCoroutine(코루틴변수)
  • 모든 코루틴 종료: StopAllCoroutines()
Coroutine myRoutine;

void Start()
{
    myRoutine = StartCoroutine(MyCo());
}

void StopIt()
{
    StopCoroutine(myRoutine);
}

 

여기서 주의할점은 코루틴을 변수로 사용하지 않는다면 StopCoroutine을해도 멈추지 않는다 왜냐하면 다른 인스턴스를 참조하기 때문이다!!


✅ 언제 Coroutine을 사용해야 할까?

사용 사례설명
연출 처리 화면 전환, 효과 타이밍, 대기 후 실행 등
시간 기반 반복 일정 시간 간격으로 동작 반복 (예: 총알 발사 쿨타임)
조건 대기 어떤 조건을 만족할 때까지 기다리는 처리
비동기 작업 웹 요청, 파일 로딩 등 완료까지 시간이 걸리는 작업
 

🧠 주의할 점

  • yield return new WaitForSeconds()는 Time.timeScale의 영향을 받는다. (0이면 멈춤)
  • MonoBehaviour가 비활성화되면 코루틴도 멈춘다.
  • 코루틴 내에서 무한 루프를 만들면 게임이 멈출 수 있다.

🧪 예시: 간단한 반복 공격

IEnumerator AutoAttack()
{
    while (true)
    {
        Attack();
        yield return new WaitForSeconds(1f); // 1초마다 공격
    }
}

🏁 마무리

코루틴은 Unity 개발에서 시간을 다루는 가장 강력한 도구 중 하나이다.
처음엔 Update()보다 복잡하게 느껴질 수 있지만, 익숙해지면 타이밍 제어, 연출 구현, 대기 처리에 매우 유용하다.

 

 

흠..원래 개발할때 코루틴을 많이 썼었는데 인보크도 많이 사용하는 듯 하다 인보크와 코루틴 비교하는 글도 한번 작성해 봐야겠다.

반응형
반응형

🌀 Unity MonoBehaviour 생명주기 (Lifecycle) 정리

Unity는 MonoBehaviour 기반의 스크립트를 일정한 순서로 호출하며, 게임 오브젝트의 생성부터 종료까지 다양한 이벤트 함수를 실행한다. 아래는 각 단계별로 정리한 생명주기 흐름이다.

 

🔹 1. 초기화 (Initialization)

이벤트 함수설명
Awake() 오브젝트가 인스턴스화된 직후 호출. 스크립트 간 참조 연결에 자주 사용. Start()보다 먼저 호출됨.
OnEnable() 오브젝트가 활성화될 때마다 호출. 컴포넌트가 켜지거나 오브젝트가 활성화되면 호출됨.
Reset() 에디터에서 컴포넌트를 추가할 때 자동 호출됨. 기본값 초기화 목적.
Start() 스크립트가 활성화된 상태일 때, 첫 번째 프레임 전에 단 한 번 호출됨.

 

- Awake: 이 함수는 항상 Start 함수 전에 호출되며 프리팹이 인스턴스화 된 직후에 호출됩니다. 게임 오브젝트가 시작하는 동안 비활성 상태인 경우 Awake 함수는 활성화될 때까지 호출되지 않습니다.


- OnEnable: (오브젝트가 활성화된 경우에만): 오브젝트 활성화 직후 이 함수를 호출합니다. 레벨이 로드되거나 스크립트 컴포넌트를 포함한 게임 오브젝트가 인스턴스화될 때와 같이 MonoBehaviour를 생성할 때 이렇게 할 수 있습니다.

 

- Start: 스크립트 인스턴스가 활성화된 경우에만 첫 번째 프레임 업데이트 전에 호출됩니다.


🔹 2. 물리 업데이트 (Physics)

이벤트 함수설명
FixedUpdate() 일정 시간 간격으로 호출되는 물리 업데이트. Rigidbody 물리 계산 시 여기에 구현.
OnTriggerEnter/Stay/Exit() 트리거 충돌 감지 이벤트
OnCollisionEnter/Stay/Exit() 일반 충돌 감지 이벤트

 

Unity - Update(), FixedUpdate(), LateUpdate()

✅ Unity의 3가지 주요 루프 함수함수 이름실행 주기용도특징Update()매 프레임마다사용자 입력, 일반 로직프레임 속도에 따라 실행 빈도 달라짐 (가변)FixedUpdate()고정 시간 간격마다물리 연산 (Rigidb

dev-jen.tistory.com

- FixedUpdate: FixedUpdate 는 종종 Update 보다 더 자주 호출됩니다. 프레임 속도가 낮은 경우 프레임당 여러 번 호출될 수 있으며 프레임 속도가 높은 경우 프레임 사이에 호출되지 않을 수 있습니다. 모든 물리 계산 및 업데이트는 FixedUpdate 후 즉시 발생합니다. FixedUpdate 의 움직임 계산을 적용할 때 Time.deltaTime 만큼 값을 곱할 필요가 없습니다. FixedUpdate 가 프레임 속도와 관계없이 신뢰할 수있는 타이머에서 호출되기 때문입니다.

- Update: Update 는 프레임당 한 번 호출됩니다. 프레임 업데이트를 위한 주요 작업 함수입니다.

- LateUpdate: LateUpdate 는 Update 가 끝난 후 프레임당 한 번 호출됩니다. Update 에서 수행된 모든 계산은 LateUpdate 가 시작할 때 완료됩니다. LateUpdate 는 일반적으로 다음의 3인칭 카메라에 사용합니다. 캐릭터를 움직이고 Update 로 방향을 바꾸게 하는 경우 LateUpdate 에서 모든 카메라 움직임과 로테이션 계산을 수행할 수 있습니다. 이렇게 하면 카메라가 포지션을 추적하기 전에 캐릭터가 완전히 움직였는지 확인할 수 있습니다.

 


🔹 3. 입력 및 게임 로직 (Input & Game Logic)

이벤트 함수설명
Update() 프레임마다 한 번 호출. 게임 로직의 중심 함수
LateUpdate() Update()가 끝난 직후 호출. 주로 카메라 추적 처리 등에 사용
OnMouseDown/Up/Drag() 마우스 관련 이벤트 감지

🔹 4. 애니메이션 관련 (Animation)

이벤트 함수설명
OnAnimatorMove() 루트 모션 제어용 함수
OnAnimatorIK() IK(역운동학) 처리용 함수
StateMachineBehaviour 콜백들 OnStateEnter, OnStateExit, OnStateUpdate, OnStateIK, OnStateMove 등
내부 프로세스 State Machine Update, ProcessGraph, ProcessAnimation, WriteTransform, WriteProperties 등

🔹 5. 렌더링 전/후 처리 (Rendering)

이벤트 함수설명
OnPreCull() 카메라가 오브젝트를 컬링하기 전 호출
OnBecameVisible/Invisible() 카메라 시야에 들어오거나 나갈 때 호출
OnWillRenderObject() 오브젝트가 카메라에 의해 렌더링될 때 호출
OnPreRender() / OnPostRender() 카메라 렌더링 전/후 호출
OnRenderImage() 포스트 프로세싱에 사용
OnRenderObject() GL이나 Graphics API를 직접 호출할 때
OnDrawGizmos() 에디터에서 Gizmo를 그릴 때
OnGUI() GUI를 그릴 때. 프레임당 여러 번 호출

🔹 6. 코루틴 (Coroutine)

사용법 설명
yield return null 다음 프레임까지 대기
yield return new WaitForSeconds(x) x초간 대기
yield return new WaitForFixedUpdate() 다음 FixedUpdate 이후 실행
yield return StartCoroutine() 다른 코루틴을 완료할 때까지 대기

🔹 7. 종료 및 비활성화 (Decommissioning)

이벤트 함수 설명
OnApplicationPause() 앱이 일시정지 될 때 호출
OnApplicationQuit() 애플리케이션이 종료될 때 호출
OnDisable() 오브젝트가 비활성화될 때 호출
OnDestroy() 오브젝트가 제거되거나 씬이 종료될 때 호출됨

✅ 요약: 주요 순서 흐름

  1. Awake → OnEnable → Start
  2. FixedUpdate → Update → LateUpdate
  3. (필요 시) Trigger/Collision → Animator 관련 → Rendering → Coroutine 재개
  4. OnDisable → OnDestroy → OnApplicationQuit

 

 

원래 생명주기에 대해서는 잘 알고 있다고 생각했는데..내가 모르는 라이프사이클의 함수가 굉장히 많았다..하나씩 정리해보면서 느꼈지만 아직도 공부할게 산더미 인거같다ㅎㅎ..

반응형
반응형

🌈 2025년 7월 넷째 주 WIL

1. 이번 주 가장 인상 깊었던 배움은 무엇이었나요?

이번 주는 Unity를 활용해 다양한 게임 장르와 기능을 직접 구현하면서,
게임 구조 설계와 시스템 간 연동의 중요성을 체감한 한 주였다.

가장 기억에 남는 배움은 다음과 같다:

  • Flappy Bird 스타일 게임을 만들며
    점프 로직, 장애물 재배치, 반복 배경, 점수 시스템 등
    단순하지만 타이트한 게임 흐름 제어를 익혔다.
  • The Stack 블록 쌓기 게임에서는
    타이밍 기반 블록 정렬, 오차 계산, UI 상태 전환 등의 로직을 구현하며
    반복 플레이에 중독성을 주는 디자인 요소를 경험했다.
  • 또 하나 인상 깊었던 것은,
    NPC와의 상호작용을 통한 메타버스 느낌의 미니게임 씬 전환 시스템을 만든 것이다.
    NPC와 대화하는 과정에서 F 키를 눌러 특정 씬으로 전환하고,
    대사 상태에 따라 다른 반응을 출력하게 하며
    씬 간 흐름, 게임모드 분기 처리, 상태 기반 UI 연동을 직접 설계하고 구현했다.

이 과정에서 말풍선에 TextMeshPro를 적용,
NPC가 기본 상태 / 화난 상태 / 대화 상태를 오가며 자연스럽게 반응하는 로직을 만들면서
UI, 애니메이션, 상태 시스템이 어떻게 유기적으로 연동되어야 하는지를 실전으로 체득할 수 있었다.

특히, 몬스터가 총알을 발사하고
플레이어가 자신의 총알로 이를 상쇄하는 전투 상호작용 시스템을 구현한 점도
처음으로 적의 공격을 피하거나 맞는 것이 아닌, 상호 제압하는 구조를 직접 설계해본 값진 경험이었다.

 

2. 그 배움을 얻기까지 어떤 어려움이 있었나요?

이번 주에는 다양한 게임 구조를 구현하면서 씬 전환, 상태 제어, UI 처리, 충돌 상호작용 등 복잡한 흐름을 설계해야 했기 때문에, 각각의 시스템이 꼬이거나 충돌하는 상황이 잦았다.

🙁 예를 들면…

  • 게임 오버 후 씬이 재시작되지 않고 UI만 바뀌는 문제가 발생했고,
    이는 SceneManager.LoadScene() 호출이 누락된 것이 원인이었다.
  • 몬스터 총알을 플레이어 총알로 상쇄하는 시스템에서도,
    처음에는 충돌 감지가 제대로 되지 않아 총알이 서로 관통하거나 동시에 사라지지 않는 현상이 생겼다.
    레이어 설정, 태그 구분, OnTriggerEnter2D의 조건 검토를 통해 해결했다.
  • NPC와의 상호작용에서는
    대사 상태가 "화남"일 때도 기본 랜덤 대사가 계속 출력되는 문제가 있었는데,
    이건 상태 전환 조건이 우선순위 없이 체크되고 있어서 생긴 문제였다.
    결국 조건 분기를 명확히 나누고, 상태 변경이 일어날 때마다 말풍선을 새로 갱신하도록 처리했다.

⚙️ 그리고 구조적 설계에서도…

  • UIManager나 GameManager의 싱글톤 구조를 유지하면서도 DontDestroyOnLoad를 사용할지 말지에 대한 고민이 계속 있었고,
    중간에 기존 구조를 폐기하고 다시 설계하는 일도 있었다.
  • 씬 전환 이후에 NPC나 애니메이션 상태가 리셋되거나 꼬이는 문제도 있었고,
    결국 각 씬 진입 시 초기화 로직과 상태 복원 로직을 나누어 관리해야 했다.

이러한 어려움 속에서도 기능 하나하나를 테스트하고 직접 실험하면서 해결하는 과정 자체가 큰 배움이 되었다.
그동안은 구현 위주로만 작업했는데, 이번 주에는 버그를 정확히 분석하고 수정하는 과정까지 깊이 경험할 수 있었다.

 

3. 그 과정에서 나는 무엇을 깨달았고, 어떤 감정/생각이 들었나요?

이번 주의 개발 과정은 단순히 기능을 "만드는 것"을 넘어서
기능 간의 연결과 구조 설계의 중요성을 온몸으로 체험하는 시간이었다.

처음에는 "이것만 구현하면 끝이겠지?" 하고 시작했던 기능들이
막상 실제 플레이 흐름 속에 들어가면 의도치 않은 버그
다른 시스템과의 충돌로 인해 예상보다 훨씬 복잡해졌고,
그때마다 **"아직 내가 생각하지 못한 부분이 많았구나"**라는 사실을 느꼈다.

특히 NPC 상태나 UI 상태처럼 여러 조건이 동시에 작동하는 경우,
우선순위나 분리된 처리 구조 없이 구현하면 금방 꼬인다는 걸 알게 되었고,
그 경험을 통해 코드는 언제나 예외를 고려하며 작성해야 한다는 걸 실감했다.

또한 문제를 마주했을 때 “왜 이게 안 되지?”라는 막막함보다는
한 발짝 물러서서 원인부터 차근히 좁혀나가 보는 습관을 조금씩 익혀가며,
혼자 문제를 해결하는 시간들이 점점 재밌고 보람 있게 느껴졌다.

때로는 ‘결국 내가 직접 해결해야만 일이 굴러가는구나’ 싶을 때도 있었지만,
바로 그 순간들이 나를 한 단계씩 성장시키는 시간이었다고 느낀다.

 

4. 메모 (느낀 점, 다짐)

이번 주는 정말 많이 부딪히고, 스스로 풀어낸 시간이 많았다.
처음엔 단순해 보였던 기능들이 막상 실제 게임 흐름 안에 들어가면 얼마나 복잡해질 수 있는지를 경험했고,
그 과정에서 "내가 아직 모르고 있는 게 참 많구나"를 다시 깨달았다.

하지만 중요한 건 모른다는 걸 인정하고, 계속해서 부딪히며 해결해 나가는 자세라는 걸 알게 됐다.
때로는 혼자 버그를 붙잡고 머리를 싸매다가,
정말 작은 조건 하나를 고치고 나서 기분 좋게 해결되는 순간도 많았다.

이번 주 가장 고마웠던 건 스스로 원인을 추적하고 해결하는 습관이 조금은 자리 잡히기 시작했다는 것.
"이 정도는 내가 직접 풀 수 있어"라는 자신감이 하나둘 생기기 시작한 것 같다.

앞으로도 복잡한 문제 앞에서 겁먹지 않고,
천천히, 하지만 정확하게 원인을 파악하고 해결하는 개발자가 되고 싶다.

 

사실 이번주는 개발만 해서 뭔가 많이 배우지는 않았지만 실전 개발을 하면서 여러가지 깨달은것이 많았다. 다음주도 새롭게 다시 팀프로젝트를 시작할텐데 하나씩 천천히 구조도 잘 짜보고 잘 만들어보자아ㅏ!! 다음주도 화이티잉ㅇ!!!

  

 

📅 이번 주 TIL 목록

 

내일배움캠프 16일차 TIL [팀프로젝트 발표 + 유니티 개발]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 : 프로젝트 회의 및 코드 정리전체 구조 리뷰 및 코드 수정팀원들과 기능 분담 및 로직 개선 방향 논의🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 16:

dev-jen.tistory.com

 

내일배움캠프 17일차 TIL [TopDown게임 제작]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:00 : 새로운 팀 배정 및 팀원 자기소개10:00 ~ 10:30 : Unity 입문 챕터 발제 강의 수강10:30 ~ 13:00 : 2D TopDown Shooting 게임 개발 시작🍽️ 점심시간13:00 ~ 14:00 : 점심시

dev-jen.tistory.com

 

내일배움캠프 18일차 TIL [메타버스 게임]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 : 프로젝트 회의 및 캐릭터/무기 구조 개선🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 18:00 : 캐릭터 점프 애니메이션 구현, 무기 플립 회전 문제 해

dev-jen.tistory.com

 

내일배움캠프 19일차 TIL [메타버스 게임]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 : Unity 개발NPC에 TextMeshPro 말풍선 부착 및 자동 잡담 시스템 구현총알 피격 시 다른 대사 출력 기능 구현몬스터가 총알을 발사하고, 플레이어가 총알로 상

dev-jen.tistory.com

 

내일배움캠프 20일차 TIL [메타버스 게임]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:30 : EnemyManager 수정하드/이지 난이도에 따라 다른 적 프리팹이 생성되도록 구조 변경GameManager.CurrentDifficulty 값 사용 확인 및 디버깅 완료10:30 ~ 13:00 : 씬 전환

dev-jen.tistory.com

 

📅 이번 주 Study 목록

 

Unity - Singleton Pattern (싱글톤 패턴) in Unity

🎮 Unity에서의 싱글톤(Singleton) 패턴🔍 싱글톤이란?싱글톤(Singleton)은 프로그램 전체에서 단 하나의 인스턴스만 존재하도록 보장하는 디자인 패턴이다. 게임에서는 주로 오디오 매니저, 게임 매

dev-jen.tistory.com

 

Unity - Unity에서의 Generic Singleton 패턴

❓ 왜 Generic Singleton이 필요할까?Unity에서는 GameManager, SoundManager, UIManager 등 다양한 매니저 클래스에서 싱글톤(Singleton) 패턴을 사용한다.하지만 매번 static instance 선언, Awake()에서 중복 제거 같은

dev-jen.tistory.com

 

Unity - 2D TopDown에서 캐릭터와 무기의 회전 및 Flip 처리 정리

Unity 2D TopDown에서 캐릭터와 무기의 회전 및 Flip 처리 정리✨ 문제 배경TopDown 방식의 2D 슈팅 게임을 만들다 보면, 마우스 방향에 따라 캐릭터가 회전하고, 무기도 함께 회전하도록 구현해야 합니

dev-jen.tistory.com

 

Unity - Collider2D의 Layer Overrides(Include Layers, Exclude Layers) 알아보기

✍️ 본문최근 Unity에서 OnTriggerEnter2D가 도무지 작동하지 않아 시간을 꽤 허비했습니다.알고 보니 Collider2D의 "Layer Overrides" 설정이 원인이었습니다.이번 글에서는 이 기능이 무엇인지, 왜 문제가

dev-jen.tistory.com

 

 

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 10:30 : EnemyManager 수정
    • 하드/이지 난이도에 따라 다른 적 프리팹이 생성되도록 구조 변경
    • GameManager.CurrentDifficulty 값 사용 확인 및 디버깅 완료
  • 10:30 ~ 13:00 : 씬 전환 시 난이도 정보 유지 문제 해결
    • EasyStartGame(), HardStartGame() 함수 점검
    • 씬 로드 후 난이도 정보가 사라지는 이슈 해결

🍽️ 점심시간

  • 13:00 ~ 14:00 : 점심시간

✅ 오후

  • 14:00 ~ 15:30 : InteractionButton 기능 구현
    • GameType(EasyGame, TheStackGame) 기반 분기
    • NPC와 상호작용 시 F 키로 게임 시작 가능하게 처리
    • 한때 말풍선으로 힌트 출력 시도 → 결과적으로 사용 안 하기로 결정
  • 15:30 ~ 16:30 : 마을로 돌아가는 버튼 기능 구현 & 버그 수정
    • ReturnToVillageButton.cs 생성
    • 버튼 UI에 OnClick으로 연결해 "MainScene" 로드 가능하게 처리
    • 나머지 버그 수정
  • 16:30 ~ 18:00 : DNP 데미지 숫자 시스템 연동
    • ProjectileController에서 적 충돌 시 데미지 숫자(DNP) 띄우기 구현
    • DNP_DemoManager 사용 중 NullReference 오류 발생 → 원인 파악 완료
    • 최종적으로 DNP_DemoManager 대신 커스텀 DamageNumber 호출 구조로 방향 전환 고려

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁시간

✅ 저녁

  • 19:00 ~ 20:30 : 애니메이션 다듬기 및 최종 마무리
    • AnimationHandler에서 IsDamage 트리거 0.1초 후 자동 false로 되도록 코루틴 추가
    • 사용하지 않는 음악 기능, 상호작용 힌트 출력 기능은 직접 테스트 후 사용 안 함으로 결정
    • 마지막으로 마을에 NPC 여러 명 배치하며 마무리 작업 완료

✅ 오늘 학습 키워드

  • 난이도별 적 프리팹 분기 처리 (EnemyManager)
  • 씬 전환 시 데이터 유지 (GameManager.CurrentDifficulty)
  • NPC와 상호작용 구조 (InteractionButton, GameType)
  • 버튼 기반 씬 이동 (ReturnToVillageButton)
  • 총알 충돌 판정 및 데미지 적용 (ProjectileController)
  • Damage Number Pro(DNP) 시스템 연동
  • 애니메이션 코루틴 활용 (IsDamage 0.1초 유지)
  • Unity에서의 Clip Count 및 Animation Curve 분석
  • 기능 보류/삭제에 대한 판단 (배경음 변경, 말풍선 힌트 출력)

✅ 오늘 학습 한 내용을 나만의 언어로 정리하기

 

Unity - Collider2D의 Layer Overrides(Include Layers, Exclude Layers) 알아보기

✍️ 본문최근 Unity에서 OnTriggerEnter2D가 도무지 작동하지 않아 시간을 꽤 허비했습니다.알고 보니 Collider2D의 "Layer Overrides" 설정이 원인이었습니다.이번 글에서는 이 기능이 무엇인지, 왜 문제가

dev-jen.tistory.com

오늘은 게임에서 하드/이지 난이도에 따라 다른 적들이 등장하도록 EnemyManager를 수정했다. 처음에는 프리팹 리스트만 바꿔주면 될 줄 알았지만, 실제로 GameManager의 난이도 값이 씬 전환 후 초기화되는 문제를 겪으면서, 난이도 유지 시점과 순서를 정확히 고려해야 한다는 걸 배웠다. 결국 CurrentDifficulty 값을 적절히 설정하고, 씬 전환 전에 정확히 반영되도록 하여 문제를 해결했다.

또한, NPC와의 상호작용을 통해 미니게임으로 이동하는 구조를 설계했다. GameType이라는 enum을 만들어, 한 스크립트에서 여러 미니게임을 구분할 수 있게 했고, F 키로 입력을 받는 방식으로 사용자 경험도 고려했다. 말풍선을 이용해 상호작용 힌트를 출력하려 했지만, 시각적으로 어울리지 않거나 기능이 애매하다고 판단하여 실제 게임에선 사용하지 않기로 결정했다. 기능을 단순화하면서도 효과적인 UX를 위해 과감히 제외하는 것도 중요한 판단이라는 걸 느꼈다.

추가로, 게임을 종료하거나 마을로 돌아갈 수 있는 기능도 만들었다. 단순히 MainScene을 로드하는 방식이지만, 사용자 흐름을 정리해주는 중요한 역할을 한다고 생각했다. 버튼 하나라도 플레이어 경험에 직접적인 영향을 준다는 걸 체감했다.

그리고 총알이 적에게 닿을 때 데미지 숫자가 떠오르는 기능을 구현하기 위해 Damage Number Pro(DNP)를 연동했다. ProjectileController에서 데미지를 적용하는 시점에 숫자를 출력하는 구조였고, 처음에는 DNP_DemoManager를 사용하려다 null 오류를 겪고 구조적으로 더 안전한 커스텀 방식으로의 전환을 고려하게 됐다. 이 과정에서 외부 에셋을 프로젝트에 통합할 때 단순히 코드만 붙이는 게 아니라, 매니저나 오브젝트 의존성도 함께 고려해야 한다는 걸 배웠다.

마지막으로, 애니메이션에서 데미지를 받는 상태(IsDamage)를 짧게 유지하는 기능도 코루틴을 통해 간결하게 처리했다. 짧은 시각적 피드백이라도 자연스럽게 표현되는 것이 중요하다는 걸 느꼈고, 전체적인 디테일을 마무리하는 데 도움이 되었다.


🧩 학습하며 겪었던 문제점 & 에러

1. 문제정의: 하드 모드인데 Easy 적이 나오는 문제

  • 시도: GameManager.CurrentDifficulty 값을 보고 프리팹 리스트를 선택하도록 코드 수정
  • 해결 방법: 씬을 전환하기 전에 난이도를 정확히 설정해야 한다는 것을 인지하고, EasyStartGame() / HardStartGame() 내부에서 CurrentDifficulty 값을 먼저 설정하고 씬을 로드하는 순서로 수정
  • 새롭게 알게 된 점: 씬 전환 전에 변수 상태를 정확히 설정하지 않으면 다음 씬에서는 초기값으로 시작한다는 Unity의 흐름
  • 다시 만나게 된다면: 상태 데이터를 유지해야 하는 경우는 반드시 씬 전환 전에 정리하고, 필요하면 DontDestroyOnLoad나 PlayerPrefs로 넘겨주는 방식을 고려할 것

2. 문제정의: Interaction 힌트 메시지 말풍선 출력 시도 실패

  • 시도: NpcDialog.ShowInteractionHint() 함수를 만들어 플레이어가 다가오면 “F 키를 눌러 미니게임을 시작하세요” 메시지를 출력
  • 해결 방법: 직접 테스트 결과, 메시지가 기존 대사 흐름과 섞이면서 흐름이 어색하고 UI가 예쁘지 않다는 판단으로 해당 기능은 제외
  • 새롭게 알게 된 점: 무조건 기능을 넣는 것보다 사용자 경험 관점에서 판단해 삭제하는 것도 좋은 선택
  • 다시 만나게 된다면: 메시지를 출력할 때 기존 상태와 분리되도록 더 구조화하거나, 별도 전용 UI를 사용하는 방식 고려

3. 문제정의: DNP_DemoManager 사용 시 NullReferenceException 발생

  • 시도: ProjectileController에서 DNP_DemoManager.instance.GetSettings()를 호출
  • 해결 방법: 콘솔 오류를 통해 instance가 null이라는 것을 확인 → 해당 오브젝트가 현재 게임 씬에 존재하지 않음을 파악
  • 새롭게 알게 된 점: 외부 에셋을 사용할 때는 매니저 객체가 씬에 포함되어 있는지, 초기화가 완료되었는지 항상 확인해야 함
  • 다시 만나게 된다면: 데모 매니저가 아닌 커스텀 매니저를 만들어 인스펙터에서 프리팹을 수동으로 할당하고 사용할 것

4. 문제정의: IsDamage 애니메이션이 끝나지 않고 계속 유지됨

  • 시도: Damage() 함수에서 animator.SetBool(IsDamage, true)만 설정
  • 해결 방법: 코루틴을 만들어 0.1초 뒤에 false로 자동 리셋되도록 구현
  • 새롭게 알게 된 점: 상태 기반 애니메이션은 시각적으로 너무 길게 남아 있으면 부자연스럽기 때문에 짧고 명확하게 제어해줘야 한다
  • 다시 만나게 된다면: Animator의 Trigger 또는 Animation Events로 자연스럽게 제어할 수도 있다는 점도 고려할 것

📝 메모

오늘은 정말 많은 기능을 만들었고, 그만큼 고민도 많았던 하루였다. 기능 하나 추가하려고 했다가 예상하지 못한 문제가 생기고, 막상 구현해놓고도 직접 테스트해보니 애매해서 빼버리는 선택도 해야 했다. 처음엔 아까운 마음도 들었지만, 그게 오히려 더 중요한 결정이었다는 걸 느꼈다.

하드/이지 적 분기처럼 단순해 보이는 기능도 실제로 구현할 땐 씬 전환 흐름과 상태 유지 같은 복잡한 요소들이 얽혀 있었다. 내가 만든 구조를 더 깊이 이해하게 되었고, 이제는 단순히 “되게 만드는 것”에서 “깨끗하게 설계하는 것”으로 한 단계 올라서고 있다는 느낌이 들었다.

무엇보다 좋았던 건 마지막에 NPC들을 하나씩 마을에 배치하면서 “아 이제 진짜 내가 만든 게임 같다”는 만족감이 들었던 순간이다. UI 하나, 대사 하나, 버튼 하나까지도 다 내 손으로 다듬은 거라서 더 애착이 갔다.

조금은 지치기도 했지만, 하나하나 기능을 직접 만들고 테스트하고 결정해나가는 이 시간이 정말 즐겁고 보람찼다!!!! 오예!! 앞으로도 화이팅!!

 

유튜브는 금일 마지막까지 개발하고 거의 완성!

 

반응형
반응형

✍️ 본문

최근 Unity에서 OnTriggerEnter2D가 도무지 작동하지 않아 시간을 꽤 허비했습니다.
알고 보니 Collider2D의 "Layer Overrides" 설정이 원인이었습니다.
이번 글에서는 이 기능이 무엇인지, 왜 문제가 생기는지, 어떻게 설정해야 하는지를 정리해봅니다.


🧩 Layer Overrides란?

Unity 2020.3부터 Collider2D에는 Layer Overrides 기능이 추가되었습니다.
이는 기존의 Physics 2D → Layer Collision Matrix 설정을 무시하고,
Collider 개별 객체 단위에서 충돌 대상을 지정할 수 있는 기능입니다.

💡 간단히 말해, Collider 자신만의 충돌 필터를 설정할 수 있게 된 것이죠.


⚙️ 구성 요소 설명

항목 설명
Include Layers 충돌하고자 하는 레이어만 지정합니다. 지정된 레이어만 통과 가능
Exclude Layers 충돌을 막고 싶은 레이어를 명시합니다. 포함보다 우선 순위가 높습니다

🔁 동작 우선순위

Unity에서 충돌이 발생하려면 다음 조건이 모두 만족해야 합니다:

  1. 두 Collider의 Include Layers에 서로의 레이어가 포함되어 있어야 함
  2. 두 Collider의 Exclude Layers에 서로의 레이어가 없어야 함
  3. Physics 2D의 Layer Collision Matrix에서도 서로 충돌이 가능해야 함

❗ Layer Overrides 설정이 존재하면 Collision Matrix보다 우선 적용됩니다


🔧 문제 예시와 해결

문제 상황:

  • BoxCollider2D (IsTrigger ✅)가 있음
  • Rigidbody2D 있는 플레이어가 진입하는데도 OnTriggerEnter2D() 호출 안 됨
  • 레이어 충돌 매트릭스도 제대로 설정되어 있음

원인:

Include Layers와 Exclude Layers가 둘 다 Nothing으로 되어 있어
실제로 어떤 레이어와도 충돌하지 않도록 차단되어 있었음

해결:

  • Include Layers: Everything 또는 충돌 허용할 레이어 선택
  • Exclude Layers: Nothing으로 설정

✅ 권장 설정 예시

항목
IsTrigger
Include Layers Player (또는 Everything)
Exclude Layers Nothing
플레이어 쪽 Rigidbody2D + Collider2D, 태그: "Player"
 

💡 기억할 것

  • Include Layers = Nothing이면 → 아무와도 충돌 안 함
  • Exclude Layers = Everything이면 → 모든 충돌 차단됨
  • Layer Collision Matrix가 잘 되어 있어도, Override가 있으면 무시됨

📝 마무리

Collider가 이상하게 작동하지 않을 땐, 이제 Layer Overrides도 꼭 함께 확인하세요.
특히 씬에선 잘 되는데 실제 빌드에서 안 되는 경우, 이 설정이 숨겨진 원인일 수도 있습니다...

 

후..계속 이상하게 OnTriggerEnter2D를 했는대도 아무것도 나오지않아서..당황했다 이거는 절대 안까먹을듯 하다..include, Exclude 레이어 꼭 잘 확인하자.. 덕분에 새로운거 자세히 알았네ㅎㅎ..

반응형