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
no image
Unity - TopDown 레이싱 방치형 RPG
🚗 Unity Car Survival Prototype — 데이터·이벤트 기반 차량 생존 슈팅 만들기자동차에 무기를 장착해 몰려오는 적을 처치하며 스테이지를 버티는 탑다운 프로토타입입니다.싱글톤 매니저, 무기/업그레이드, 스테이지/스폰, 리스폰, UI·사운드까지 확장 가능한 구조로 구현했어요.🧾 개요요약: ScriptableObject(WeaponData) + 이벤트 기반(UI/상태) + 제네릭 싱글톤 매니저로 빠르게 기능을 붙여 나갈 수 있는 구조.핵심 요소: 자동 주행(CarAI), 자동 사격(BaseWeapon), 업그레이드(WeaponSlotsManager), Respawn, 스테이지 타이머/스폰.대상 독자: 서바이벌라이크/탑다운 프로토타입을 빨리 만들고 싶은 분, 아키텍처 참고가 필요한 분...
2025.08.29
no image
내일배움캠프 43일차 TIL [개인프로젝트 3D 방치형 RPG]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 12:00 : 프로젝트 구조 정리 및 시스템 설계(업그레이드/파티클/사운드 플로우 구상)🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 15:00 : BGM/SFX 파일 임포트 및 SoundManager 기본 세팅15:00 ~ 16:00 : 슬라이더 초기값/볼륨 연동 정리(PlayerPrefs 포함)16:00 ~ 17:00 : ParticleManager 제작(풀링, 월드 위쪽 고정 분사)17:00 ~ 18:00 : 스테이지 가산형 스케일링 패치(HP/Speed 절대값 적용)🍽️ 저녁시간18:00 ~ 19:00 : 저녁시간✅ 저녁19:00 ~ 20:00 : 사운드 NRE 해결(EnsureInit, 실행 순서 조정)20:00 ~ 20:30..
2025.08.28
no image
내일배움캠프 42일차 TIL [개인프로젝트 3D 방치형 RPG]
🗓️ 오늘 하루 일정✅ 오전10:30 ~ 12:30 : 캐논 업그레이드 시스템 1차 구현발사력/공격 속도/탄속/스플래시 반경 단계별 설계업그레이드 버튼과 비용(골드) 차감 로직 연결🍽️ 점심시간13:00 ~ 14:00 : 점심✅ 오후14:00 ~ 15:00 : GoldUI 수정 및 Enemy 히트 파티클 추가15:00 ~ 16:00 : Generic Singleton 베이스 클래스 추가 → 매니저 공통화16:00 ~ 17:30 : Upgrade UI 고도화 + EnemyManager/GameManager/StageManager 정리스테이지 클리어 → 보상 지급 → 업그레이드 패널 오픈 플로우 연결🍽️ 저녁시간18:00 ~ 19:00 : 저녁✅ 저녁19:30 ~ 21:00 : 이미지 에셋 작업배경 제..
2025.08.28
no image
내일배움캠프 41일차 TIL [개인프로젝트 3D 방치형 RPG]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 11:30 : HP/MP/EXP 컨디션–UI 연동PlayerCondition 이벤트 → UIConditionBinder 슬라이더/텍스트 바인딩초기값 미반영 이슈 해결(구독 직후 강제 갱신)11:30 ~ 12:00 : 디버그 입력 점검새 Input System 대응(키 입력 미동작 수정)🍽️ 점심시간13:00 ~ 14:00 : 점심✅ 오후14:00 ~ 15:30 : CarAI 안정화도착 판정 nodeReachDistance 확대, XZ 평면 거리로 판정기즈모 반경 = 도착 반경 동기화15:30 ~ 16:00 : 속도 UI(km/h) 출력 추가16:00 ~ 18:00 : 챌린지반 강의 – AssetBundle / Addressables🍽️ 저녁시간18:00 ~ ..
2025.08.26
no image
내일배움캠프 40일차 TIL [개인프로젝트 3D 방치형 RPG]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 10:00 : 개인 시간10:00 ~ 11:00 : 유니티 심화 프로젝트 발제11:00 ~ 12:00 : 팀 자기소개 & 협업/기획 논의🍽️ 점심시간13:00 ~ 14:00 : 점심시간✅ 오후14:00 ~ 14:30 : 팀 회의 (점심 이후)14:30 ~ 15:00 : 개인 프로젝트 – URP 전환 체크 & 재질 교체15:00 ~ 17:00 : 개인 프로젝트 – CarAI 트랙/노드 로직 수정 & 디버깅🍽️ 저녁시간18:00 ~ 19:00 : 저녁시간✅ 저녁19:00 ~ 20:00 : 개인 프로젝트 – 스플라인 설계/가시화, NavMesh 재베이크/파라미터 조정20:00 ~ 21:00 : 기획팀 협업 미팅✅ 오늘 학습 키워드URP 전환: URP/Lit 재질 ..
2025.08.25
no image
내일배움캠프 39일차 TIL [3D_Survival_Project]
🗓️ 오늘 하루 일정✅ 오전09:00 ~ 11:30 : Craft UI 연결 및 프리뷰 슬롯 NRE 수정(countText 널 가드 처리, 버튼/아이콘 점검)11:30 ~ 12:00 : NPC 대화 타이핑 기능 점검 (스킵/완료 분기 처리)🍽️ 점심시간13:00 ~ 14:00 : 점심✅ 오후14:00 ~ 16:00 : 팀 프로젝트 발표16:00 ~ 18:00 : 팀원들과 회의 및 의견 교환🍽️ 저녁시간18:00 ~ 19:00 : 저녁식사✅ 저녁19:00 ~ 20:30 : 단원평가 진행 및 팀원들과 대화20:30 ~ 21:00 : TIL 작성 및 하루 마무리✅ 오늘 학습 키워드Craft UINPC 대화 타이핑팀 프로젝트 발표단원평가✅ 오늘 학습 한 내용을 나만의 언어로 정리하기오늘 오전에는 Craft..
2025.08.22
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 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!

반응형
반응형

🚗 Unity Car Survival Prototype — 데이터·이벤트 기반 차량 생존 슈팅 만들기

자동차에 무기를 장착해 몰려오는 적을 처치하며 스테이지를 버티는 탑다운 프로토타입입니다.
싱글톤 매니저, 무기/업그레이드, 스테이지/스폰, 리스폰, UI·사운드까지 확장 가능한 구조로 구현했어요.


🧾 개요

  • 요약: ScriptableObject(WeaponData) + 이벤트 기반(UI/상태) + 제네릭 싱글톤 매니저로 빠르게 기능을 붙여 나갈 수 있는 구조.
  • 핵심 요소: 자동 주행(CarAI), 자동 사격(BaseWeapon), 업그레이드(WeaponSlotsManager), Respawn, 스테이지 타이머/스폰.
  • 대상 독자: 서바이벌라이크/탑다운 프로토타입을 빨리 만들고 싶은 분, 아키텍처 참고가 필요한 분.

🎮 게임 소개

차량을 조작(AI 주행)하며 시간이 지날수록 강해지는 적을 상대하는 탑다운 생존 슈팅입니다.
처치 보상으로 골드/경험치를 모아 무기를 업그레이드하고, 위기 상황에서는 Respawn으로 트랙 위 최근접 노드에 복귀해 흐름을 이어갑니다.

  • 목표: 가능한 오래 생존하며 Stage를 올리고 더 강한 웨이브를 버티기
  • 루프: 처치 보상 → 골드/EXP → 업그레이드 패널에서 레벨업/티어업

🖼️ 플레이 영상 & GIF

 

✨ Features

  • Generic Singleton: ClassName.Instance로 전역 접근(중복 생성 방지/선 생성 불필요)
  • 무기 시스템(SO): WeaponData로 피해/사거리/발사 속도/쿨타임/티어 정의 → BaseWeapon 공통 파이프라인 + CannonWeapon 파생
  • 업그레이드 & 슬롯: WeaponSlotsManager가 슬롯 mount에 무기를 스폰/교체하고 레벨·티어 업 로직 처리, UpgradePanelController로 UI 연동
  • 스테이지 & 스폰: StageManager 타이머로 Stage 상승, EnemyManager가 NavMesh 영역에 적 스폰(최대 생존 수 유지)
  • Respawn 버튼: “가장 가까운 트랙 노드”로 즉시 복귀(속도·웨이포인트 리셋)
  • UI/HUD: 체력/경험치/레벨, 골드, 속도(km/h), 적 머리 위 HP 빌보드
  • 사운드: BGM + 풀링 기반 SFX + 슬라이더로 볼륨 제어
  • 센서 & 이동 제어: 전방 센서로 정지/재가속, 런타임 파라미터 튜닝 샘플 제공

📁 프로젝트 구조(요약)

 
02. Scripts
├─ Base
│  ├─ BaseCondition.cs
│  ├─ BaseWeapon.cs
│  └─ Singleton.cs
├─ Camera
│  └─ FollowCamera.cs
├─ Controller
│  └─ UpgradePanelController.cs
├─ Enemy
│  ├─ AI
│  │  └─ EnemyAI.cs
│  ├─ Attack
│  │  ├─ EnemyAttack.cs
│  │  └─ EnemyCondition.cs
│  └─ Interface
│     └─ IDamageable.cs
├─ Manager
│  ├─ Enemy
│  │  └─ EnemyManager.cs
│  ├─ Player
│  │  ├─ PlayerManager.cs
│  │  └─ RespawnManager.cs
│  ├─ SkillManager.cs
│  ├─ CurrencyManager.cs
│  ├─ Weapon
│  │  └─ WeaponSlotsManager.cs
│  ├─ GameManager.cs
│  ├─ SoundManager.cs
│  └─ StageManager.cs
├─ Player
│  ├─ Skill
│  │  ├─ AttackController.cs (partial)
│  │  ├─ AttackController.Heal.cs (partial)
│  │  └─ AttackController.SpinAttack.cs (partial)
│  ├─ CarAI.cs
│  └─ PlayerCondition.cs
├─ Scriptable
│  └─ WeaponData.cs
├─ UI
│  ├─ Enemy
│  │  └─ EnemyHealthUI.cs
│  ├─ Player
│  │  ├─ CarSpeedUI.cs
│  │  └─ GoldUI.cs
│  └─ UIConditionBinder.cs
├─ Util
│  ├─ controllingCarAI.cs
│  └─ SensorManager.cs
└─ Weapon
   ├─ Projectile
   │  └─ SimpleProjectile.cs
   └─ CannonWeapon.cs

🧱 설계/디자인 패턴

  • Singleton(제네릭): 매니저 전역 접근/중복 생성 방지
  • Observer(이벤트 기반): PlayerCondition 이벤트 → UI가 구독해 즉시 갱신
  • Strategy(무기 확장): BaseWeapon 공통 파이프라인 + 파생 무기
  • Interface(결합도↓): IDamageable로 피해 처리를 통일
  • Partial Class: AttackController를 Spin/Heal로 분리해 관심사 정리
  • Data-Driven & Composition: ScriptableObject·컴포넌트 조합 중심 설계

🧰 사용 기술 & 시스템

  • NavMesh: CarAI 웨이포인트 스냅, EnemyManager 스폰 샘플링
  • WheelCollider + Rigidbody: GetWorldPose로 메시 동기화, 모터/브레이크/조향 제어
  • Catmull-Rom Spline: 트랙 노드 사이 부드러운 경로 생성(루프/샘플 수 옵션)
  • Physics Overlap/Trigger: Spin(OverlapSphere), 투사체/근접 충돌 → IDamageable
  • TMP + UGUI: HUD/패널 구성

🚗 핵심 동작 요약

  • CarAI: trackNodes → 스플라인 웨이포인트 생성 → 바퀴/조향/가속 갱신, carFront 기준 도달 판정, CurrentSpeedKmh 제공
  • Respawn: 현재 위치(가능하면 carFront) 기준 최근접 노드 탐색 → CarAI.TeleportToNode() → 속도·각속도 초기화 + 웨이포인트 리셋
  • 무기/업그레이드: 슬롯 mount에 프리팹 스폰, WeaponData로 레벨업/티어업, UI 반영
  • 스테이지/스폰: 타이머로 Stage 상승, NavMesh 영역 내 최대 생존 수 유지
  • UI: 플레이어 HUD + 적 HP 빌보드

🕹 플레이 방법

  1. 시작: 플레이하면 StageManager가 타이머를 돌리며 Stage가 주기적으로 상승
  2. 이동: CarAI가 trackNodes를 따라 주행(루프/랜덤/커스텀 경로). 전방 센서 접촉 시 일시 정지 후 재출발
  3. 전투: WeaponSlotsManager가 슬롯 mount에 무기 스폰 → BaseWeapon 파이프라인으로 자동 조준·발사
  4. 성장: 처치 보상으로 골드/EXP 획득 → 업그레이드 패널에서 레벨업/티어업
  5. 복구: 길 이탈 시 Respawn으로 최근접 트랙 노드 복귀

기본 흐름은 AI 주행 + 자동 사격. 입력형 조작을 추가하고 싶으면 별도 컨트롤러로 쉽게 확장 가능합니다.


🧪 씬 세팅 체크리스트

  • 싱글톤 매니저 배치: Game/Stage/Enemy/Sound/Currency/Skill/WeaponSlots/PlayerManager
  • 차량: CarAI + 바퀴(콜라이더/메시) + carFront 지정, trackNodes 등록
  • 무기: WeaponData 생성 → 슬롯 mount에 연결(시작 시 자동 스폰)
  • UI: 슬라이더/텍스트를 인스펙터로 바인딩
  • Respawn 버튼: RespawnManager.RespawnToNearestTrackNode() OnClick
  • NavMesh: 스폰 영역/트랙 주변 베이크

🧯 Troubleshooting (Deep Dive)

발생했는가 → 어떻게 고쳤는가 → 재발 방지까지 실제로 겪었던 이슈 중심으로 정리.

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

현상
UIConditionBinder가 생성자/필드 초기화 타이밍에 Singleton.Instance를 참조하면서 UnityException 발생.

원인(Why)
MonoBehaviour는 생성자/필드 초기화 시점에 씬 오브젝트가 준비되지 않음. 이 타이밍의 FindObjectsOfType/Instance 접근은 금기.

해결(How)

  • 참조 획득은 Awake/Start, 이벤트 구독은 OnEnable, 해제는 OnDisable.
  • 가능하면 [SerializeField] 후 인스펙터에서 수동 바인딩.

재발 방지(Prevent)

  • 팀 규칙: “필드 초기화/생성자에서 Singleton.Instance 금지”
  • 코드리뷰 체크 항목에 추가.

2) PlayerManager.carTransform 미할당으로 Respawn 버튼 NullReference/UnassignedReference

현상
버튼 클릭 시 RespawnManager가 carTransform 접근하다 예외.

원인

  • PlayerManager.Awake 실행 순서 지연, 또는 인스펙터 미바인딩.
  • 씬 활성/비활성 순서에 따른 타이밍 이슈.

해결

  • RespawnManager.ResolveRefs(): PlayerManager → 씬 검색 → car.transform 순으로 자체 복구 로직 추가.
  • Script Execution Order로 PlayerManager.Awake 선행.

재발 방지

  • 핵심 참조는 인스펙터 명시 바인딩 우선.
  • 런타임에서도 한 번 더 널 가드.

3) UI OnEnable에서 즉시 SFX → SoundManager NRE

현상
UpgradePanelController.OnEnable() 내 PlaySfx() 호출 시 NRE.

원인
사운드 풀/오디오소스가 아직 초기화되지 않은 타이밍에 호출.

해결

 
// UI 측 if (SoundManager.Instance && SoundManager.Instance.IsReady) SoundManager.Instance.PlaySfx(SoundManager.SfxId.Upgrade); // 또는 Start / WaitForEndOfFrame로 지연
  • SoundManager.Awake()에서 풀 확실히 초기화.

재발 방지

  • 가이드: “UI의 OnEnable에서 즉시 오디오 재생 금지”
  • 씬 부팅 순서 문서화.

4) BaseCondition 보호된 필드 접근(CS0122)

현상
EnemyHealthUI에서 BaseCondition.health/maxHealth 직접 접근 시 접근 제한자 에러.

원인
캡슐화 위반: 외부 UI가 내부 상태를 직접 읽으려 함.

해결

  • Public 프로퍼티/이벤트로 노출(Health, Health01, 변경 이벤트).
  • UI는 이벤트를 구독해 슬라이더만 업데이트.

재발 방지

  • 규칙: “UI는 이벤트/프로퍼티만 사용”.

5) 빌보드 HP UI 떨림/뒤집힘

현상
카메라 회전 시 HP 슬라이더가 순간적으로 뒤집히거나 흔들림.

원인
Update 순서/축 처리 미흡, LookAt이 Z축까지 뒤집음.

해결

void LateUpdate() {
    var cam = Camera.main.transform;
    Vector3 dir = cam.position - transform.position; dir.y = 0f; // 수평만
    if (dir.sqrMagnitude > 0.0001f)
        transform.rotation = Quaternion.LookRotation(dir);
}

재발 방지

  • 월드 스페이스 UI는 LateUpdate에서 위치/방향 갱신 고정.

6) 투사체 임팩트 후 TrailRenderer/파티클 누수

현상
충돌 직후 본체 파괴 시 Trail/VFX가 같이 사라지거나, 반대로 고아 오브젝트로 남음.

원인
Trail이 본체에 붙은 채 파괴되거나, 별도 라이프사이클 미관리.

해결

  • 충돌 시 Trail을 detach → 별도 타이머로 제거.
  • Impact VFX는 풀링 또는 Destroy(go, duration)로 정리.

재발 방지

  • 본체/트레일/임팩트 라이프사이클 분리 원칙.

7) NavMesh 스폰 지점이 벽/경계 밖으로 샘플링

현상
적이 벽 내부/경계 밖에서 등장하거나 추락.

원인
NavMesh.SamplePosition 반경 과소, areaMask 미설정.

해결

  • 후보 지점에서 SamplePosition(point, out hit, **radius**, **areaMask**)로 여유 반경 제공.
  • allowedAreaNames로 마스크 명시.

재발 방지

  • 스폰 영역 Gizmo/BoxCollider 시각화, 반경/마스크 프리셋 유지.

8) WheelCollider 시각/물리 불일치(튐/박힘)

현상
속도가 오르거나 경사면에서 바퀴 메시가 뜨거나 섀시가 튄다.

원인
메시 동기화가 Update에서 이뤄짐, 물리 타임스텝/보간 불일치.

해결

  • FixedUpdate에서 GetWorldPose(out pos, out rot)로 메시 동기화.
  • Rigidbody Interpolate 사용, Fixed Timestep(권장 0.02s) 점검.

재발 방지

  • 차량 비주얼 동기화는 항상 FixedUpdate.

9) 이벤트 중복 구독 → UI 두 배 갱신

현상
씬 재로드/패널 토글 후 HP/골드 텍스트가 중복 업데이트.

원인
OnEnable에서 AddListener만 하고 OnDisable 해제 누락.

해결

  • 모든 구독은 OnEnable ↔ OnDisable 페어 관리.
  • 필요 시 구독 전 RemoveListener로 1차 청소.

재발 방지

  • 리뷰 체크리스트: “이벤트 구독 해제했나?”

10) Stage 타이머 드리프트/폭주

현상
시간이 지날수록 Stage 속도가 빨라지거나 UI가 밀림.

원인
Time.time 기반 반복이 정지/프레임 드롭에 영향, 코루틴 중복 실행.

해결

  • 단일 코루틴 가드(isRunning) + WaitForSeconds.
  • 일시정지 대응 필요 시 unscaledDeltaTime 누적.

재발 방지

  • 모든 루프/타이머에 중복 실행 가드 + 정지/재개 시나리오 점검.
반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 12:00 : 프로젝트 구조 정리 및 시스템 설계(업그레이드/파티클/사운드 플로우 구상)

🍽️ 점심시간

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

✅ 오후

  • 14:00 ~ 15:00 : BGM/SFX 파일 임포트 및 SoundManager 기본 세팅
  • 15:00 ~ 16:00 : 슬라이더 초기값/볼륨 연동 정리(PlayerPrefs 포함)
  • 16:00 ~ 17:00 : ParticleManager 제작(풀링, 월드 위쪽 고정 분사)
  • 17:00 ~ 18:00 : 스테이지 가산형 스케일링 패치(HP/Speed 절대값 적용)

🍽️ 저녁시간

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

✅ 저녁

  • 19:00 ~ 20:00 : 사운드 NRE 해결(EnsureInit, 실행 순서 조정)
  • 20:00 ~ 20:30 : 에디터 Hierarchy 인덱스 오류 점검(레이아웃/플러그인 확인)
  • 20:00 ~ 21:00 : 팀 프로젝트 회의

✅ 오늘 학습 키워드

  • Unity SoundManager (BGM/SFX 분리, 슬라이더 초기화, DefaultExecutionOrder)
  • ParticleManager (풀링, World 시뮬레이션, Quaternion.LookRotation(Vector3.up))
  • 가산형 스테이지 스케일링 (체력/스피드 절대값 적용, 기준값 캐시)
  • 에디터 Hierarchy 트리 뷰 오류 대응

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

  • 오디오 시스템은 믹서 없이도 BGM 1소스 + SFX 풀만으로 충분히 관리 가능하다. 중요한 건 초기화 시점UI 연동이다.
  • 슬라이더는 표시값과 실제 볼륨 동기화가 핵심. SetValueWithoutNotify로 초기 표시를 맞추고, 값 변경은 콜백에서 처리한다.
  • 파티클은 “프리팹 축”과 “시뮬레이션 공간”을 이해하면 방향 문제 대부분이 풀린다. 월드 시뮬레이션 + 월드 위쪽 정렬로 언제나 하늘로 뿜게 만들 수 있다.
  • 스테이지 스케일링은 퍼센트보다 가산형 절대값이 디버깅과 밸런싱에 명확하다. 스폰 시 기준값 캐시 → (기준 + 증가량 * (stage-1))로 매번 “절대 재설정”하는 패턴이 안전하다.

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

1) NullReferenceException (SoundManager가 먼저 준비 안 됨)

  • 문제정의: UpgradePanelController.OnEnable() → PlaySfx() 호출 시, sfxMap/풀이 아직 생성 전이라 NRE.
  • 시도: Awake 순서만 믿고 사용.
  • 해결방법: EnsureInit()로 게으른 초기화 + 실행순서 조정.
[DefaultExecutionOrder(-1000)]
public class SoundManager : MonoBehaviour {
    bool _inited;
    void Awake() => EnsureInit();
    void EnsureInit() {
        if (_inited) return;
        // bgmSource 생성, sfx 풀 생성, sfxMap 매핑...
        _inited = true;
    }
    public void PlaySfx(SfxId id, float v=1f) { EnsureInit(); /* ... */ }
}
  • 새롭게 알게 된 점: UI가 먼저 열릴 수 있으니 초기화 방어가 필수.
  • 다시 만나면: Audio 부트스트랩 씬을 두거나, 싱글톤에 항상 EnsureInit()을 둔다.

2) 슬라이더 초기값 반영 안 됨

  • 문제정의: 슬라이더 표시값과 실제 볼륨이 다르게 시작.
  • 해결방법: 바인딩 시 초기값을 이벤트 없이 밀어넣고, 변경만 콜백에서 처리.
void InitSlider(Slider s, float init, UnityAction<float> onChanged){
    if (!s) return;
    s.onValueChanged.RemoveListener(onChanged);
    s.onValueChanged.AddListener(onChanged);
    s.SetValueWithoutNotify(init); // 표시값만 세팅
}
  • 새롭게 알게 된 점: 초기 렌더와 로직 트리거를 분리하니 깔끔해졌다.

3) 파티클 방향이 제멋대로임(하늘로 고정 필요)

  • 문제정의: 부모 회전에 따라 분사 방향이 바뀜.
  • 해결방법: 월드 시뮬레이션 + 월드 위쪽으로 회전 고정.
// 스폰 시
var rot = Quaternion.LookRotation(Vector3.up);
var go = Instantiate(vfxPrefab, pos, rot);
var ps = go.GetComponent<ParticleSystem>();
var main = ps.main;
main.simulationSpace = ParticleSystemSimulationSpace.World;
ps.Play();
  • 다시 만나면: 프리팹의 분사축(Z+)를 기준으로 생각하자.

4) 스테이지가 올라가도 적 능력치가 안 변함(퍼센트가 아니라 가산형으로)

  • 문제정의: 기존 구조는 피해량 배율/표기 불일치로 체감이 약함.
  • 해결방법: 스폰 시 기준 MaxHealth/Speed를 캐시하고, 스테이지마다 절대값 재설정.
// 체력
float baseMax;  // 스폰 시 1회 저장
void ApplyStageHealth(int stage, float addPerStage){
    int n = Mathf.Max(0, stage-1);
    SetMaxHealthAbsolute(baseMax + addPerStage * n, keepRatio:true);
}

// 스피드
float baseSpeed; // 스폰 시 1회 저장
void ApplyStageSpeed(int stage, float addPerStage){
    int n = Mathf.Max(0, stage-1);
    agent.speed = baseSpeed + addPerStage * n;
}
  • 체크포인트: buffAliveOnStageChange 켜서 살아있는 적도 즉시 갱신.

5) 에디터 ArgumentOutOfRangeException (Hierarchy)

  • 문제정의: Hierarchy 트리뷰가 그리는 동안 목록이 변해 인덱스 오류.
  • 해결방법: 검색 필터 해제 → 레이아웃 리셋 → Hierarchy 관련 플러그인 OFF → Library/ 재생성 순으로 정리.
  • 메모: [ExecuteInEditMode]와 OnValidate에서 오브젝트 생성/삭제 금지.

📝 메모

오늘은 기초를 다시 튼튼히 다진 날이었다. 특히 초기화 시점절대값 스케일링의 중요성을 제대로 체감했다. 퍼센트보다 가산형이 내 프로젝트 흐름에 훨씬 명확했다. “보이는 것(파티클/사운드)”을 먼저 단단히 만들고, 구조를 그 위에 쌓아가니 마음이 한결 편해졌다. 내일은 업그레이드 밸런스 숫자를 손보고, 스테이지 전환 연출(페이드/사운드 큐)까지 깔끔히 묶어보자. 🙂


반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 10:30 ~ 12:30 : 캐논 업그레이드 시스템 1차 구현
    • 발사력/공격 속도/탄속/스플래시 반경 단계별 설계
    • 업그레이드 버튼과 비용(골드) 차감 로직 연결

🍽️ 점심시간

  • 13:00 ~ 14:00 : 점심

✅ 오후

  • 14:00 ~ 15:00 : GoldUI 수정 및 Enemy 히트 파티클 추가
  • 15:00 ~ 16:00 : Generic Singleton 베이스 클래스 추가 → 매니저 공통화
  • 16:00 ~ 17:30 : Upgrade UI 고도화 + EnemyManager/GameManager/StageManager 정리
    • 스테이지 클리어 → 보상 지급 → 업그레이드 패널 오픈 플로우 연결

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁

✅ 저녁

  • 19:30 ~ 21:00 : 이미지 에셋 작업
    • 배경 제거 PNG 정사각 리사이즈, 축 가이드( x,y,z ) 오버레이 버전 제작

✅ 오늘 학습 키워드

  • Cannon Upgrade Flow(비용·단계·적용·피드백)
  • Generic Singleton로 매니저 통합
  • Stage → Reward → Upgrade UI 상태 전이
  • Particle 히트 피드백 / 풀링 기초
  • GoldUI 데이터 바인딩 정리

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

  • 업그레이드는 데이터(현재 단계/최대 단계/비용)–로직(검증/적용)–UI(표시/버튼) 를 분리해야 안정적이다. UI는 “눌렀다”를 알리고, 실제 적용/검증은 시스템이 한다.
  • 매니저가 늘어날수록 초기화 순서/중복 인스턴스 이슈가 커진다. Generic Singleton으로 공통 규약을 두니, 생성·파괴·DontDestroyOnLoad 정책을 한 곳에서 통일할 수 있었다.
  • 전투 피드백(히트 파티클, 사운드)은 정답이 아니라 체감이다. 먼저 “보인다/느껴진다”를 완성하고, 이후 과하게 눈에 띄는 지점을 줄이자는 흐름이 효율적이다.
  • 에셋 작업(배경 제거/정사각)은 귀찮아 보여도 UI 일관성가독성에 바로 영향을 준다. 결과적으로 업그레이드 화면 완성도가 한 단계 올라갔다.

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

1) 업그레이드 누적 적용 버그 (연타 시 단계/비용 불일치)

  • 문제정의: 버튼을 빠르게 연타하면 단계와 골드가 어긋남.
  • 시도: 버튼 인터랙션 잠금, 로직 내 2중 체크.
  • 해결 코드:
public bool TryUpgrade(ref int level, int max, ref int gold, int cost, Action apply)
{
    if (level >= max) return false;
    if (gold < cost) return false;

    // 원자적 처리
    gold -= cost;
    level++;
    apply?.Invoke();
    return true;
}
  • 새롭게 알게 된 점: UI 잠금만 믿지 말고 도메인 로직에서 최종 검증이 필수.

2) Singleton 중복 생성(NRE, 초기화 순서 꼬임)

  • 문제정의: 여러 씬에서 매니저 프리팹이 중복으로 살아나 예기치 않은 참조 에러.
  • 해결 코드 (Generic Singleton):
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    static T _instance;
    public static T I => _instance;

    protected virtual void Awake()
    {
        if (_instance != null && _instance != this as T)
        {
            Destroy(gameObject);
            return;
        }
        _instance = this as T;
        DontDestroyOnLoad(gameObject);
    }
}
  • 다시 만나면: 매니저는 하나의 부트스트랩 씬에서만 생성하고, 다른 씬엔 프리팹을 두지 않는다.

3) 히트 파티클 과다 생성(프레임 드랍)

  • 문제정의: 다수 적 동시 타격 시 파티클 Instantiate 남발.
  • 해결 코드(간단 풀링):
Queue<ParticleSystem> pool = new Queue<ParticleSystem>();

public ParticleSystem Get()
{
    if (pool.Count > 0) return pool.Dequeue();
    return Instantiate(hitParticlePrefab);
}

public void PlayAt(Vector3 pos)
{
    var ps = Get();
    ps.transform.position = pos;
    ps.gameObject.SetActive(true);
    ps.Play();
    StartCoroutine(ReturnWhenDone(ps));
}

IEnumerator ReturnWhenDone(ParticleSystem ps)
{
    yield return new WaitWhile(() => ps.isPlaying);
    ps.gameObject.SetActive(false);
    pool.Enqueue(ps);
}
  • 새롭게 알게 된 점: “보이는가?” 다음엔 “몇 개까지 버티는가?”.

4) GoldUI 숫자 갱신 타이밍 지연

  • 문제정의: 골드 차감은 되었는데 UI 반영이 한 프레임 늦게 보임.
  • 해결 방법: 골드 변경을 이벤트로 발행하고, UI가 즉시 구독하여 적용.
public event Action<int> OnGoldChanged;

public void AddGold(int amount) { gold += amount; OnGoldChanged?.Invoke(gold); }
public bool SpendGold(int cost)
{
    if (gold < cost) return false;
    gold -= cost; OnGoldChanged?.Invoke(gold);
    return true;
}

📝 메모

어제의 하이라이트는 캐논 업그레이드였다. 숫자가 오르는 손맛, 파티클이 터지는 시각 피드백, 그리고 골드가 딱 맞게 차감되는 느낌까지 하나하나 맞물리니 화면이 살아났다. 동시에 매니저 구조를 정리하니 머릿속도 정리된 느낌. 에셋 손질까지 마무리하니 업그레이드 화면이 확실히 또렷해졌다. 욕심내지 말고, 오**균형(밸런스/비용/단계캡)**부터 다듬자. 🙂


반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 11:30 : HP/MP/EXP 컨디션–UI 연동
    • PlayerCondition 이벤트 → UIConditionBinder 슬라이더/텍스트 바인딩
    • 초기값 미반영 이슈 해결(구독 직후 강제 갱신)
  • 11:30 ~ 12:00 : 디버그 입력 점검
    • 새 Input System 대응(키 입력 미동작 수정)

🍽️ 점심시간

  • 13:00 ~ 14:00 : 점심

✅ 오후

  • 14:00 ~ 15:30 : CarAI 안정화
    • 도착 판정 nodeReachDistance 확대, XZ 평면 거리로 판정
    • 기즈모 반경 = 도착 반경 동기화
  • 15:30 ~ 16:00 : 속도 UI(km/h) 출력 추가
  • 16:00 ~ 18:00 : 챌린지반 강의 – AssetBundle / Addressables

🍽️ 저녁시간

  • 18:00 ~ 19:00 : 저녁

✅ 저녁

  • 19:00 ~ 20:00 : 카메라
    • Orthographic 등각 추적 카메라 스크립트 적용(오프셋+SmoothDamp)
  • 20:00 ~ 21:00 : 전투/이펙트
    • Animator 파라미터(Spin_Attack Trigger, Gun_Attack Bool) 헬퍼 작성
    • 스핀 어택 OverlapSphere 히트 + 옆으로 노크백
    • 스핀 시작/끝 이벤트로 루프 파티클 ON/OFF
    • 프리팹 자식으로 파티클 생성(위치 고정)
  • 21:00 ~ : 차량에 Gun 프리팹 장착(기능 구현은 내일)

✅ 오늘 학습 키워드

  • UGUI 바인딩 (슬라이더/텍스트 이벤트 갱신)
  • UnityEvent 흐름(구독 타이밍/초기 동기화)
  • New Input System 대응(디버그 키 입력)
  • CarAI 도착 반경 조정 & XZ 평면 거리 판정
  • Gizmo 표기와 판정 반경 동기화
  • OverlapSphere 히트 체크
  • Rigidbody 노크백(ForceMode.VelocityChange)
  • Animator 파라미터(Trigger/Bool) 제어
  • 파티클 루프(스핀) / 원샷(히트) 분리
  • Orthographic Follow Camera(SmoothDamp, 오프셋)
  • Git LFS로 대용량 에셋 관리
  • AssetBundle vs Addressables (주소/라벨 기반 로딩)

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

  • UI는 데이터→이벤트→바인딩 루프가 핵심. 구독 직후 강제 동기화를 넣으면 초기 표시가 안정적이다.
  • CarAI의 “도착”은 기즈모 크기가 아니라 거리 임계값으로 판정된다. 고속에선 반경을 키우고 Y를 무시(XZ) 하면 안정적.
  • 전투 이펙트는 **상태 루프(스핀 동안)**와 히트 원샷을 분리하면 제어가 간단해진다.
  • 대형 파일은 처음부터 LFS로 관리해야 push 이슈가 없다.
  • Addressables는 AssetBundle을 래핑해 주소/라벨 기반 로딩으로 운영을 단순화한다.

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

1) 슬라이더가 값 반영 안 됨

  • 정의: 씬 시작 시 HP/MP/EXP가 0으로 보임.
  • 시도: 이벤트만 연결.
  • 해결 방법: 구독 직후 ForceNotify(초기 브로드캐스트) 호출.
  • 새롭게 알게 된 점: UI는 “언제 구독했는가”가 중요.
  • 다시 만나면: 바인더 템플릿에 초기 동기화 호출을 기본 포함.

2) CarAI가 고속에서 노드 놓침/미끄러짐

  • 정의: Max RPM↑ 시 코너에서 지나침.
  • 시도: 다양한 보간/룩어헤드 실험.
  • 해결 방법: nodeReachDistance 확대 + XZ 거리 판정, 기즈모 반경 동기화.
  • 새롭게 알게 된 점: 단순한 해법이 체감상 더 낫다.
  • 다시 만나면: 속도 구간별 반경 가변만 소폭 추가.

3) 스핀 파티클이 매번 안 나옴

  • 정의: 적을 맞출 때만 나오거나 1회만 재생.
  • 시도: Instantiate 위치/부모 지정, 변수명 충돌 수정.
  • 해결 방법: 스핀 시작/끝 이벤트에서 루프 파티클 ON/OFF, 필요 시 히트 스파크는 원샷으로 별도 처리.
  • 새롭게 알게 된 점: 파티클은 루프원샷 역할 분리.
  • 다시 만나면: Object Pool로 전환해 성능·GC 최적화.

4) 100MB 파일 Push 실패

  • 정의: GitHub 용량 제한 경고.
  • 시도: 일반 커밋/푸시.
  • 해결 방법: 해당 경로를 Git LFS로 트래킹, 필요 시 과거 이력 정리.
  • 새롭게 알게 된 점: 리소스 경로가 바뀌면 다시 LFS에 등록 필요.
  • 다시 만나면: .gitattributes에 패턴 등록(예: .png, 특정 경로).

📝 메모

오늘은 Craft UI를 연결하면서 NRE를 널 가드로 정리했다. CarAI는 도착 반경을 키워 고속 미끄러짐을 완화했고, 초기 UI 값은 구독 직후 강제 동기화가 확실하다는 걸 체감했다. 구현을 복잡하게 하기보다 단순한 해법이 체감 품질을 올린다는 점을 다시 확인. 내일은 Gun 시스템 설계를 시작해 최소 발사 루프를 띄울 예정이다.


지금 구현중인 차를 이용한 방치형 RPF 만들기~

반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 10:00 : 개인 시간
  • 10:00 ~ 11:00 : 유니티 심화 프로젝트 발제
  • 11:00 ~ 12:00 : 팀 자기소개 & 협업/기획 논의

🍽️ 점심시간

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

✅ 오후

  • 14:00 ~ 14:30 : 팀 회의 (점심 이후)
  • 14:30 ~ 15:00 : 개인 프로젝트 – URP 전환 체크 & 재질 교체
  • 15:00 ~ 17:00 : 개인 프로젝트 – CarAI 트랙/노드 로직 수정 & 디버깅

🍽️ 저녁시간

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

✅ 저녁

  • 19:00 ~ 20:00 : 개인 프로젝트 – 스플라인 설계/가시화, NavMesh 재베이크/파라미터 조정
  • 20:00 ~ 21:00 : 기획팀 협업 미팅

✅ 오늘 학습 키워드

  • URP 전환: URP/Lit 재질 매핑(Albedo/Metallic/Normal/AO/Emission), Clear Coat
  • AI Navigation 전환 경고(Deprecated 창 → Window > AI > Navigation)
  • NavMeshSurface: Collect 범위/레이어 제한, Agent Radius, Min Region Area, Voxel Size
  • CarAI 트랙 노드: useTrackNodes/loopTrack/nodeReachDistance/trackNodes
  • 경로 스무딩: Catmull-Rom 스플라인 샘플링(+ NavMesh.SamplePosition 투영)
  • WheelCollider GetWorldPose & 우측 바퀴 미러링 180° 오프셋
  • BaseCondition + IValueChangable: ValueChanged(int) virtual, 이벤트로 UI 연동
  • 비트마스크 계산 정정: NavMeshLayerBite |= (1 << area)

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

URP로 갈아타면 HDRP 전용 셰이더는 핑크가 되니, 재질을 URP/Lit 로 교체하고 맵을 재배치해야 한다. 네비는 구(舊) Navigation 창 대신 AI Navigation 패키지를 써야 하며, NavMesh는 **선(Line)**이 아니라 면(폭 있는 메시/콜라이더) 위에만 베이크된다. CarAI는 무작위 경로보다 노드 기반이 안정적이고, 노드 간 직선(Lerp) 대신 Catmull-Rom 스플라인 으로 샘플링하면 코너가 부드럽다. 우측 바퀴가 180° 뒤집히는 건 메쉬 미러링 축 문제라

rot * Quaternion.Euler(0,180,0)

로 보정했다. 공통 상태 관리는

BaseCondition

에 넣고,

ValueChanged(int)

를 virtual로 둬 파생에서 선택적으로 오버라이드할 수 있게 했다.


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

1) URP 전환 후 자동차가 핑크

  • 정의: HDRP 전용 셰이더라 URP에서 렌더 실패.
  • 시도: 프로젝트 전체 업그레이드, 머티리얼 개별 교체.
  • 해결: URP/Lit로 변경 후 맵 재할당(Albedo/Metallic/Normal/AO/Emission), 유리는 Transparent.
  • 새롭게 앎: URP 12+의 Clear Coat로 자동차 페인트 질감 일부 대체 가능.
  • 다시 만나면: 에셋 임포트 시 URP 변환 프로파일부터 적용, 자동 변환 안 되는 커스텀 셰이더는 Shader Graph로 포팅.

2) 오른쪽 바퀴가 180° 돌아감

  • 정의: 우측 바퀴 메쉬가 미러링되어 GetWorldPose 회전이 반대로 적용.
  • 시도: 트랜스폼 축/스케일 확인, 상위 오브젝트 회전 점검.
  • 해결: 우측만 rot * Quaternion.Euler(0,180,0) 보정(임시), 가능하면 프리팹 피벗 정리.
  • 새롭게 앎: lossyScale.x < 0면 미러링 의심.
  • 다시 만나면: “피벗 래퍼” 생성 → 코드에는 래퍼를 쓰고 메쉬는 로컬 회전 고정.

3) 트랙이 각져서 부자연스러움

  • 정의: 노드 간 직선 보간으로 급커브에서 조향이 튐.
  • 시도: Lerp, 웨이포인트 간격 축소.
  • 해결: Catmull-Rom 스플라인으로 세그먼트당 8~16 포인트 샘플링, NavMesh.SamplePosition으로 트랙 중앙에 스냅.
  • 새롭게 앎: 스플라인은 노드를 통과(C¹ 연속)해서 차량 움직임이 자연스러움.
  • 다시 만나면: 속도에 따라 샘플 수를 가변 조절(속도↑ → 샘플↑), nodeReachDistance 튜닝.

📝 메모

  • TrackPath()가 웨이포인트를 계속 붙이므로 리스트 길이 관리(슬라이딩 윈도우) 필수
  • NavMesh 베이크: 트랙 레이어만 포함, Agent Radius ≤ 도로 반폭
  • 내일: 스플라인 최종 적용 + 스포너 연결(MVP 루프 완성) + HUD(HP/골드/스테이지) 초안

오늘 새로운 팀 배정이 됐는데 11조로 배정을 받았고 29조 기획분들과 협업을 하게 되었다. 새로운 우리팀원분들도 성격이 너무 좋아보여서 다행이다 ㅎㅎ.. 기획분들중에서 저저번에 같이 팀플을 진행했던분이 계셔서 기획과 협업도 문제없을거라 생각한다 오늘 첫날이지만 회의를 꽤 많이 진행했고 서로의 의견을 나누며 하다보니 생각보다 기획분들과 협업이 쉽지않다고는 생각했다 하지만 다행히 진행이 잘 됐고 중간을 맞추는게 쉽지않았지만 잘 해결됐다 기획분들도 너무 좋으신분들이라 다행이다ㅎㅎ 앞으로 이번주에 팀 프로젝트를 진행하며 개발팀은 개인과제진행하고 기획분들은 다음주에 같이 협업해서 진행할 팀프로젝트 기획을 작성하게 된다. 벌써 다음주에 어떤 게임을 팀 프로젝트로 진행할지 너무 기대된다!! 내일도 화이팅!!!


반응형
반응형

🗓️ 오늘 하루 일정

✅ 오전

  • 09:00 ~ 11:30 : Craft UI 연결 및 프리뷰 슬롯 NRE 수정
  • (countText 널 가드 처리, 버튼/아이콘 점검)
  • 11:30 ~ 12:00 : NPC 대화 타이핑 기능 점검 (스킵/완료 분기 처리)

🍽️ 점심시간

  • 13:00 ~ 14:00 : 점심

✅ 오후

  • 14:00 ~ 16:00 : 팀 프로젝트 발표
  • 16:00 ~ 18:00 : 팀원들과 회의 및 의견 교환

🍽️ 저녁시간

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

✅ 저녁

  • 19:00 ~ 20:30 : 단원평가 진행 및 팀원들과 대화
  • 20:30 ~ 21:00 : TIL 작성 및 하루 마무리

✅ 오늘 학습 키워드

  • Craft UI
  • NPC 대화 타이핑
  • 팀 프로젝트 발표
  • 단원평가

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

오늘 오전에는 Craft UI와 NPC 대화 관련 세부 버그를 수정하며 UI 안정성을 다졌다. 오후에는 팀 프로젝트 발표를 통해 그동안 준비한 결과물을 공유했고, 팀원들과 발표 후 회고를 진행하며 서로의 개선점과 성과를 나눴다. 저녁에는 단원평가를 치르면서 학습한 내용을 점검했고, 이후 다시 팀원들과 의견을 나누며 하루를 마무리했다.


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

  1. 문제정의: Craft UI 프리뷰 슬롯에서 NRE 발생
    • 시도: countText 접근 시 널 가드 추가, 버튼 및 아이콘 참조 재확인
    • 해결 방법: 널 체크 조건을 추가하고 인스펙터에서 잘못된 연결 수정
    • 새롭게 알게 된 점: UI 연결 시 참조가 빠진 경우 런타임에서 예상치 못한 예외가 발생할 수 있음
    • 다시 만나게 된다면: UI 초기화 시점에서 참조 유효성 검증 코드를 넣어 예방할 것

📝 메모

오늘 발표를 하면서 팀원들과 함께 준비한 것들을 공유할 수 있어 뿌듯했다. 긴장도 했지만, 서로 피드백을 주고받으면서 더 성장할 수 있다는 점이 좋았다. 단원평가로 공부한 내용을 다시 확인할 수 있어서 정리하는 시간이 된 것도 의미 있었다. 내일은 오늘 발표에서 받은 피드백을 토대로 개선 작업을 이어가고 싶다.

팀프로젝트가 또 끝났다 이번 팀원들과 또 헤어지게되어서 좀 아쉽지만 덕분에 많이 즐거웠다!


반응형