no image
내일배움캠프 50일차 TIL [최종 프로젝트 팀 빌딩]
🗓️ 오늘 하루 일정최종 프로젝트 팀 빌딩📝 메모같이 하고싶은 팀원들이 있는데 어떻게 진행이 될지를 모르겠다ㅠㅜㅜ 내일 아침에 다시 나머지 인원들을 정해준다고 하는데..뭔가 방식이..흠.. 매니저님들도 고심끝에 하신거일테니.. 뭐든지 모두가 만족할 수 있는 방법은 없는거 같다 내일 되어봐야 알지 않을까 싶다
2025.09.08
no image
내일배움캠프 49일차 TIL [팀프로젝트 - 3D_Squad_Swarm]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:30 : 리포지토리 스크립트/폴더 구조 점검, 파일 트리 추출 시도10:30 ~ 12:00 : 프로젝트 구조 스샷 정리 및 실제 구조 대비 표기 규칙 확정🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 16:00 : README 초안 뼈대 구성(게임소개, 플레이방법, Features, 설계&디자인패턴, 사용기술&시스템)16:00 ~ 18:00 : 스크립트 하나씩 확인하며 Features ↔ 시스템 ↔ 스크립트 매핑🍽️ 저녁시간18:00 ~ 19:00 : 저녁시간✅ 저녁19:00 ~ 21:00 : 피드백 반영(프로젝트 구조 오표기 교정), 섹션별 문구 다듬기 및 체크리스트화✅ 오늘 학습 키워드README 구조화프로젝트 폴더/스크립트 ..
2025.09.08
no image
Unity - 3D Squad Swarm (팀 프로젝트)
3D_Squad_Swarm — 상태머신으로 쌓아 올린 라운드형 좀비 액션작은 맵에서 플레이어(좀비) vs NPC가 빠르게 부딪히는 3D 라운드 액션.상태머신(FSM) 아키텍처, NavMesh AI, Stage·UI·Audio 매니저 계층으로 구성.캐릭터 전부 FSM으로 설계(플레이어·NPC·좀비)제한시간/감염도 게이지가 핵심 규칙StageConfig(SO)로 난이도·스폰 제어, UI는 상태 전환 파이프라인NavMesh + Obstacle로 길막을 네비 데이터에서 보장▶️ 플레이영상🕹️ 플레이방법실행하면 Intro → StageSelect → Game 순으로 진입제한시간 안에 적을 처치하여 감염도를 채우면 GameClear시간 초과는 TimeUP, 플레이어 사망은 GameOver일시정지는 Pause(예:..
2025.09.05
no image
내일배움캠프 48일차 TIL [팀프로젝트 - 3D_Squad_Swarm]
🗓️ 오늘 하루 일정✅ 오전10:00 ~ 12:00 : 팀 회의 & 개발 진행(스테이지/StageConfig, SO 값 정리, 스테이지 시작 시 플레이어 스폰 전략 확정)🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 15:30 : PlayerSpawner 정리(플레이어 + 카메라 프리팹 동시 생성, 메인 카메라 존재 시 프리팹 생략 로직 추가)15:30 ~ 16:00 : StageSpawner/StageManager 씬 가드 적용(홈 씬에서 스폰·NavMesh 등록 방지)16:00 ~ 18:00 : 게임 업계 취업 & 면접 준비 강의 수강🍽️ 저녁시간18:00 ~ 19:00 : 저녁시간✅ 저녁19:00 ~ 21:00 : 팀 머지 & 버그 수정(NPCFleeState NRE 해..
2025.09.04
no image
내일배움캠프 47일차 TIL [팀프로젝트 - 3D_Squad_Swarm]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:00 : 스테이지 흐름 재정의 (버튼 → StageManager.Stage1/2/3()), StageAPI/StageSceneManager 제거 방향 확정10:00 ~ 11:00 : StageConfig 리팩토링(스폰 규칙 정리, 프리팹 자급자족), StageSpawner 기본 루프 설계11:00 ~ 12:00 : 감염도 시스템 단순화└ SO(ScriptableStats)에 InfectionPoint 추가 → StatHandler로 읽고, 적 사망 시 StageManager.OnEnemyKilled(npc) → UIManager.getInfection(amount)로 일원화🍽️ 점심시간12:00 ~ 13:00 : 점심✅ 오후13:00 ~ 14:00 : 인..
2025.09.03
no image
내일배움캠프 46일차 TIL [팀프로젝트 - 3D_Squad_Swarm]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:00 : 스크립트 구조 점검 (StageSceneManager, StageManager, StageConfig 관계 확인)10:00 ~ 11:30 : 제너릭 싱글톤 구현 및 단순화 버전 리팩토링11:30 ~ 13:00 : 씬 전환 흐름(StageSceneManager → StageManager → StageStatBinder) 최종 정리🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 15:30 : StageConfig 수정 (sceneName + unitId→Stats 매핑)15:30 ~ 17:00 : StageManager 이벤트 발행 구조 리팩토링, StageStatBinder 늦스폰 대응 추가17:00 ~ 18:00 : 전체 흐..
2025.09.03
no image
내일배움캠프 45일차 TIL [팀프로젝트 - 3D_Squad_Swarm]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:00 : 개인시간10:00 ~ 10:20 : 개발 심화 발제10:20 ~ 13:00 : 팀 회의🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 18:00 : 스테이지 1·2·3 제작🍽️ 저녁시간18:00 ~ 19:00 : 저녁시간✅ 저녁19:00 ~ 20:00 : 개인 개발 시간20:00 ~ 21:00 : 팀 프로젝트 회의✅ 오늘 학습 키워드ScriptableObject 기반 StageConfig / StageStatsSetStageTier(1/2/3), ActorKind(Human/Vip/Hunter)StatsByTier → UnitStats 구조화(HP/ATK/MoveSpeed/APS)StageConfig ↔ StatsSet 분..
2025.09.01
no image
내일배움캠프 44일차 TIL [개인프로젝트 3D 방치형 RPG]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:30 : Unity 프로젝트 정리(README 구조/프로젝트 트리/트러블슈팅 초안)10:30 ~ 12:00 : 블로그용 글 편집(이미지/섹션 다듬기) + 파일 재생성 이슈 처리12:00 ~ 13:00 : 최종 점검 후 프로젝트 제출(13:00 이전 완료)🍽️ 점심시간13:00 ~ 14:00 : 점심✅ 오후14:00 ~ 15:00 : Squad Swarm 스테이지 범위/지표 합의(타이머·감염도·스폰 규칙)15:00 ~ 16:30 : StageConfig(SO) / StageCatalog(SO) 스키마 확정16:30 ~ 17:30 : StageManager ↔ SpawnDirector 인터페이스·이벤트버스(StageEvents/SpawnSignal) 정의🍽..
2025.08.29
반응형

🗓️ 오늘 하루 일정

  • 최종 프로젝트 팀 빌딩

📝 메모

같이 하고싶은 팀원들이 있는데 어떻게 진행이 될지를 모르겠다ㅠㅜㅜ 내일 아침에 다시 나머지 인원들을 정해준다고 하는데..뭔가 방식이..흠.. 매니저님들도 고심끝에 하신거일테니.. 뭐든지 모두가 만족할 수 있는 방법은 없는거 같다 내일 되어봐야 알지 않을까 싶다


반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 10:30 : 리포지토리 스크립트/폴더 구조 점검, 파일 트리 추출 시도
  • 10:30 ~ 12:00 : 프로젝트 구조 스샷 정리 및 실제 구조 대비 표기 규칙 확정

🍽️ 점심시간

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

✅ 오후

  • 14:00 ~ 16:00 : README 초안 뼈대 구성(게임소개, 플레이방법, Features, 설계&디자인패턴, 사용기술&시스템)
  • 16:00 ~ 18:00 : 스크립트 하나씩 확인하며 Features ↔ 시스템 ↔ 스크립트 매핑

🍽️ 저녁시간

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

✅ 저녁

  • 19:00 ~ 21:00 : 피드백 반영(프로젝트 구조 오표기 교정), 섹션별 문구 다듬기 및 체크리스트화

✅ 오늘 학습 키워드

  • README 구조화
  • 프로젝트 폴더/스크립트 정합성 검증
  • Features–System–Script 매핑 테이블
  • Git 기반 파일 리스트 추출

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

문서는 코드와 동기화될 때 가치가 있다. 오늘은 스크린샷/파일트리/실제 폴더를 교차 확인하며 README 섹션을 재정비했다. 핵심은 ① 프로젝트 구조를 있는 그대로 보여주고, ② 사용자 관점의 Features를 개발자 관점의 시스템/스크립트에 정확히 매핑하는 것. 이때 용어·경로·클래스명을 실제 코드 기준으로 통일해야 팀원이 혼동하지 않는다. 앞으로는 문서 수정 전에 자동/반자동 파일 리스트 추출로 검증 단계를 습관화한다.


반응형
반응형

3D_Squad_Swarm — 상태머신으로 쌓아 올린 라운드형 좀비 액션

작은 맵에서 플레이어(좀비) vs NPC가 빠르게 부딪히는 3D 라운드 액션.
상태머신(FSM) 아키텍처, NavMesh AI, Stage·UI·Audio 매니저 계층으로 구성.

  • 캐릭터 전부 FSM으로 설계(플레이어·NPC·좀비)
  • 제한시간/감염도 게이지가 핵심 규칙
  • StageConfig(SO)로 난이도·스폰 제어, UI는 상태 전환 파이프라인
  • NavMesh + Obstacle로 길막을 네비 데이터에서 보장

▶️ 플레이영상

🕹️ 플레이방법

  1. 실행하면 IntroStageSelectGame 순으로 진입
  2. 제한시간 안에 적을 처치하여 감염도를 채우면 GameClear
  3. 시간 초과는 TimeUP, 플레이어 사망은 GameOver
  4. 일시정지는 Pause(예: ESC)

입력 바인딩은 Unity Input System의 PlayerInput 에셋에서 관리.


✨ Features

  • 상태머신 기반 캐릭터 로직
    • 공통 FSM: StateMachine.cs
    • Player: PlayerStateMachine + PlayerIdle/Walk/Ground/Attack/Death
    • NPC: NPCBaseState, NPCAttackState (Idle/Chase/Flee/Death 포함)
    • Zombie(Follower/Charging): ZombieStateMachine + ZombieIdle/Follow/Chasing/Charge/Attack/Death/Rise
  • Stage 시스템 & 스폰
    • StageConfig(ScriptableObject) → StageManager + StageSpawner
    • 씬·스폰·타이머·네비 설정을 SO로 일괄 관리
  • UI 파이프라인
    • UIManager가 Intro/StageSelect/Game/Pause/GameOver/GameClear/TimeUP 전환
    • 타이머는 코루틴 핸들 보관으로 중복 실행 방지
  • 전투/인터랙션
    • IDamageable, Bullet, GunAimer, ForceReciever
    • 애니메이션 이벤트: AnimationEventForwarder, NPCAnimationEventForwarder
  • 오디오/카메라
    • AudioManager, BGMVolumeController, SoundEffect
    • CameraManager + CameraDeathEffect, CameraOcclusion

🧩 설계 & 디자인패턴

  • State Pattern(FSM): 각 도메인(플레이어/NPC/좀비)에 독립 FSM. Enter/Exit/Update 수명주기.
  • Singleton<T>: GameManager / StageManager / UIManager / AudioManager 등 전역 매니저 계층.
  • ScriptableObject 주입: StageConfig, ScriptableStats → 런타임에 StageManager/StatHandler가 적용.
  • Event-Driven: 스테이지 시작/종료/컷신 신호를 이벤트로 브로드캐스트.
  • NavMesh 중심 설계: 경로/차단을 네비 데이터로 일관되게 처리(Obstacle/Carving 포함).

🛠️ 사용기술 & 시스템

  • Unity(LTS), C#
  • NavMesh: NavMeshAgent, NavMeshObstacle(Carving), NavMesh 샘플링 스폰
  • Input System: PlayerInput 액션 맵
  • UGUI: Canvas/UI 화면 전환·게이지
  • Cinemachine(선택): 가상 카메라/우선도
  • Coroutines: 타이머·페이드·스폰 루프
  • ScriptableObject: 스테이지/스탯 파라미터화

📂 폴더 구조(요약, 실제 프로젝트 기준)

 
02. Scripts
├─ AnimationForwarder
│  ├─ AnimationEventForwarder.cs
│  └─ NPCAnimationEventForwarder.cs
│
├─ Base
│  ├─ StateMachine
│  │  └─ StateMachine.cs
│  ├─ Ui
│  │  └─ BaseUI.cs
│  └─ Zombie
│     └─ BaseZombie.cs
│
├─ Camera
│  ├─ CameraDeathEffect.cs
│  └─ CameraOcclusion.cs
│
├─ ForceReciever
│  └─ ForceReciever.cs
│
├─ Interface
│  └─ Attack
│     └─ IDamageable.cs
│
├─ Manager
│  ├─ Player
│  │  └─ PlayerManager.cs
│  ├─ Stage
│  │  └─ StageManager.cs
│  ├─ UI
│  │  └─ UIManager.cs
│  ├─ Util
│  │  ├─ AudioManager.cs
│  │  └─ CameraManager.cs
│  └─ Zombie
│     └─ ZombieManager.cs
│
├─ NPC
│  ├─ Gun
│  │  ├─ Bullet.cs
│  │  └─ GunAimer.cs
│  └─ StateMachin
│     ├─ NPCAttackState.cs
│     ├─ NPCBaseState.cs
│     ├─ NPCChaseState.cs
│     ├─ NPCDeathState.cs
│     ├─ NPCFleeState.cs
│     ├─ NPCGroundState.cs
│     ├─ NPCIdleState.cs
│     ├─ NPCStateMachine.cs
│     └─ NPCTest.cs
│
├─ Player
│  ├─ Anim
│  │  └─ PlayerAnimationData.cs
│  ├─ StateMachine
│  │  ├─ PlayerAttackState.cs
│  │  ├─ PlayerBaseState.cs
│  │  ├─ PlayerDeathState.cs
│  │  ├─ PlayerGroundState.cs
│  │  ├─ PlayerIdleState.cs
│  │  ├─ PlayerStateMachine.cs
│  │  └─ PlayerWalkState.cs
│  ├─ EnemyPointer.cs
│  ├─ Player.cs
│  └─ PlayerController.cs
│
├─ ScriptableObjects
│  └─ Stage
│     └─ StageConfig.cs
│
├─ Singleton
│  ├─ BGMVolumeController.cs
│  ├─ Singleton.cs
│  └─ SoundEffect.cs
│
├─ Spawner
│  ├─ Player
│  │  └─ PlayerSpawner.cs
│  └─ Stage
│     └─ StageSpawner.cs
│
├─ Stats
│  ├─ ScriptableStats.cs
│  └─ StatHandler.cs
│
├─ UI
│  ├─ Billboard
│  │  └─ Billboard.cs
│  ├─ Effect
│  │  └─ HoverEffect.cs
│  ├─ Game
│  │  ├─ GameClearUI.cs
│  │  ├─ GameOverSkipButton.cs
│  │  ├─ GameOverTimeline.cs
│  │  ├─ GameOverUI.cs
│  │  ├─ GameUI.cs
│  │  ├─ MoveArrow.cs
│  │  └─ MoveArrow1.cs
│  ├─ Handle
│  │  └─ HandleAnimationController.cs
│  ├─ Intro
│  │  ├─ IntroSkipButton.cs
│  │  ├─ IntroTimeline.cs
│  │  └─ IntroUI.cs
│  ├─ Stage
│  │  └─ StageSelectUI.cs
│  └─ Util
│     ├─ OptionUI.cs
│     ├─ PauseUI.cs
│     └─ TimeUPUI.cs
│
└─ Zombie
   ├─ Charging
   │  └─ ChargingZombie.cs
   └─ FollowerZombie
      ├─ FollowerZombie.cs
      └─ StateMachine
         ├─ ZombieAttackState.cs
         ├─ ZombieBaseState.cs
         ├─ ZombieChargeState.cs
         ├─ ZombieChasingState.cs
         ├─ ZombieDeathState.cs
         ├─ ZombieFollowState.cs
         ├─ ZombieIdleState.cs
         ├─ ZombieRiseState.cs
         └─ ZombieStateMachine.cs

🧯 트러블슈팅

 

🎮 개발자, 기획자

개발자 : 이재은, 박정현, 박민제, 임성준

기획자 :김노아, 황의영

🎮 개발기간 

개발기간 :(2025.09.01~09.05)

게임 시작 Scene
스테이지 Scene

나머지는 영상에 나와있습니다!

 

🧯 Troubleshooting

 

 

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 10:00 ~ 12:00 : 팀 회의 & 개발 진행
  • (스테이지/StageConfig, SO 값 정리, 스테이지 시작 시 플레이어 스폰 전략 확정)

🍽️ 점심시간

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

✅ 오후

  • 14:00 ~ 15:30 : PlayerSpawner 정리
  • (플레이어 + 카메라 프리팹 동시 생성, 메인 카메라 존재 시 프리팹 생략 로직 추가)
  • 15:30 ~ 16:00 : StageSpawner/StageManager 씬 가드 적용
  • (홈 씬에서 스폰·NavMesh 등록 방지)
  • 16:00 ~ 18:00 : 게임 업계 취업 & 면접 준비 강의 수강

🍽️ 저녁시간

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

✅ 저녁

  • 19:00 ~ 21:00 : 팀 머지 & 버그 수정
  • (NPCFleeState NRE 해결, NavMeshObstacle로 벽 관통 해결, UI 타이머 코루틴 핸들 도입)

✅ 오늘 학습 키워드

  • 코루틴 핸들(변수)로 시작/정지 관리
  • NavMeshObstacle Carve 운용
  • StageSpawner 씬 매칭 가드
  • PlayerManager 등록 타이밍(초기화 순서)
  • NRE 디버깅 패턴(로그 → 가드 → 폴백)

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

  • 코루틴 핸들 관리: StartCoroutine()의 반환값을 Coroutine 변수로 보관하고, 같은 핸들로 StopCoroutine() 해야 실제로 멈춘다. 새 Enumerator를 만들어 멈추면 동작하지 않는다.
  • NavMeshObstacle: 움직이거나 닫히는 오브젝트(문/박스)는 Obstacle + carving으로 네브메시에 실시간 구멍을 내면 벽 관통을 방지할 수 있다. 정적 벽은 베이크 설정/Modifier로 차단.
  • 씬 가드: 스포너가 “현재 활성 씬 == 스테이지 씬”일 때만 동작하도록 가드하면 홈 씬에서의 잘못된 스폰과 NavMesh 등록을 차단할 수 있다.
  • 초기화 순서: 매니저가 먼저 Awake되고 플레이어가 나중에 Instantiate될 수 있다. 플레이어가 스스로 PlayerManager에 등록하거나, 상태 진입 시 널 가드로 방어해야 안전하다.
  • NRE 처리 루틴: (1) 로그로 null 위치 정확히 출력 → (2) 필수 참조 가드 → (3) 합리적 폴백값/동작 제공. 이 순서를 습관화하자.

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

1. UI 타이머가 겹쳐서 두 배로 줄어듦

  • 문제정의: 죽고 재시작 시 카운트다운이 중복 실행.
  • 내가 한 시도: StopCoroutine(Countdown()) 사용 → 멈추지 않음.
  • 해결 방법:
  •  
  • 새롭게 알게 된 점: 코루틴은 핸들로 정지해야 한다.
  • 다시 만나면: 시작 전에 항상 StopTimer() 호출 → 중복 방지.
private Coroutine _timer; public void StartTimer(float t) { StopTimer(); remainingTime = t; _timer = StartCoroutine(TimerLoop()); }
public void StopTimer() { if (_timer != null) { StopCoroutine(_timer); _timer = null; } }

2. 홈 씬으로 돌아와도 NPC/네브가 남는 현상

  • 문제정의: 홈 로드 후에도 스테이지 스폰/네브 등록이 수행됨.
  • 해결 방법: 스포너/매니저에 씬 이름 매칭 가드.
  •  
  • 새롭게 알게 된 점: DDOL + sceneLoaded 콜백 조합은 항상 현재 씬 검사가 필요.
  • 다시 만나면: 이벤트 발사/구독부와 OnEnable 즉시 실행부 모두에 가드.
using UnityEngine.SceneManagement; if (SceneManager.GetActiveScene().name != cfg.sceneName) return;

3. NPCFleeState에서 NRE

  • 문제정의: Flee.Enter()에서 PlayerManager.player가 null.
  • 해결 방법: 플레이어가 자기 자신을 매니저에 등록 + 상태에서 널 가드.
  •  
  • 새롭게 알게 된 점: 플레이어 Instantiate 타이밍과 매니저 초기화 순서가 엇갈릴 수 있다.
  • 다시 만나면: “소유자 등록”을 생성 시점에 확실히 하고, 상태 진입부에 방어 로직.
// Player.Awake 마지막 
if (PlayerManager.Instance) PlayerManager.Instance.player = this; 
// Flee.Enter var stats = PlayerManager.Instance?.player?.Stats; stateMachine.Npc.agent.speed = stats ? stats.GetStat(StatType.Speed) : 3f;

4. NavMesh에서 벽을 뚫고 지나감

  • 문제정의: 에이전트가 벽을 스치며 관통.
  • 해결 방법: NavMeshObstacle(carving) 적용, 정적 벽은 베이크 설정/Modifier로 Not Walkable 처리.
  • 새롭게 알게 된 점: 물리 콜라이더만으론 부족, 네브메시 자체를 막아야 한다.
  • 다시 만나면: 얇은 틈은 Voxel Size/Agent Radius/Step Height로 보정.

📝 메모

오늘은 회의-머지-버그 수정으로 꽉 찬 하루였다. 특히 NRE와 씬 가드, 코루틴 중복 같은 “초기화·수명주기 문제”를 다시 정리할 수 있어서 좋았다. 작은 방어 코드가 큰 사고를 막는다. 내일은 스폰 룰 튜닝과 UI 타이머 연동을 좀 더 깔끔하게 다듬어 보자. 꾸준히 한 걸음씩! 💪


 

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 10:00 : 스테이지 흐름 재정의 (버튼 → StageManager.Stage1/2/3()), StageAPI/StageSceneManager 제거 방향 확정
  • 10:00 ~ 11:00 : StageConfig 리팩토링(스폰 규칙 정리, 프리팹 자급자족), StageSpawner 기본 루프 설계
  • 11:00 ~ 12:00 : 감염도 시스템 단순화
  • └ SO(ScriptableStats)에 InfectionPoint 추가 → StatHandler로 읽고, 적 사망 시 StageManager.OnEnemyKilled(npc) → UIManager.getInfection(amount)로 일원화

🍽️ 점심시간

  • 12:00 ~ 13:00 : 점심

✅ 오후

  • 13:00 ~ 14:00 : 인트로 종료 NRE 디버깅
  • └ 씬 로드 전 UI 접근 제거, OnStageStarted 시점으로 UI 전환 이동, 널가드 추가
  • 14:00 ~ 15:00 : 타겟팅 단순화
  • └ NPC.Update()에서 매 프레임 Player/좀비 중 최단거리 타겟 갱신, NPCChaseState 널 가드
  • 15:00 ~ 16:00 : 스포너 안정화
  • └ 디스폰 시 IndexOutOfRange 수정(셧다운 플래그, 인덱스 캡처/범위 가드)
  • 16:00 ~ 18:00 : JSON/엑셀 데이터 연동 강의 수강 (2시간)

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁

✅ 저녁

  • 19:00 ~ 21:00 : 팀 회의└ 네브메시 기반 스폰 설계(NavMeshData 등록, AddNavMeshData + SamplePosition/삼각형 샘플) 및 navSampleMaxDistance 사용 기준 합의
  • └ VIP 사망 보상: PlayerManager.PlayerSpeedUp() 로직 확정(싱글톤 초기화/널가드 포함)
  • └ 스폰 포인트 StageConfig 단일 관리 확정(씬 트랜스폼 참조 제거 → 좌표/네브 기반)

✅ 오늘 학습 키워드

StageManager

StageConfig

StageSpawner

ScriptableStats.InfectionPoint

UIManager.getInfection

NavMeshData

NavMesh.SamplePosition

최근접 타겟팅 · 코루틴/디스폰 가드 · 싱글톤 초기화(base.Awake())


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

  • 스테이지 로딩은 한 곳(StageManager)에서만: 버튼 → Stage1/2/3()로 단순화. 로드 완료 신호는 OnStageStarted.
  • 스폰은 SO 한 군데에서만: StageConfig에 규칙/포인트/네브 옵션을 두고, StageSpawner는 그 데이터만 읽어 작동.
  • 감염도는 적 프리팹이 몰라도 됨: 적 사망 시 StatHandler.GetStat(InfectionPoint)로 점수 읽고 UIManager.getInfection(amount) 호출.
  • 타겟팅은 “최근접”만 유지: 매 프레임 Player/좀비를 스캔해 최단거리 객체를 Target으로. 상태 로직은 이 한 값에 의존.
  • 네브메시 기반 스폰이 안전: NavMesh 삼각형/샘플링으로 “걷는 곳” 위에만 소환 → 장애물/빈 공간 회피.

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

1) IntroTimeline 종료 시 NRE

  • 정의: 씬 로드 전에 UI 호출하여 NullReferenceException 발생.
  • 시도: LoadScene 직후 UI 전환 호출 → 여전히 레이스 컨디션.
  • 해결: UI 전환을 OnStageStarted 리스너로 이동, 널 가드 추가.
  • 새로 앎: 씬 객체 의존 로직은 “로드 완료” 이벤트에서만 실행.
  • 다시 만나면: 로더 내부 UI 호출 금지, 이벤트 구독 구조로 분리.

2) 디스폰 시 IndexOutOfRangeException

  • 정의: 씬 전환 중 _DespawnNotifier가 aliveCounts[i] 접근하다 범위 초과.
  • 시도: 리스트 즉시 Clear() → 더 자주 터짐.
  • 해결: _shuttingDown 플래그로 셧다운 중 콜백 무시, idx 로컬 캡처 + 범위 가드.
  • 새로 앎: 코루틴/콜백과 컨테이너 수명은 분리해서 안전장치 필요.
  • 다시 만나면: “정리 중” 플래그 + 인덱스/널 가드 기본 탑재.

3) ScriptableObject에 씬 Transform 참조로 인한 NRE

  • 정의: SO의 Transform[] 스폰 포인트가 런타임에 null.
  • 시도: 씬에서 다시 할당 → 유지보수 난감.
  • 해결: 좌표/네브데이터만 SO에 보관. 스포너가 좌표/네브에서 위치 산출.
  • 새로 앎: SO ↔ 씬 오브젝트 직접 참조는 지양. 데이터만 들고 있게.
  • 다시 만나면: 좌표/ID/키만 저장하고 런타임에 조회.

4) VIP 사망 시 NRE (PlayerManager.Instance null)

  • 정의: 싱글톤 초기화 누락으로 Instance가 null.
  • 시도: Awake에서 직접 필드 할당 → Instance 여전히 null.
  • 해결: protected override Awake() + base.Awake() 호출, player/Stats 널 가드.
  • 새로 앎: 커스텀 싱글톤은 base.Awake()가 생명줄.
  • 다시 만나면: 모든 싱글톤에 동일 체크리스트 적용.

📝 메모

  • 스폰 포인트는 StageConfig: 좌표 리스트 또는 NavMeshData 등록 → SamplePosition(반경 1~3) 또는 삼각형 샘플.
  • 적 사망 처리 하나로 통일: StageManager.OnEnemyKilled(NPC) → 내부에서 SO InfectionPoint 읽어 UIManager.getInfection().
  • VIP 보상: NPCDeathState.Enter에서 타입 체크 → PlayerManager.PlayerSpeedUp() 호출(기본 배수/시간 인스펙터 노출).
  • 타겟팅은 간단·안전 우선, 성능 이슈 생기면 0.2s 주기 스캔으로 전환.
  • 씬 전환 시 코루틴/콜백 정리 순서 반드시 확인(셧다운 플래그 유효).

 

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 10:00 : 스크립트 구조 점검 (StageSceneManager, StageManager, StageConfig 관계 확인)
  • 10:00 ~ 11:30 : 제너릭 싱글톤 구현 및 단순화 버전 리팩토링
  • 11:30 ~ 13:00 : 씬 전환 흐름(StageSceneManager → StageManager → StageStatBinder) 최종 정리

🍽️ 점심시간

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

✅ 오후

  • 14:00 ~ 15:30 : StageConfig 수정 (sceneName + unitId→Stats 매핑)
  • 15:30 ~ 17:00 : StageManager 이벤트 발행 구조 리팩토링, StageStatBinder 늦스폰 대응 추가
  • 17:00 ~ 18:00 : 전체 흐름 점검 및 개선 포인트 메모

🍽️ 저녁시간

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

✅ 저녁

  • 19:00 ~ 20:30 : 오늘 작업 정리, TIL 작성
  • 20:30 ~ 21:00 : 질문/회고 (각 스크립트 역할, 필요 없는 부분 확인)

✅ 오늘 학습 키워드

  • ScriptableObject(StageConfig, ScriptableStats)
  • 전환 파이프라인: StageSceneManager → StageManager → StageStatBinder → StatHandler
  • OnStageStarted 이벤트 브로드캐스트
  • 유닛 식별: Tag 기반 unitId
  • StatHandler.ApplyFrom(...) / BoostStat(...)
  • DontDestroyOnLoad / 씬 로드(Async)
  • 늦게 스폰된 유닛 즉시 적용 처리

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

  • 스테이지 전환은 버튼(선택)과 실제 전환(로직)을 분리하면 깔끔하다.
    • 버튼/UI는 StageSceneManager가 StageConfig를 골라 **StageManager.LoadStage(cfg)**만 호출한다.
    • StageManager는 씬을 로드하고, 로드 완료 시점에 OnStageStarted(cfg)를 뿌린다.
    • 각 유닛의 StageStatBinder는 이벤트를 받아 자기 Tag(unitId) 에 맞는 ScriptableStats를 찾아 StatHandler.ApplyFrom으로 런타임 스탯을 채운다.
  • 데이터는 SO(불변), 런타임 수치는 컴포넌트에서 관리 → 공유 에셋 부작용 방지.
  • 씬을 나눠도 DontDestroyOnLoad와 로드 완료 이벤트만 잘 잡으면 모든 유닛이 자연스럽게 최신 스탯을 받는다.

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

1) 씬만 로드하면 스탯 이벤트가 안 뜸

  • 문제&에러에 대한 정의: StageSceneManager가 씬 이름만 로드하니, 유닛들이 스탯을 받을 OnStageStarted가 발생하지 않음.
  • 내가 한 시도: StageSceneManager → StageConfig 선택 후 StageManager.LoadStage(cfg)로 위임.
  • 해결 방법: StageManager에서 씬 로드 완료 콜백에서 OnStageStarted(cfg) 발행.
  • 새롭게 알게 된 점: 스탯 적용 타이밍은 “씬 로드 완료”가 정답.
  • 이 문제&에러를 다시 만나게 되었다면: UI에서 절대 직접 씬 로드하지 말고 반드시 StageManager를 통해 처리.

2) 늦게 스폰된 유닛에 스탯 미적용

  • 문제&에러에 대한 정의: 이벤트 타이밍을 놓친 프리팹은 스탯을 못 받음.
  • 내가 한 시도: StageStatBinder.OnEnable()에서 StageManager.Current를 확인해 즉시 1회 적용 추가.
  • 해결 방법: 이벤트 구독 + 활성화 시 현재 스테이지 재적용의 이중 안전장치.
  • 새롭게 알게 된 점: 씬 전환 구조에선 OnEnable 훅이 중요한 세컨드 트리거.
  • 이 문제&에러를 다시 만나게 되었다면: 바인더는 항상 “이벤트 + 즉시 재적용” 패턴 유지.

3) StatHandler 초기화 이중/널 문제

  • 문제&에러에 대한 정의: Awake()에서 중복 초기화 또는 baseStats 미할당 시 NRE 가능.
  • 내가 한 시도: ApplyFrom(baseStats, true) 한 번만 호출 + isAlive 널 가드.
  • 해결 방법: 초기화 경로 단일화.
  • 새롭게 알게 된 점: 런타임 값은 항상 한 통로로만 주입해야 안전.
  • 이 문제&에러를 다시 만나게 되었다면: InitializeStats() 같은 중복 경로 제거, 주입 함수만 사용.

4) 버프 코루틴과 스테이지 전환 충돌 가능성

  • 문제&에러에 대한 정의: 전환 중 ApplyFrom() 후, 버프 코루틴이 “/multiplier” 복구하면 값 꼬임.
  • 내가 한 시도: 전환 직전 버프 정리 or 모디파이어 레이어로 재계산 구조 고려.
  • 해결 방법: 당장은 전환 전에 버프 클리어 정책 채택(간단), 장기적으로 모디파이어 방식 도입.
  • 새롭게 알게 된 점: 코루틴 기반 “곱/나눔” 복구는 전환과 충돌하기 쉬움.
  • 이 문제&에러를 다시 만나게 되었다면: (base + Σadd) × Πmul 재계산 구조로 변경.

📝 메모

  • 세팅 체크:
    • StageConfig.sceneName은 Build Settings 등록 필수.
    • 유닛 Tag ↔ unitId 철자 완전 일치(대소문자 포함).
    • 씬당 StageManager 1개(싱글톤).
  • 코드 습관: 이벤트 브로드캐스트는 항상 로드 완료 시점에, 데이터 주입은 한 통로(ApplyFrom) 로.
  • 다음 액션: 로딩 UI(progress bar) 붙이기, 매핑 누락/Tag 불일치 경고 로그 보강, 버프 정책 확정.

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 10:00 : 개인시간
  • 10:00 ~ 10:20 : 개발 심화 발제
  • 10:20 ~ 13:00 : 팀 회의

🍽️ 점심시간

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

✅ 오후

  • 14:00 ~ 18:00 : 스테이지 1·2·3 제작

🍽️ 저녁시간

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

✅ 저녁

  • 19:00 ~ 20:00 : 개인 개발 시간
  • 20:00 ~ 21:00 : 팀 프로젝트 회의

✅ 오늘 학습 키워드

  • ScriptableObject 기반 StageConfig / StageStatsSet
  • StageTier(1/2/3), ActorKind(Human/Vip/Hunter)
  • StatsByTier → UnitStats 구조화(HP/ATK/MoveSpeed/APS)
  • StageConfig ↔ StatsSet 분리/참조로 데이터 드리븐 설계
  • StageManager 타이머/리젠 루프, HunterRule(AnimationCurve) 간격 제어
  • 프리팹 능력치 주입(Stat Injection), NRE 방어

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

  • 데이터 책임 분리개체 능력치(HP/공격력/이동속도/공속)는 StageStatsSet이 맡는다.
  • StageConfig.stageTier로 현재 스테이지(1/2/3)를 명시하고, statsSet.Get(kind, tier)로 필요한 스탯을 읽기 전용으로 가져와 프리팹에 주입한다.
  • 스폰 수치·시간(Init/Max/Cooldown/목표 등)은 StageConfig가,
  • 유연한 밸런싱 파이프라인
  • 모든 스테이지가 한 개의 StatsSet을 공유하므로, 밸런서는 StatsSet만 수정해도 전 스테이지가 반영된다. 반대로 특수 스테이지는 별도 StatsSet 에셋을 가리키면 된다.
  • 헌터 스폰의 난이도 곡선화
  • HunterRule.intervalByInfection 커브로 감염률→스폰간격을 매핑하니 난이도 체감이 부드럽다. 하드 스테이지는 커브 기울기만 바꿔도 된다.
  • 운영 루프 간결화
  • CoTimer / CoHumanRegen / CoVipRegen / CoHunterControl로 역할이 분리돼 가독성이 좋아졌다. 스테이지 전환 시 StopAllCoroutines()로 누수 방지.

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

1. StageStatsSet 미지정 시 NRE 위험

  • 문제정의: StageConfig.statsSet이 비어 있으면 스탯 주입 코드에서 NRE 가능.
  • 시도: 사용부에서만 null 체크.
  • 해결 방법: 제공자와 사용자 모두 방어. StageConfig.GetStats()에서 null 대응, 사용부도 이중 가드.
// StageConfig.cs
public UnitStats GetStats(ActorKind kind) {
    if (statsSet == null) return null;
    return statsSet.Get(kind, stageTier);
}

// 사용부
var stat = cfg.GetStats(ActorKind.Human);
if (stat == null) return; // 안전 가드
  • 새롭게 알게 된 점: SO 의존성은 “제공자 가드 + 소비자 가드”가 심리적 안정감을 준다.
  • 다시 만나면: 에디터 Validate(예: OnValidate)에서 미지정 시 콘솔 경고 띄우기.

2. 스테이지별 스탯 매핑 실수(잘못된 Tier 선택)

  • 문제정의: Tier 매핑 스위치문에서 default 처리를 안 하면 잘못된 값 사용 가능.
  • 시도: 단순 스위치 반환.
  • 해결 방법: 명시적 default에디터 노출 순서 일치.
// StatsByTier.cs
public UnitStats Get(StageTier tier) {
    switch (tier) {
        case StageTier.Stage1: return stage1;
        case StageTier.Stage2: return stage2;
        case StageTier.Stage3: return stage3;
        default: return stage1; // 안전 기본값
    }
}
  • 새롭게 알게 된 점: Enum 확장 시 누락 위험이 있다.
  • 다시 만나면: Dictionary로 전환하거나 switch에 _ 패턴 사용(C# 버전에 따라).

📝 메모

생각보다 데이터 책임 분리가 많은 걸 바꿔준다. “스테이지는 규칙과 수량”, “능력치는 별도 세트”로 나누니 머리가 한결 가벼워졌다. 오늘 스테이지 1·2·3을 끝까지 밀어 붙인 게 큰 수확! 모르는 걸 부끄러워하지 말고, 내일은 UI에서 현재 Tier/목표/남은 시간을 직관적으로 보여주는 패널까지 연결하자.

본격적으로 팀 프로젝트 시작하는 1일차이다 이번이 5번째인가.. 다음 마지막 프로젝트가 최종 프로젝트인데 그 전 마지막 프로젝트이다 이번 팀원들과도 마지막까지 힘내보자 화이티잉!!!!!


반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 10:30 : Unity 프로젝트 정리(README 구조/프로젝트 트리/트러블슈팅 초안)
  • 10:30 ~ 12:00 : 블로그용 글 편집(이미지/섹션 다듬기) + 파일 재생성 이슈 처리
  • 12:00 ~ 13:00 : 최종 점검 후 프로젝트 제출(13:00 이전 완료)

🍽️ 점심시간

  • 13:00 ~ 14:00 : 점심

✅ 오후

  • 14:00 ~ 15:00 : Squad Swarm 스테이지 범위/지표 합의(타이머·감염도·스폰 규칙)
  • 15:00 ~ 16:30 : StageConfig(SO) / StageCatalog(SO) 스키마 확정
  • 16:30 ~ 17:30 : StageManager ↔ SpawnDirector 인터페이스·이벤트버스(StageEvents/SpawnSignal) 정의

🍽️ 저녁시간

  • 17:30 ~ 18:30 : 저녁

✅ 저녁

  • 18:30 ~ 19:30 : PlantUML 클래스/컴포넌트/시퀀스 초안 작성
  • 19:30 ~ 20:30 : 다이어그램 피드백 반영(코루틴 가드/읽기전용 프로퍼티/주입 경로)
  • 20:30 ~ 21:00 : 최종 통합 다이어그램 공유 및 TIL 정리

✅ 오늘 학습 키워드

ScriptableObject

EventBus(Pub/Sub)

Single Source of Truth(StageManager)

scaled vs unscaled time

Coroutine Guard

Spawn/Respawn 규칙

UML(PlantUML)

Execution Order


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

 

Unity - TopDown 레이싱 방치형 RPG

🚗 Unity Car Survival Prototype — 데이터·이벤트 기반 차량 생존 슈팅 만들기자동차에 무기를 장착해 몰려오는 적을 처치하며 스테이지를 버티는 탑다운 프로토타입입니다.싱글톤 매니저, 무기/업

dev-jen.tistory.com

 

  • 진행의 중심을 한 곳(StageManager)에 모으자. 타이머·감염·일시정지·결과는 StageManager가 판단하고, 나머지는 이벤트만 구독하도록 만들면 결합도가 낮아진다.
  • 읽기와 쓰기를 분리하자. StageEvents는 “사실 알림”, SpawnSignal은 “행동 지시”. 채널을 분리하니 사이드이펙트 추적이 쉬워졌다.
  • 시간은 목적에 맞게 쓴다. 게임 진행은 deltaTime(scaled), 재개 카운트다운은 WaitForSecondsRealtime(unscaled).
  • 리젠은 가드가 생명. 종류별 1코루틴 원칙 + 현재 카운트 추적으로 Max 보장.
  • 난이도/페이스는 SO로. 스테이지 특례(예: Stage3 헌터 즉시+주기 스폰, Max 20)를 코드 변경 없이 에셋으로만 조정 가능.

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

1) FindObjectsOfType를 생성자/필드 초기화에서 호출

  • 문제&에러에 대한 정의
  • UIConditionBinder가 초기화 타이밍에 Singleton.Instance 접근 → UnityException.
  • 내가 한 시도
  • 생성자에서 참조 잡기 → 동일 에러 재현.
  • 해결 방법
  • 참조는 Awake/Start, 이벤트 구독은 OnEnable, 해제는 OnDisable로 이동. 가능한 건 인스펙터 바인딩.
  • 새롭게 알게 된 점
  • MonoBehaviour는 생성자/필드 초기화 시점에 씬이 준비되지 않는다.
  • 이 문제&에러를 다시 만나게 되었다면
  • “필드 초기화에서 Instance 호출 금지”를 체크리스트에 고정.

2) Respawn 버튼에서 PlayerManager.carTransform 미할당

  • 문제&에러에 대한 정의
  • 버튼 클릭 시 UnassignedReferenceException.
  • 내가 한 시도
  • 인스펙터 재바인딩 → 씬 활성 순서에 따라 간헐 실패.
  • 해결 방법
  • RespawnManager.ResolveRefs() 추가(Instance→씬 검색→car.transform) + Execution Order에서 PlayerManager.Awake 선행.
  • 새롭게 알게 된 점
  • 명시 바인딩 + 런타임 복구 로직이 함께 있어야 안전.
  • 이 문제&에러를 다시 만나게 되었다면
  • 필수 참조는 에디터 검증 스크립트로 미리 경고.

3) SpawnDirector 리젠 코루틴 중복 실행 위험

  • 문제&에러에 대한 정의
  • 동일 시그널이 반복되면 같은 종류 리젠 코루틴이 여러 개 돌아갈 수 있음.
  • 내가 한 시도
  • 호출부 조건 분기만으로 제어 → 비동기 상황에서 여전함.
  • 해결 방법
  • isHuman/VIP/HunterRegenRunning 가드 + 현재 카운트(current*) 추적. 구독/해제는 OnEnable/OnDisable에서만.
  • 새롭게 알게 된 점
  • 코루틴 제어는 소비자 쪽 가드가 확실하다.
  • 이 문제&에러를 다시 만나게 되었다면
  • 리젠 시작을 단일 포인트로 통일하고, 상태를 디버그 HUD로 노출.

📝 메모

다음주부터 팀 프로젝트 다시 시작이다! 팀원들과 회의도 많이 했고 친분도 많이 쌓였다ㅎㅎ 다음주도 화이팅이다!!


오늘 최종 완성한 레이싱 방치형 RPG!

반응형