no image
WIL - 본캠프 6주차(25.08.04~08.08)
1) 이번 주 가장 인상 깊었던 배움디자인 패턴 학습옵저버 패턴, 팩토리 패턴, 이벤트 버스, 상태 패턴(FSM 비교 포함), 커맨드 패턴, 전략 패턴, 중재자 패턴을 Unity 예시 코드로 구현하며 개념과 활용 방법을 정리했다.특히 상태 패턴과 FSM의 차이를 직접 코드로 확인하며, 상황별로 어떤 구조를 쓰는 것이 유지보수와 확장성 측면에서 유리한지 감을 잡았다.Unity Input System 이해 심화InputAction.CallbackContext.phase가 입력 상태 변화 시점에만 호출된다는 점을 이해했고, 지속적인 행동(달리기, 스태미나 소모)은 Update()와 상태 플래그로 처리해야 한다는 것을 알게 됐다.이를 1인칭 이동 시스템과 3인칭 오비트 카메라 전환 작업에 적용했다.플레이어 컨트..
2025.08.10
no image
내일배움캠프 30일차 TIL [Project_Up]
📝 TIL - 2025년 8월 8일 (금)🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 : 3D 서바이벌 프로젝트 개발플레이어 애니메이션 시스템 설계 및 구현Blend Tree 애니메이션 전환 테스트 및 디버깅PlayerAnimation, PlayerController 스크립트 수정Speed 값 기반으로 Idle, Walk, Run 상태 구분 구현Rigidbody.velocity 기반의 실제 이동속도 반영애니메이션 끊김 현상 지속적으로 디버깅🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 18:00 : 인벤토리 및 상태 시스템 검토UIInventory, ItemSlot, Equip, ItemObject 등 주요 시스템 확인 및 정리PlayerCondition, Condit..
2025.08.08
no image
Unity - 3D Survival Game(인벤토리 기능)
# 🧭 3D Survival Game (Unity Project)Unity를 사용하여 제작한 3D 생존 게임입니다. 플레이어는 자원을 수집하고, 적과 전투하며, 아이템을 활용해 생존을 이어갑니다. **불, 날씨, 사운드 등 환경 요소까지 구현하여 몰입감을 강화했습니다.**---## 📌 주요 기능### 🕹️ 플레이어 조작- `Input System` 기반 WASD 이동 + Space 점프- 마우스 카메라 회전 (`LookSensitivity`)- 체력, 허기, 스태미나 관리 (`PlayerCondition`)---### 🛠️ 자원 채집 & 전투 시스템- `EquipTool` 장비를 통해: - 자원 채집 (`Resource.cs`) - 적 NPC 공격 (`IDamageable`)- 공격 시 스..
2025.08.08
no image
내일배움캠프 29일차 TIL [인벤토리 시스템 구현]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 : 3D 서바이벌 프로젝트 진행 (인벤토리 시스템 구현 및 디버깅)ItemData 구조 점검[System.Serializable] 누락 문제 해결inventoryWindow.activeInHierarchy 활용한 UI 상태 확인 방법 학습🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 16:00 : 인벤토리 UI 개선 및 아이템 장착 시스템 구현아이템 클릭 → 정보 출력 → 버튼 기능 연결 흐름 정리장착된 무기에 따라 공격 애니메이션 동작하도록 연동16:00 ~ 17:00 : 챌린지반 강의 수강 (3D 장착 시스템 및 애니메이션 연동)17:00 ~ 18:00 : 인벤토리 기능 블로그용 정리, 유니티 12강 까지 마무리🍽️ 저녁..
2025.08.07
no image
Unity - Inventory 인벤토리 시스템 구현 정리
🎒 Unity 3D 서바이벌 게임 개발: 인벤토리 시스템 구현 정리 Unity로 서바이벌 게임을 만들면서 인벤토리 시스템을 구현해봤습니다. 생각보다 복잡했지만, 구현하면서 많이 배운 기능이라 정리해두면 좋을 것 같았습니다!✔️ 구현 목표아이템을 줍고 인벤토리에 추가하기인벤토리 창을 열고 닫기아이템을 클릭해서 정보 확인하기아이템 사용/버리기/장착/해제 기능 만들기장착 아이템에 따라 공격 애니메이션 실행하기🧩 1. 아이템 데이터 구조: ScriptableObject 활용아이템은 ScriptableObject로 데이터를 따로 관리하게 했습니다! 이렇게 하면 인스펙터에서 편하게 데이터를 만들고, 재활용할 수도 있어서 좋습니다![CreateAssetMenu(fileName = "Item", menuName =..
2025.08.07
no image
Unity - Unity의 TryGetComponent
🎯 Unity의 TryGetComponent 제대로 알기Unity 개발을 하다 보면 오브젝트의 컴포넌트를 가져와야 할 일이 자주 있습니다. 이때 흔히 사용하는 방식이 GetComponent()입니다. 하지만 이 방식은 컴포넌트가 존재하지 않을 경우 NullReferenceException을 발생시킬 수 있다는 단점이 있습니다.이런 위험을 피하고자 Unity에서는 보다 안전한 방식으로 컴포넌트를 가져올 수 있는 TryGetComponent() 메서드를 제공합니다. 이 글에서는 TryGetComponent의 기본 개념, 사용법, 실제 활용 예시, 그리고 GetComponent와의 차이점까지 상세히 정리해보겠습니다.📌 TryGetComponent란?TryGetComponent(out T component)..
2025.08.07
no image
내일배움캠프 28일차 TIL [Input System과 디자인 패턴 정리]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:00 : 팀원들과 나머지 인사 및 소통 시간10:00 ~ 10:30 : Unity 숙련 주차 발제 강의 수강10:30 ~ 11:00 : 팀원들과 추가 인사 및 친목 시간11:00 ~ 13:00 : 개인 프로젝트 3D_Survival 시작🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 16:00 : Unity 강의 수강 (Input System 개념 정리, InputAction 중심 학습)16:00 ~ 18:00 : 챌린지반 강의 수강 (디자인 패턴 전반 학습: 싱글톤, 옵저버, 팩토리, 이벤트버스, 상태패턴 vs FSM, 커맨드, 전략, 중재자)🍽️ 저녁시간18:00 ~ 19:00 : 저녁시간✅ 저녁19:00 ~ 21:00 : 디자..
2025.08.06
no image
DesignPattern - 중재자(Mediator) 패턴
🧩 Unity 디자인 패턴 - 중재자(Mediator) 패턴1. 중재자 패턴이란?중재자(Mediator) 패턴은 객체 간의 직접적인 소통을 피하고, 모든 통신을 중앙 관리자(중재자)를 통해 진행하도록 설계하는 패턴입니다."A와 B가 서로를 몰라도, 중재자에게만 말하면 필요한 연결이 자동으로 이뤄지는 구조"입니다.2. 언제 사용하나요?UI 요소나 시스템 간 상호작용이 많고 복잡할 때객체 간 결합도를 낮추고 싶을 때Observer 패턴보다 더 넓은 범위의 제어가 필요할 때3. 구조 구성요소역할설명IMediator중재자 인터페이스ConcreteMediator실제 이벤트를 중계하는 클래스Participant중재자에게 메시지를 보내는 구성원 객체4. Unity 예제: 버튼 누르면 여러 시스템에 명령 전파💬 S..
2025.08.06
반응형

1) 이번 주 가장 인상 깊었던 배움

  • 디자인 패턴 학습
    옵저버 패턴, 팩토리 패턴, 이벤트 버스, 상태 패턴(FSM 비교 포함), 커맨드 패턴, 전략 패턴, 중재자 패턴을 Unity 예시 코드로 구현하며 개념과 활용 방법을 정리했다.
    특히 상태 패턴과 FSM의 차이를 직접 코드로 확인하며, 상황별로 어떤 구조를 쓰는 것이 유지보수와 확장성 측면에서 유리한지 감을 잡았다.
  • Unity Input System 이해 심화
    InputAction.CallbackContext.phase가 입력 상태 변화 시점에만 호출된다는 점을 이해했고, 지속적인 행동(달리기, 스태미나 소모)은 Update()와 상태 플래그로 처리해야 한다는 것을 알게 됐다.
    이를 1인칭 이동 시스템과 3인칭 오비트 카메라 전환 작업에 적용했다.
  • 플레이어 컨트롤 시스템 개선
    카메라 피벗과 캐릭터 회전을 분리해 스트레이프 이동이 가능하도록 변경했고, 마우스로만 시야를 제어하도록 구현했다.
    1인칭 시점에서 3인칭 시점으로 전환하며 줌, 카메라 충돌 보정, 시야각 제한 등 다양한 기능을 적용했다.
  • 현대세계: 최후의 궁수 프로젝트 마무리
    팀 프로젝트의 마지막 주로, 스킬/업그레이드 시스템과 몬스터 스폰 매니저 구현을 마무리했다.
    각 기능을 통합하고 최종 버그 수정, UI/사운드 조정까지 완료하며 빌드 테스트까지 진행했다.
    프로젝트를 마치면서 협업 과정에서의 커뮤니케이션과 GitHub 브랜치 전략의 중요성을 다시 한번 느꼈다.

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

  • 디자인 패턴 적용의 난이도
    패턴 자체 개념은 이해했지만, Unity 환경에서 구체적으로 적용하려다 보니 GameObject, 컴포넌트 구조와 어떻게 결합해야 하는지가 쉽지 않았다.
    특히 상태 패턴과 FSM을 비교하며 설계하려니, 상태 전환 로직과 Update 흐름 관리에서 혼동이 있었다.
  • Input System의 한계 이해
    기존에는 OnRun 같은 콜백 메서드 안에서만 처리하려다 보니, Shift를 누른 순간 한 번만 실행되고 계속된 입력이 반영되지 않는 문제가 있었다.
    이 구조를 개선하려고 상태 플래그 + Update() 방식을 도입하는 과정에서 입력 상태 관리 코드를 전반적으로 수정해야 했다.
  • 1인칭 → 3인칭 전환 시 충돌
    카메라 전환 후에도 기존 1인칭 로직이 일부 남아 있어, 캐릭터가 이동할 때 카메라도 같이 회전해 버리는 문제가 있었다.
    이를 해결하려면 이동과 시야 제어를 완전히 분리해야 했고, 관련 코드를 리팩토링하는 데 시간이 꽤 걸렸다.
  • 팀 프로젝트 막바지 통합 작업
    현대세계: 최후의 궁수 프로젝트의 마지막 빌드 과정에서, UI와 사운드 타이밍이 어긋나거나 몬스터 스폰 타이밍이 잘못되는 문제가 발생했다.
    각자 구현한 기능을 통합하면서 충돌이 많았고, GitHub 브랜치 병합 후 테스트 과정에서 예상치 못한 버그를 여러 번 수정해야 했다.

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

  • 개념 이해보다 적용이 더 어렵다는 걸 다시 한번 느꼈다. 디자인 패턴이나 Input System 같은 기술은 책이나 문서로만 볼 때는 단순해 보이지만, 실제 프로젝트 상황에 맞게 녹여내는 과정에서 많은 변수가 생긴다.
  • 특히 Unity에서는 객체지향 설계와 게임 오브젝트 구조가 맞물려야 유지보수하기 좋은 코드가 된다는 걸 배웠다. 단순히 “작동하는 코드”가 아니라, 앞으로도 수정하기 편한 코드를 만드는 것이 중요하다고 생각하게 됐다.
  • Input System 문제를 해결하면서, 프레임 기반(Update) 처리와 이벤트 기반 처리의 차이를 명확히 구분하게 됐다. 덕분에 앞으로는 입력 구조를 설계할 때 이 두 가지 흐름을 처음부터 고려할 수 있을 것 같다.
  • 팀 프로젝트 막바지에는 기능을 붙이는 것보다 협업과 조율이 더 어렵다는 걸 실감했다. 기능을 합칠수록 충돌이 많아지고, 의도치 않은 버그가 생기는 과정에서 팀원과의 소통이 정말 중요했다.
  • 마지막 빌드를 마쳤을 때, 아쉬움도 있었지만 “이제는 이런 규모의 프로젝트를 처음부터 끝까지 완주할 수 있다”는 자신감이 생겼다.

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

이번 주는 새로운 기술을 배우는 것보다 배운 것을 실제로 녹여내고 마무리하는 주였다.
디자인 패턴, Input System, 카메라 전환 등 각각 따로 보면 어렵지 않아 보이지만,
실제 프로젝트 상황에 맞춰 적용하려니 예상치 못한 문제와 구조상의 제약이 많았다.

특히 팀 프로젝트를 완주하면서, 기능 구현보다 중요한 건 협업과 일정 관리라는 걸 다시 느꼈다.
코드 품질과 구조 설계를 미리 잘 잡아놓아야 막판 통합 과정에서 버그와 충돌을 최소화할 수 있다는 교훈도 얻었다.

다음 주에는 이번에 익힌 구조와 패턴을 개인 프로젝트에도 적극적으로 적용해,
기능뿐 아니라 유지보수성과 확장성을 갖춘 코드를 작성하는 습관을 들이고 싶다.
“빨리”보다 “오래” 가는 개발을 목표로 한 주를 보내겠다. 💪

 

 

 

📅이번주 TIL 목록

 

내일배움캠프 26일차 TIL [팀프로젝트(Archero)]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 11:00 : StageChangeTrigger 조건문 로직 디버깅11:00 ~ 12:30 : MonsterSpawnManager 개선 (스폰 포인트별로 몬스터 순차 소환 / 프리팹 랜덤)🍽️ 점심시간13:00 ~ 14:00 : 점심시

dev-jen.tistory.com

 

내일배움캠프 27일차 TIL [팀프로젝트 마무리 + 발표]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 :프로젝트 시연 영상 2종 촬영GitHub README 파일 최종 수정결과보고서 최종 점검프로젝트 기능 최종 확인 및 점검최종 발표 준비 진행🍽️ 점심시간13:00 ~ 14:

dev-jen.tistory.com

 

내일배움캠프 28일차 TIL [Input System과 디자인 패턴 정리]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:00 : 팀원들과 나머지 인사 및 소통 시간10:00 ~ 10:30 : Unity 숙련 주차 발제 강의 수강10:30 ~ 11:00 : 팀원들과 추가 인사 및 친목 시간11:00 ~ 13:00 : 개인 프로젝트 3D_

dev-jen.tistory.com

 

내일배움캠프 29일차 TIL [인벤토리 시스템 구현]

🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 : 3D 서바이벌 프로젝트 진행 (인벤토리 시스템 구현 및 디버깅)ItemData 구조 점검[System.Serializable] 누락 문제 해결inventoryWindow.activeInHierarchy 활용한 UI 상태 확

dev-jen.tistory.com

 

내일배움캠프 30일차 TIL [Project_Up]

📝 TIL - 2025년 8월 8일 (금)🗓️ 오늘 하루 일정✅ 오전09:00 ~ 13:00 : 3D 서바이벌 프로젝트 개발플레이어 애니메이션 시스템 설계 및 구현Blend Tree 애니메이션 전환 테스트 및 디버깅PlayerAnimation, Pla

dev-jen.tistory.com

 

📅이번주 Study 목록

 

Unity - Unity의 메인 카메라(Main Camera) & Projection

🎥 Unity의 메인 카메라(Main Camera)란?✅ 1. 기본 정의Unity 씬(Scene)에서 **플레이어가 보는 시점(Viewport)**을 결정하는 렌더링 카메라기본적으로 Main Camera 태그를 가진 GameObject로 자동 생성됨Camera.main

dev-jen.tistory.com

 

프로젝트 소개 - 「현대세계 최후의 궁수」

🎮 1. 게임 소개이번 프로젝트는 '궁수의 전설(Archero)'에서 영감을 받아 제작한 탑다운 슈팅 기반의 액션 게임입니다.현대 세계를 배경으로, 마지막 남은 궁수가 되어 적들을 물리치고 스테이지

dev-jen.tistory.com

 

Unity - Input System - InputAction

🎮 Unity Input System - InputAction 완전 정복1. 🧭 InputAction이란?InputAction은 Unity의 새 Input System에서 사용자의 입력을 추상화하여 "행동" 단위로 정의하는 구성 요소입니다.예를 들어 Jump, Move, Shoot 같은

dev-jen.tistory.com

 

DesignPattern - 옵저버(Observer) 패턴

🔭 Unity 디자인 패턴 - 옵저버(Observer) 패턴1. 옵저버 패턴이란?옵저버(Observer) 패턴은 어떤 객체의 상태가 변경될 때, 그 객체를 "구독"하고 있는 다른 객체들에게 자동으로 알림을 보내는 구조입

dev-jen.tistory.com

 

DesignPattern - 팩토리(Factory) 패턴

🏭 Unity 디자인 패턴 - 팩토리(Factory) 패턴1. 팩토리 패턴이란?팩토리(Factory) 패턴은 객체의 생성 과정을 감추고, 생성 책임을 별도의 팩토리 클래스에 위임하는 디자인 패턴입니다. Unity에서는 다

dev-jen.tistory.com

 

DesignPattern - 이벤트 버스(Event Bus) 패턴

📡 Unity 디자인 패턴 - 이벤트 버스(Event Bus) 패턴1. 이벤트 버스란?이벤트 버스(Event Bus) 패턴은 객체 간 직접적인 참조 없이, 전역 이벤트 허브를 통해 메시지를 주고받는 구조입니다."A가 B를 직

dev-jen.tistory.com

 

DesignPattern - 상태 패턴(State Pattern) vs FSM

🔄 Unity 디자인 패턴 - 상태 패턴(State Pattern) vs FSM1. 상태를 관리하는 두 가지 방식게임 캐릭터의 행동이나 UI의 전환처럼 상태에 따라 동작이 달라져야 할 때, 우리는 다음 두 가지 접근 방식을

dev-jen.tistory.com

 

DesignPattern - 커맨드(Command) 패턴

🎮 Unity 디자인 패턴 - 커맨드(Command) 패턴1. 커맨드 패턴이란?커맨드(Command) 패턴은 요청(행동)을 하나의 객체로 캡슐화하여,나중에 실행하거나취소하거나저장하거나여러 명령을 큐에 쌓아두었

dev-jen.tistory.com

 

DesignPattern - 전략(Strategy) 패턴

🧠 Unity 디자인 패턴 - 전략(Strategy) 패턴1. 전략 패턴이란?전략(Strategy) 패턴은 행동(알고리즘)을 객체로 분리하여, 런타임에 자유롭게 교체할 수 있도록 하는 패턴입니다."동일한 행동 인터페이

dev-jen.tistory.com

 

DesignPattern - 중재자(Mediator) 패턴

🧩 Unity 디자인 패턴 - 중재자(Mediator) 패턴1. 중재자 패턴이란?중재자(Mediator) 패턴은 객체 간의 직접적인 소통을 피하고, 모든 통신을 중앙 관리자(중재자)를 통해 진행하도록 설계하는 패턴입니

dev-jen.tistory.com

 

Unity - Unity의 TryGetComponent

🎯 Unity의 TryGetComponent 제대로 알기Unity 개발을 하다 보면 오브젝트의 컴포넌트를 가져와야 할 일이 자주 있습니다. 이때 흔히 사용하는 방식이 GetComponent()입니다. 하지만 이 방식은 컴포넌트가

dev-jen.tistory.com

 

Unity - Inventory 인벤토리 시스템 구현 정리

🎒 Unity 3D 서바이벌 게임 개발: 인벤토리 시스템 구현 정리 Unity로 서바이벌 게임을 만들면서 인벤토리 시스템을 구현해봤습니다. 생각보다 복잡했지만, 구현하면서 많이 배운 기능이라 정리해

dev-jen.tistory.com

 

Unity - 3D Survival Game(인벤토리 기능)

# 🧭 3D Survival Game (Unity Project)Unity를 사용하여 제작한 3D 생존 게임입니다. 플레이어는 자원을 수집하고, 적과 전투하며, 아이템을 활용해 생존을 이어갑니다. **불, 날씨, 사운드 등 환경 요소까

dev-jen.tistory.com

 

반응형
반응형

📝 TIL - 2025년 8월 8일 (금)

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 13:00 : 3D 서바이벌 프로젝트 개발
    • 플레이어 애니메이션 시스템 설계 및 구현
    • Blend Tree 애니메이션 전환 테스트 및 디버깅
    • PlayerAnimation, PlayerController 스크립트 수정
    • Speed 값 기반으로 Idle, Walk, Run 상태 구분 구현
    • Rigidbody.velocity 기반의 실제 이동속도 반영
    • 애니메이션 끊김 현상 지속적으로 디버깅

🍽️ 점심시간

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

✅ 오후

  • 14:00 ~ 18:00 : 인벤토리 및 상태 시스템 검토
    • UIInventory, ItemSlot, Equip, ItemObject 등 주요 시스템 확인 및 정리
    • PlayerCondition, Condition, UICondition 스크립트 정상 작동 확인
    • 상태 UI와 플레이어의 체력 연동 점검
    • FootSteps, DamageIndicator, Interaction 시스템 파일 구성 확인

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁식사

✅ 저녁

  • 19:00 ~ 21:00 : 챌린지반 강의 수강

✅ 오늘 학습 키워드

  • Rigidbody.velocity 기반 애니메이션 전환
  • Blend Tree의 전환 조건 및 루프 설정
  • Animator 파라미터 조정 (Speed, Grounded, Jump, FreeFall)
  • PlayerController에서 실제 움직임 계산 방식
  • 인벤토리 연동 구조 및 상태 UI 연동

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

 

Unity - 3D Survival Game(인벤토리 기능)

# 🧭 3D Survival Game (Unity Project)Unity를 사용하여 제작한 3D 생존 게임입니다. 플레이어는 자원을 수집하고, 적과 전투하며, 아이템을 활용해 생존을 이어갑니다. **불, 날씨, 사운드 등 환경 요소까

dev-jen.tistory.com

 

오늘은 플레이어의 이동 속도를 기반으로 애니메이션을 자연스럽게 전환해보려 했다. 기존에는 단순히 설정된 moveSpeed를 사용해 애니메이션 속도를 반영했지만, 실제로는 물리적으로 이동하는 velocity 값을 활용해야 보다 현실감 있는 전환이 가능하다는 것을 배웠다.

Speed 파라미터를 Rigidbody.velocity를 통해 계산하고, Idle, Walk, Run 상태로 구분하여 애니메이션 트리거를 조정했다. 하지만 여전히 끊김 현상이 남아있어 다른 방식(FSM, 단일 애니메이션 관리)도 고려하게 됐다.

또한 인벤토리 시스템, 상태 시스템이 잘 정리되어 있는지 확인하고 구조를 복습하면서 내가 어떤 구조로 코드를 짜왔는지 다시 점검할 수 있는 시간이었다.


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

1. 애니메이션 끊김 현상

  • 문제정의 : 걷기/뛰기 애니메이션이 자연스럽게 전환되지 않고 끊기는 문제가 발생
  • 시도 : Blend Tree 속도 조정, 루프타임 확인, Speed 값 변화 확인, 로그 출력
  • 해결방법 : Rigidbody.velocity에서 y축 제외한 수평 속도만 추출하여 사용
  • 새롭게 알게 된 점 : 물리 기반 움직임을 애니메이션에 반영할 땐 실제 움직이는 속도를 써야 자연스럽다
  • 다시 만나게 된다면 : FSM 패턴을 도입하거나 CrossFade 방식으로 스무스한 전환 시도해볼 것

📝 메모

  • 생각보다 애니메이션과 실제 속도의 연동이 까다롭다. 수치를 확인하며 디버깅하는 습관이 정말 중요하다는 걸 다시 느꼈다.
  • 문제를 계속 시도해보다가 “일단은 이렇게 해두자”라는 결론도 중요한 선택이다. 완벽보다 우선순위에 따라 유연하게 넘어가는 게 실력이다.
  • 저녁 강의는 집중해서 듣고, 내일은 스테미너 시스템이나 몬스터와의 상호작용 쪽도 해보면 좋을 것 같다!

 

반응형
반응형

# 🧭 3D Survival Game (Unity Project)

Unity를 사용하여 제작한 3D 생존 게임입니다.  
플레이어는 자원을 수집하고, 적과 전투하며, 아이템을 활용해 생존을 이어갑니다.  
**불, 날씨, 사운드 등 환경 요소까지 구현하여 몰입감을 강화했습니다.**


---

## 📌 주요 기능

### 🕹️ 플레이어 조작
- `Input System` 기반 WASD 이동 + Space 점프
- 마우스 카메라 회전 (`LookSensitivity`)
- 체력, 허기, 스태미나 관리 (`PlayerCondition`)

---

### 🛠️ 자원 채집 & 전투 시스템
- `EquipTool` 장비를 통해:
  - 자원 채집 (`Resource.cs`)
  - 적 NPC 공격 (`IDamageable`)
- 공격 시 스태미나 소모 (스태미나 부족 시 공격 불가)

---

### 🤖 적 AI (NPC)
- FSM 상태 기반 (Idle → Wandering → Attacking)
- `NavMeshAgent`로 자동 이동 및 경로 탐색
- 플레이어 감지 후 추적 + 공격
- 사망 시 아이템 드랍 (`ItemData.dropPrefab`)

---

### 🎒 인벤토리 시스템

> **ScriptableObject 기반의 강력한 아이템/장비 관리 기능**

- `ItemData`를 ScriptableObject로 설계 (이름, 설명, 아이콘, 드랍 프리팹, 스탯 등 포함)
- 인벤토리 창(`UIInventory`)에서 다음 기능 제공:
  - ✅ **아이템 획득** (중복 시 스택, 최대 수량 초과 시 드랍)
  - ✅ **아이템 장비/해제** (장비형: `equipPrefab` 연결)
  - ✅ **아이템 사용** (소모형: 체력/허기 회복 등)
  - ✅ **아이템 버리기** (지정 위치에 드랍)
  - ✅ **선택 아이템 정보창** (이름, 설명, 스탯 등 표시)
- `ItemSlot.cs` 기반의 슬롯 UI로 정리됨

---

### 🔥 환경 시스템

#### 🌙 낮/밤 사이클 (`DayNightCycle.cs`)
- 태양과 달의 위치, 색상, 세기 등을 시간에 따라 자동 조정
- `Gradient` + `AnimationCurve` 활용한 자연스러운 변화

#### 🔥 캠프파이어 데미지 (`CampFire.cs`)
- 불에 들어가면 `IDamageable`에게 지속 피해
- `OnTriggerEnter/Exit` + `InvokeRepeating()` 사용

#### 🎵 음악 존 (`MusicZone.cs`)
- 특정 구역에 들어가면 음악이 서서히 켜지고
- 나가면 다시 꺼지는 `Fade In/Out` 사운드 구현

---

### 👣 사운드 연출
- 플레이어가 일정 속도로 움직일 때마다
- 발걸음 소리(`FootSteps.cs`)를 무작위로 재생

---

## 📂 프로젝트 구조

```text
Assets/
├── 01_Scripts/                    → 전체 스크립트 폴더
│   ├── Character/                → 플레이어 컨트롤, 상태 시스템 등 핵심 로직
│   │   ├── CharacterManager.cs   → 싱글톤 플레이어 관리자
│   │   ├── Player.cs             → 입력 & 상태 연결
│   │   ├── PlayerController.cs   → 이동 및 점프 처리
│   │   ├── PlayerCondition.cs    → 체력, 허기, 스태미나 관리
│   │   └── Condition.cs          → 상태 수치 정의용 데이터 클래스
│   │
│   ├── Equipments/               → 장비 및 아이템 사용 관련
│   │   ├── Equip.cs              → 장비 착용
│   │   ├── EquipTool.cs          → 채집 및 공격 도구 처리
│   │   └── Equipment.cs          → 장착 아이템 프리팹 관리
│   │
│   ├── Environment/              → 환경 오브젝트 관련
│   │   ├── CampFire.cs           → 캠프파이어 데미지 처리
│   │   ├── DayNightCycle.cs      → 낮/밤 주기 시스템
│   │   └── MusicZone.cs          → 음악 재생 구역 (페이드 인/아웃)
│   │
│   ├── Interaction/              → 플레이어와 상호작용 가능한 오브젝트
│   │   ├── Interaction.cs        → Raycast 기반 상호작용 처리
│   │   └── Resource.cs           → 자원 채집 가능 오브젝트
│   │
│   ├── Items/                    → 아이템 데이터 및 관련 기능
│   │   ├── ItemData.cs           → ScriptableObject 기반 아이템 정의
│   │   ├── ItemObject.cs         → 인게임 드랍용 오브젝트
│   │   ├── ItemSlot.cs           → 인벤토리 슬롯 UI 처리
│   │   └── Equipment.cs          → 장비 프리팹과 연결되는 아이템 기능
│   │
│   ├── NPCs/                     → 적 AI 관련 스크립트
│   │   └── NPC.cs                → NavMesh 기반 상태 머신 AI (Wander, Attack)
│   │
│   └── UI/                       → 사용자 인터페이스 관련
│       ├── UICondition.cs        → 체력, 허기, 스태미나 UI 연동
│       ├── UIInventory.cs        → 인벤토리 UI 처리
│       └── DamageIndicator.cs    → 피격 시 화면 이펙트
'''












반응형

'Unity' 카테고리의 다른 글

Unity - TopDown 레이싱 방치형 RPG  (2) 2025.08.29
Unity - Project_Up  (3) 2025.08.13
Unity - Inventory 인벤토리 시스템 구현 정리  (3) 2025.08.07
Unity - Unity의 TryGetComponent  (1) 2025.08.07
Unity - Input System - InputAction  (6) 2025.08.06
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 13:00 : 3D 서바이벌 프로젝트 진행 (인벤토리 시스템 구현 및 디버깅)
    • ItemData 구조 점검
    • [System.Serializable] 누락 문제 해결
    • inventoryWindow.activeInHierarchy 활용한 UI 상태 확인 방법 학습

🍽️ 점심시간

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

✅ 오후

  • 14:00 ~ 16:00 : 인벤토리 UI 개선 및 아이템 장착 시스템 구현
    • 아이템 클릭 → 정보 출력 → 버튼 기능 연결 흐름 정리
    • 장착된 무기에 따라 공격 애니메이션 동작하도록 연동
  • 16:00 ~ 17:00 : 챌린지반 강의 수강 (3D 장착 시스템 및 애니메이션 연동)
  • 17:00 ~ 18:00 : 인벤토리 기능 블로그용 정리, 유니티 12강 까지 마무리

🍽️ 저녁시간

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

✅ 저녁

  • 19:00 ~ 21:00 : TIL 작성 및 인벤토리 정리 문서 마무리

✅ 오늘 학습 키워드

  • ScriptableObject를 활용한 아이템 데이터 구성
  • ItemDataConsumable 배열에 [System.Serializable] 속성 필요성
  • IInteractable 인터페이스 구현을 통한 상호작용 처리
  • TextMeshPro 오토 사이즈(Auto Size) 기능
  • inventoryWindow.activeInHierarchy를 통한 UI 활성 상태 판별
  • 인벤토리 슬롯 구성 및 아이템 스택 처리
  • InputAction으로 인벤토리 열고 닫기 구현
  • 아이템 장착 및 장착된 무기 애니메이션 트리거 연결
  • Non-convex MeshCollider 오류 해결 방법
  • UIInventory, ItemSlot, SelectedItemWindow 연동 흐름 이해

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

 

Unity - Unity의 TryGetComponent

🎯 Unity의 TryGetComponent 제대로 알기Unity 개발을 하다 보면 오브젝트의 컴포넌트를 가져와야 할 일이 자주 있습니다. 이때 흔히 사용하는 방식이 GetComponent()입니다. 하지만 이 방식은 컴포넌트가

dev-jen.tistory.com

 

Unity - Inventory 인벤토리 시스템 구현 정리

🎒 Unity 3D 서바이벌 게임 개발: 인벤토리 시스템 구현 정리 Unity로 서바이벌 게임을 만들면서 인벤토리 시스템을 구현해봤습니다. 생각보다 복잡했지만, 구현하면서 많이 배운 기능이라 정리해

dev-jen.tistory.com

 

오늘은 인벤토리 시스템을 본격적으로 구현했다. 처음에는 단순히 아이템을 담는 창을 만든다고 생각했지만, 막상 구현을 시작하니 생각보다 훨씬 많은 것들이 얽혀 있었다.

먼저 ScriptableObject를 활용해 아이템 데이터 구조를 설계했다. 이름, 설명, 아이콘, 스택 가능 여부뿐 아니라 소비형 아이템의 효과 정보까지 넣어야 했고, 장착 가능한 아이템은 장착용 프리팹까지 연결해줘야 했다. 여기서 내가 [System.Serializable]을 빼먹는 바람에 Inspector에서 ItemDataConsumable[]이 보이지 않는 일이 있었는데, 이걸 찾느라 꽤 시간을 썼다. 이처럼 사소한 부분 하나로 진행이 막히는 경험을 다시 했다.

아이템을 줍는 기능은 IInteractable 인터페이스를 통해 Raycast로 구현했다. 플레이어가 F 키를 누르면 아이템을 인벤토리에 추가하고, 슬롯에 아이콘과 수량이 표시되도록 구성했다. TextMeshPro 컴포넌트로 아이콘 수량을 보여주는 부분도 처음에는 연결이 안 되어 헤맸지만, 드래그로 연결해주니 잘 작동했다.

가장 어려웠던 건 인벤토리 UI를 구성하고, 아이템의 상태에 따라 버튼의 동작을 다르게 하는 부분이었다. 특히 장착 기능은 장착 여부에 따라 상태를 바꿔줘야 했고, 장착한 아이템의 애니메이션까지 연동해줘야 했다. Attack 트리거를 Animator에 추가하고, InputAction으로 공격 키를 눌렀을 때 무기 애니메이션이 나오도록 하는 과정을 구현했다. 이 과정에서 Non-convex MeshCollider 오류도 발생했는데, Equip된 무기에 Rigidbody가 달려있어서 생긴 문제였다. 이건 Rigidbody를 제거하거나 Kinematic으로 설정해서 해결했다.

이번 작업은 단순한 UI를 넘어서, 아이템의 속성과 상태에 따라 실제 월드와 상호작용하는 흐름까지 전반적으로 이해하고 구현해야 했던 시간이었다. 기능 하나를 넣기 위해 생각보다 많은 곳에서 서로 연결되어 있다는 걸 깨달았고, 그래서 더 어려웠던 것 같다.


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

1. Inspector에 ItemDataConsumable[] 배열이 안 보임

  • 문제정의
  • ItemData에 ItemDataConsumable[] consumables 필드를 추가했지만, Inspector 창에서 해당 배열이 나타나지 않음.
  • 시도
  • Unity를 재시작하거나 다시 컴파일해봤지만 여전히 Inspector에 보이지 않음.
  • 해결방법
  • ItemDataConsumable 클래스에 [System.Serializable] 어트리뷰트를 추가함으로써 해결됨.
  • 예시 코드
[System.Serializable]
public class ItemDataConsumable
{
    public ConsumableType type;
    public float value;
}
  • 새롭게 알게 된 점
  • 커스텀 클래스가 Inspector에 표시되기 위해서는 반드시 [System.Serializable]을 선언해줘야 한다는 것을 다시 한 번 확인함.
  • 다시 만나게 된다면
  • ScriptableObject에 배열이나 리스트를 사용할 때는 무조건 [System.Serializable]을 먼저 확인할 것!

2. 아이템이 획득되지 않고 사라지는 현상

  • 문제정의
  • 아이템을 획득했는데, 인벤토리에 들어오지 않고 그냥 사라져버림.
  • 시도
  • AddItem() 로직을 따라가면서 GetEmptySlot()이 null을 반환하는지 확인함.
  • 해결방법
  • 인벤토리 슬롯이 가득 차 있을 경우 ThrowItem() 메서드가 자동으로 실행되어 아이템이 땅에 떨어지게 되어 있었음. 하지만 땅에 떨어지는 위치가 카메라에서 잘 안 보여서 사라진 것처럼 느껴졌던 것.
  • 새롭게 알게 된 점
  • 예상치 못한 분기 처리(슬롯이 없을 경우 자동 드롭)도 충분히 인지하고 있어야 디버깅이 쉬워진다는 점을 배움.

3. Non-convex MeshCollider 오류

  • 문제정의"Non-convex MeshCollider with non-kinematic Rigidbody is no longer supported since Unity 5..."
  • 무기를 장착한 후 게임 실행 시 콘솔에 다음과 같은 에러 발생:
  • 시도
  • 메시가 잘못됐나 싶어 FBX 파일을 다시 임포트해보기도 했지만 여전히 오류 발생.
  • 해결방법Rigidbody 제거 또는 Kinematic 체크로 해결됨.
  • Equip_Sword(Clone) 안의 무기 모델에 Rigidbody가 붙어 있었고, Kinematic이 체크되어 있지 않아서 발생한 문제.
  • 새롭게 알게 된 점
  • Unity는 Non-convex MeshCollider에 대해 일반 Rigidbody를 허용하지 않으며, 반드시 Kinematic으로 설정하거나 Collider를 Convex로 바꿔야 한다는 점을 다시 확실히 알게 됨.

📝 메모

오늘은 정말 많은 걸 구현했지만, 그만큼 어려움도 많았던 하루였다. 처음에는 단순히 아이템을 저장하는 UI 창만 만들면 되는 줄 알았는데, 아이템을 줍는 것부터 시작해서, 장착하고 애니메이션까지 연결하는 흐름이 하나로 연결되어 있다는 걸 직접 부딪히며 체감했다.

특히 인벤토리는 보이는 것보다 훨씬 복잡한 구조였다. 아이템을 주울 때마다 슬롯을 확인하고, 겹칠 수 있는 아이템이면 스택을 쌓고, 장착 상태도 관리하고, UI도 갱신해야 하고… 구현하면서 머리가 지끈했지만, 그래도 하나씩 해결해가니까 재미도 있었던 것 같다.

중간에 오류나 디버깅이 많아서 멈추기도 했지만, 그 과정에서 Unity의 동작 원리를 더 깊이 이해할 수 있었고, 이제는 아이템을 클릭했을 때 어떤 동작이 이어지는지, 그리고 그걸 어떻게 연결해야 할지 감이 조금씩 잡히고 있다. 그만큼 또 한 걸음 나아간 하루였다고 생각한다. 오늘은 여기까지! 내일도 화이팅!!!!!

오늘 만든 인벤토리 시스템!

 

반응형
반응형

🎒 Unity 3D 서바이벌 게임 개발: 인벤토리 시스템 구현 정리

Unity로 서바이벌 게임을 만들면서 인벤토리 시스템을 구현해봤습니다. 생각보다 복잡했지만, 구현하면서 많이 배운 기능이라 정리해두면 좋을 것 같았습니다!


✔️ 구현 목표

  • 아이템을 줍고 인벤토리에 추가하기
  • 인벤토리 창을 열고 닫기
  • 아이템을 클릭해서 정보 확인하기
  • 아이템 사용/버리기/장착/해제 기능 만들기
  • 장착 아이템에 따라 공격 애니메이션 실행하기

🧩 1. 아이템 데이터 구조: ScriptableObject 활용

아이템은 ScriptableObject로 데이터를 따로 관리하게 했습니다! 이렇게 하면 인스펙터에서 편하게 데이터를 만들고, 재활용할 수도 있어서 좋습니다!

[CreateAssetMenu(fileName = "Item", menuName = "New Item")]
public class ItemData : ScriptableObject
{
    public string displayName;
    public string description;
    public ItemType type; // Equipable, Consumable, Resource
    public Sprite icon;
    public GameObject dropPrefab;

    public bool canStack;
    public int maxStackAmount;

    public ItemDataConsumable[] consumables; // 회복 효과 등
    public GameObject equipPrefab; // 장착 아이템일 경우 연결할 프리팹
}

💡 헷갈렸던 점: ItemDataConsumable이 Inspector에 안 보이길래 왜 그런가 했는데, [System.Serializable]을 안 붙여서 그런 거였어요. 이거 빠뜨리면 아무리 배열이어도 인스펙터에 안 뜨더라고요.


🖱️ 2. 아이템과 상호작용: Raycast + IInteractable

화면 가운데서 Ray를 쏴서 아이템을 감지하고, IInteractable 인터페이스를 통해 상호작용할 수 있도록 했습니다!

public interface IInteractable
{
    string GetInteractPrompt();
    void OnInteract();
}

아이템 오브젝트에 이 인터페이스를 붙이고, 플레이어가 가까이 가서 E 키를 누르면 OnInteract()가 실행되도록 구성했어요. 이때 아이템 데이터를 Player.itemData로 넘기고, 인벤토리에 추가됩니다.


🧭 3. 인벤토리 UI 구성

인벤토리는 다음과 같은 구조로 만들었습니다:

  • UIInventory.cs: 전체 인벤토리 관리 (슬롯 생성, 아이템 추가, 정보 표시 등)
  • ItemSlot.cs: 슬롯 한 칸에 대한 개별 관리 (아이콘, 수량 표시 등)
  • SelectedItemWindow: 아이템 이름, 설명, 스탯, 버튼들 표시
public void Set()
{
    icon.sprite = item.icon;
    quatityText.text = quantity > 1 ? quantity.ToString() : string.Empty;
}

아이템이 있는 경우 아이콘을 보여주고, 수량이 1보다 크면 숫자를 표시합니다.


➕ 4. 아이템 획득 로직

플레이어가 아이템을 획득하면 Player.itemData에 데이터가 저장되고, 인벤토리에서 AddItem() 메서드를 호출해서 슬롯에 추가됩니다!

public void AddItem()
{
    ItemData data = CharacterManager.Instance.Player.itemData;

    if (data.canStack)
    {
        ItemSlot slot = GetItemStack(data);
        if (slot != null)
        {
            slot.quantity++;
            UpdateUI();
            return;
        }
    }

    ItemSlot emptySlot = GetEmptySlot();
    if (emptySlot != null)
    {
        emptySlot.item = data;
        emptySlot.quantity = 1;
        UpdateUI();
        return;
    }

    // 슬롯이 꽉 찼다면, 아이템을 땅에 떨어뜨림
    ThrowItem(data);
}

🍽️ 5. 아이템 사용하기

아이템이 소비 아이템(예: 당근, 고기 등)일 경우, 버튼을 눌러서 사용할 수 있습니다!

public void OnUseButton()
{
    foreach (var effect in selectedItem.item.consumables)
    {
        switch (effect.type)
        {
            case ConsumableType.Health:
                condition.Heal(effect.value); break;
            case ConsumableType.Hunger:
                condition.Eat(effect.value); break;
        }
    }
    RemoveSelectedItem();
}

사용하고 나면 수량을 줄이고, 0개가 되면 슬롯을 비워주는 식으로 처리돼요!


🧹 6. 아이템 삭제 및 드롭

버튼을 눌러서 아이템을 버릴 수도 있어요. 이때는 아이템을 Instantiate() 해서 실제 땅에 떨어뜨리는 방식으로 처리했습니다!

public void OnDropButton()
{
    ThrowItem(selectedItem.item);
    RemoveSelectedItem();
}

처음엔 그냥 리스트에서만 지우면 끝인 줄 알았는데, 직접 프리팹을 땅에 생성해야 눈에도 보이고 다시 주울 수도 있겠더라고요.


📌 7. 인벤토리 열고 닫기 (InputSystem)

새로운 InputSystem을 이용해서 Tab 키(또는 설정한 키)로 인벤토리를 열고 닫을 수 있어요.

public void OnInventoryButton(InputAction.CallbackContext context)
{
    if (context.phase == InputActionPhase.Started)
    {
        inventory?.Invoke();
        ToggleCursor();
    }
}

ToggleCursor()도 함께 써서 인벤토리를 열 때는 마우스가 보이도록 설정했어요. 이거 안 하면 클릭이 안 되더라고요!

 

🔁 8. 선택한 아이템 처리 로직

아이템 슬롯을 클릭하면 해당 아이템이 선택되고, 우측 정보창에 이름/설명/스탯이 표시돼요. 이때 어떤 아이템을 선택 중인지 저장해두는 selectedItemIndex, selectedItem도 함께 관리해줘야 해요.

public void SelectItem(int index)
{
    selectedItemIndex = index;
    selectedItem = slots[index];
    UpdateSelectedItemUI();
}

처음에는 NullReferenceException 오류가 났었는데, 알고 보니 선택한 슬롯에 아이템이 없는데 접근하려고 해서 그랬어요. 꼭 조건 체크도 같이 해줘야 해요!


✅ 마무리하며

처음에는 생각보다 구현할 게 많아서 막막했는데, 하나씩 만들어가다 보니까 점점 구조가 잡히더라고요. 특히 ScriptableObjectInputSystem을 잘 활용하면 유지보수도 편하고, UI도 깔끔하게 정리할 수 있었습니다!

 

스파르타 코딩클럽에서 배운 내용인데 기록을 안해놓으면 까먹을거 같아서 작성해요!

실행화면입니다!

 

반응형
반응형

🎯 Unity의 TryGetComponent 제대로 알기

Unity 개발을 하다 보면 오브젝트의 컴포넌트를 가져와야 할 일이 자주 있습니다. 이때 흔히 사용하는 방식이 GetComponent<T>()입니다. 하지만 이 방식은 컴포넌트가 존재하지 않을 경우 NullReferenceException을 발생시킬 수 있다는 단점이 있습니다.

이런 위험을 피하고자 Unity에서는 보다 안전한 방식으로 컴포넌트를 가져올 수 있는 TryGetComponent<T>() 메서드를 제공합니다. 이 글에서는 TryGetComponent의 기본 개념, 사용법, 실제 활용 예시, 그리고 GetComponent와의 차이점까지 상세히 정리해보겠습니다.


📌 TryGetComponent란?

TryGetComponent<T>(out T component)는 특정 컴포넌트가 현재 GameObject에 존재할 경우 해당 컴포넌트를 안전하게 가져오는 메서드입니다. 존재하지 않을 경우 false를 반환하고, 컴포넌트를 반환하지 않기 때문에 예외가 발생하지 않습니다.

✅ 문법

public bool TryGetComponent<T>(out T component) where T : Component;
  • T : 가져오려는 컴포넌트 타입 (예: Rigidbody, Collider, Animator, 사용자 정의 컴포넌트 등)
  • component : 컴포넌트를 담을 out 매개변수
  • 리턴값 : 해당 컴포넌트가 존재하면 true, 없으면 false

🔍 왜 TryGetComponent를 써야 하나요?

기존의 GetComponent는 다음과 같은 단점이 있습니다:

Rigidbody rb = GetComponent<Rigidbody>();
rb.AddForce(Vector3.up * 10f); // Rigidbody가 없으면 NullReferenceException!

이 코드에서 Rigidbody가 붙어있지 않다면 NullReferenceException이 발생합니다. 이를 방지하려면 다음과 같이 조건문을 넣어야 하죠:

Rigidbody rb = GetComponent<Rigidbody>();
if (rb != null)
{
    rb.AddForce(Vector3.up * 10f);
}

하지만 TryGetComponent를 사용하면 이런 코드를 더 깔끔하고 안전하게 작성할 수 있습니다:

if (TryGetComponent<Rigidbody>(out Rigidbody rb))
{
    rb.AddForce(Vector3.up * 10f);
}
  • 장점: 예외 처리 필요 없음
  • 성능: 내부적으로 GetComponent보다 성능이 약간 더 나은 것으로 알려져 있음 (Unity 공식 문서 기준)
  • 가독성: 조건문 안에서 바로 사용할 수 있어 코드가 간결해짐

💡 실전 예제

🎯 예제 1: 총알이 적에게 부딪혔을 때 데미지 주기

private void OnTriggerEnter(Collider other)
{
    if (other.TryGetComponent<Enemy>(out Enemy enemy))
    {
        enemy.TakeDamage(10f);
        Destroy(gameObject); // 총알 삭제
    }
}

총알이 부딪힌 오브젝트가 Enemy 컴포넌트를 가지고 있다면 데미지를 주고, 총알은 파괴합니다. 만약 적이 아닌 오브젝트라면 아무 일도 일어나지 않습니다.

🎯 예제 2: 인터랙션 가능한 오브젝트 찾기

private void Interact(GameObject target)
{
    if (target.TryGetComponent<IInteractable>(out IInteractable interactable))
    {
        interactable.Interact();
    }
}

IInteractable 인터페이스를 구현한 오브젝트와만 상호작용하도록 처리할 수 있습니다.


🔄 GetComponent vs TryGetComponent

항목 GetComponent<T>() TryGetComponent<T>(out T)
반환값 컴포넌트 객체 또는 null true 또는 false
예외 처리 null 체크 필요 예외 없음
성능 약간 느릴 수 있음 약간 더 효율적
코드 가독성 길어질 수 있음 간결하고 안전함
 

🧠 마무리하며

TryGetComponent는 Unity 개발에서 보다 안전하고 깔끔한 코드를 작성하는 데 매우 유용한 도구입니다. 특히 충돌 처리, 상호작용, 조건부 로직 등에서 널 예외를 방지하고 코드를 단순하게 만들어 줍니다.

앞으로 GetComponent 대신 TryGetComponent를 기본으로 사용하는 습관을 들여보세요. 실수도 줄고, 유지보수도 쉬워질 것입니다!

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 10:00 : 팀원들과 나머지 인사 및 소통 시간
  • 10:00 ~ 10:30 : Unity 숙련 주차 발제 강의 수강
  • 10:30 ~ 11:00 : 팀원들과 추가 인사 및 친목 시간
  • 11:00 ~ 13:00 : 개인 프로젝트 3D_Survival 시작

🍽️ 점심시간

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

✅ 오후

  • 14:00 ~ 16:00 : Unity 강의 수강 (Input System 개념 정리, InputAction 중심 학습)
  • 16:00 ~ 18:00 : 챌린지반 강의 수강 (디자인 패턴 전반 학습: 싱글톤, 옵저버, 팩토리, 이벤트버스, 상태패턴 vs FSM, 커맨드, 전략, 중재자)

🍽️ 저녁시간

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

✅ 저녁

  • 19:00 ~ 21:00 : 디자인 패턴 블로그 시리즈 정리 (7개 패턴) 및 TIL 작성

✅ 오늘 학습 키워드

 

Unity - Input System - InputAction

🎮 Unity Input System - InputAction 완전 정복1. 🧭 InputAction이란?InputAction은 Unity의 새 Input System에서 사용자의 입력을 추상화하여 "행동" 단위로 정의하는 구성 요소입니다.예를 들어 Jump, Move, Shoot 같은

dev-jen.tistory.com

 

DesignPattern - 옵저버(Observer) 패턴

🔭 Unity 디자인 패턴 - 옵저버(Observer) 패턴1. 옵저버 패턴이란?옵저버(Observer) 패턴은 어떤 객체의 상태가 변경될 때, 그 객체를 "구독"하고 있는 다른 객체들에게 자동으로 알림을 보내는 구조입

dev-jen.tistory.com

 

DesignPattern - 팩토리(Factory) 패턴

🏭 Unity 디자인 패턴 - 팩토리(Factory) 패턴1. 팩토리 패턴이란?팩토리(Factory) 패턴은 객체의 생성 과정을 감추고, 생성 책임을 별도의 팩토리 클래스에 위임하는 디자인 패턴입니다. Unity에서는 다

dev-jen.tistory.com

 

DesignPattern - 이벤트 버스(Event Bus) 패턴

📡 Unity 디자인 패턴 - 이벤트 버스(Event Bus) 패턴1. 이벤트 버스란?이벤트 버스(Event Bus) 패턴은 객체 간 직접적인 참조 없이, 전역 이벤트 허브를 통해 메시지를 주고받는 구조입니다."A가 B를 직

dev-jen.tistory.com

 

DesignPattern - 상태 패턴(State Pattern) vs FSM

🔄 Unity 디자인 패턴 - 상태 패턴(State Pattern) vs FSM1. 상태를 관리하는 두 가지 방식게임 캐릭터의 행동이나 UI의 전환처럼 상태에 따라 동작이 달라져야 할 때, 우리는 다음 두 가지 접근 방식을

dev-jen.tistory.com

 

DesignPattern - 커맨드(Command) 패턴

🎮 Unity 디자인 패턴 - 커맨드(Command) 패턴1. 커맨드 패턴이란?커맨드(Command) 패턴은 요청(행동)을 하나의 객체로 캡슐화하여,나중에 실행하거나취소하거나저장하거나여러 명령을 큐에 쌓아두었

dev-jen.tistory.com

 

DesignPattern - 전략(Strategy) 패턴

🧠 Unity 디자인 패턴 - 전략(Strategy) 패턴1. 전략 패턴이란?전략(Strategy) 패턴은 행동(알고리즘)을 객체로 분리하여, 런타임에 자유롭게 교체할 수 있도록 하는 패턴입니다."동일한 행동 인터페이

dev-jen.tistory.com

 

DesignPattern - 중재자(Mediator) 패턴

🧩 Unity 디자인 패턴 - 중재자(Mediator) 패턴1. 중재자 패턴이란?중재자(Mediator) 패턴은 객체 간의 직접적인 소통을 피하고, 모든 통신을 중앙 관리자(중재자)를 통해 진행하도록 설계하는 패턴입니

dev-jen.tistory.com

  • Unity Input System
  • InputAction (Button, Value, Pass-through, CallbackContext, ReadValue<T>)
  • PlayerInput 컴포넌트 및 이벤트 연동 방식
  • 디자인 패턴 전반 정리
    • 싱글톤 (Singleton)
    • 옵저버 (Observer)
    • 팩토리 (Factory)
    • 이벤트 버스 (Event Bus)
    • 상태 패턴 vs FSM
    • 커맨드 패턴 (Command)
    • 전략 패턴 (Strategy)
    • 중재자 패턴 (Mediator)

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

오늘은 Unity에서 사용되는 새 Input System의 구조를 학습했다. 특히 InputAction을 중심으로 Button/Value/PassThrough 타입의 차이, CallbackContext에서 phase와 ReadValue 사용법 등을 체계적으로 정리했다. 기존 방식보다 훨씬 명확하고 유연하다는 장점을 느꼈고, 실제 코드를 작성하며 구조를 내 것으로 만드는 시간이 되었다.

오후에는 챌린지반 강의에서 총 7가지 디자인 패턴을 한 번에 정리했다. 패턴들이 단순히 '이름'이 아니라 해결하고자 하는 문제의 본질에 맞게 탄생한 구조적 설계라는 점이 인상 깊었다. 특히 FSM vs 상태 패턴의 비교를 통해 OOP 설계가 필요한 상황과 단순 FSM의 한계를 실감했고, 중재자 패턴은 시스템 복잡도를 얼마나 효율적으로 줄여주는지 체감할 수 있었다.

학습 후엔 각 패턴을 Unity 실습 예제와 함께 블로그에 정리했다.


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

❌ 1. Input System에서 InputActionContext phase 처리 헷갈림

  • 문제정의: 버튼 입력이 눌릴 때만 동작해야 하는데 performed와 started를 혼동
  • 시도: 로그 찍으며 phase 출력해보기
  • 해결 방법: started는 누른 순간, performed는 완료된 시점이라는 것을 확인
  • 새롭게 알게 된 점: phase 흐름을 통해 더 섬세한 입력 제어가 가능함
  • 다시 만나게 된다면: phase 조건 분기를 정확히 구조화해서 사용

📝 메모

  • 디자인 패턴을 단순히 “외워야 할 것”이 아니라 “문제를 해결하기 위한 구조화된 사고방식”으로 받아들이자
  • 패턴마다 “왜 필요한가” → “어떤 상황에서 유리한가” 를 먼저 생각하고 구조를 외우는 것보다 훨씬 깊이 있게 이해된다
  • Input System도 단순히 코딩이 아니라 사용자 입력을 어떻게 구조적으로 다룰 것인가에 대한 설계의 영역이라는 것을 새삼 느꼈다

오늘 하루 정말 많은 디자인 패턴을 배웠다.. 아직 실제로 사용하지는 못해봤지만 하나씩 천천히 잘 배워보자!

내일도 화이팅!!!


반응형
반응형

🧩 Unity 디자인 패턴 - 중재자(Mediator) 패턴

1. 중재자 패턴이란?

중재자(Mediator) 패턴은 객체 간의 직접적인 소통을 피하고, 모든 통신을 중앙 관리자(중재자)를 통해 진행하도록 설계하는 패턴입니다.

"A와 B가 서로를 몰라도, 중재자에게만 말하면 필요한 연결이 자동으로 이뤄지는 구조"입니다.


2. 언제 사용하나요?

  • UI 요소나 시스템 간 상호작용이 많고 복잡할 때
  • 객체 간 결합도를 낮추고 싶을 때
  • Observer 패턴보다 더 넓은 범위의 제어가 필요할 때

3. 구조 구성요소

역할 설명
IMediator 중재자 인터페이스
ConcreteMediator 실제 이벤트를 중계하는 클래스
Participant 중재자에게 메시지를 보내는 구성원 객체

4. Unity 예제: 버튼 누르면 여러 시스템에 명령 전파

💬 Step 1: IMediator 인터페이스

public interface IMediator
{
    void Notify(string eventKey, object data = null);
}

🧠 Step 2: ConcreteMediator 클래스

using System;
using System.Collections.Generic;

public class GameMediator : IMediator
{
    private Dictionary<string, Action<object>> listeners = new();

    public void Register(string eventKey, Action<object> callback)
    {
        if (!listeners.ContainsKey(eventKey))
            listeners[eventKey] = delegate { };

        listeners[eventKey] += callback;
    }

    public void Unregister(string eventKey, Action<object> callback)
    {
        if (listeners.ContainsKey(eventKey))
            listeners[eventKey] -= callback;
    }

    public void Notify(string eventKey, object data = null)
    {
        if (listeners.TryGetValue(eventKey, out var callback))
            callback?.Invoke(data);
    }
}

📦 Step 3: MediatorProvider (싱글톤 등록소)

public static class MediatorProvider
{
    public static GameMediator Mediator = new();
}

🧱 Step 4: Button 클릭 → 중재자에게 알림

using UnityEngine;

public class UIButton : MonoBehaviour
{
    public void OnClick()
    {
        MediatorProvider.Mediator.Notify("PlayClicked", "게임 시작!");
    }
}

🖥️ Step 5: UIManager가 이벤트 수신

using UnityEngine;

public class UIManager : MonoBehaviour
{
    private void OnEnable()
    {
        MediatorProvider.Mediator.Register("PlayClicked", OnPlayClicked);
    }

    private void OnDisable()
    {
        MediatorProvider.Mediator.Unregister("PlayClicked", OnPlayClicked);
    }

    private void OnPlayClicked(object data)
    {
        Debug.Log($"UIManager 수신: {data}");
        // 예: 타이틀 화면 숨기기
    }
}

5. 정리 및 장단점

✅ 장점

  • 객체 간 직접 참조 없이 상호작용 가능 → 결합도 ↓
  • 동적으로 구독/해제 가능
  • 복잡한 시스템 간 통신 구조 단순화

❌ 단점

  • 모든 통신이 중재자를 거치기 때문에, 중재자가 비대해질 수 있음
  • 디버깅 시 흐름 추적이 어려워질 수 있음

✅ 마무리 한 줄 요약

중재자 패턴은 모든 객체가 서로를 몰라도, 하나의 창구만 알면 협력할 수 있는 설계로, 복잡한 시스템 구조를 깔끔하게 정리할 수 있는 강력한 도구입니다.

반응형