
1. AI 문제: 내 맘대로 안 움직이는 똑똑한(?) 몹들
가장 많은 시간을 쏟아부은 파트. AI는 정말 미묘해서 하나를 고치면 다른 게 터짐.
- 탱커 주민, 스킬을 한 번만 씀
- 현상: 도발 스킬을 딱 한 번만 쓰고 그 뒤로 감감무소식.
- 원인: 스킬 쿨타임을 숫자로 저장만 해놓고, 시간이 지나도 이 숫자를 줄여주는 코드가 없었음. 쿨타임이 영원히 0이 되지 않으니 다시는 스킬을 못 씀.
- 해결: 엔티티의 tick() 메소드(매 틱마다 실행되는 곳)에 "쿨타임이 0보다 크면 1씩 감소시켜라"라는 로직을 한 줄 추가해서 해결함.
- 소환사, 소환수가 다 죽어도 멀뚱멀뚱
- 현상: 전투가 끝나고 소환수가 다 죽었는데도, 소환사가 다시 소환할 생각을 안 하고 그냥 돌아다니기만 함.
- 원인: 소환 AI가 발동될 '계기(Trigger)'가 없었음. AI는 "소환수가 부족하다"는 건 알지만, "언제 그 사실을 체크해야 하는지"를 몰랐던 것.
- 해결: 소환 AI의 발동 조건에 "주변에 공격할 적이 있을 때" 라는 조건을 추가함. 평소에는 놀다가도 적을 발견하면 그제야 "어? 싸워야 하는데 소환수가 없네? 뽑아야겠다!" 라고 생각하게 만듦.
- 소환사, 맞으면 너무 빨리 도망감
- 현상: 맞자마자 우사인 볼트처럼 줄행랑을 쳐서 전투가 안 됨.
- 원인: 부모 클래스인 주민(Villager)에게 물려받은 기본 도망 AI(PanicGoal)의 속도 설정이 너무 높았음.
- 해결: 기존의 도망 AI를 강제로 제거하고, 속도가 1.0으로 고정된 새로운 PanicGoal을 직접 만들어 AI 목록에 추가해줌. 이제 맞으면 도망은 가되, 정해진 속도로만 도망감.
2. UI & 렌더링 문제: 눈에 보이는 게 이상할 때
AI 다음으로 골치 아팠던 시각적 버그들.
- 레벨업 UI 오류 (LevelingInfoLayer):
- 현상: new LevelingInfoLayer<>() 같은 코드가 "다이아몬드 연산자" 오류를 뿜으며 컴파일이 안 됨.
- 원인: 제네릭과 레이어 시스템을 너무 복잡하게 사용하고 있었음.
- 해결: 그냥 레이어 클래스 자체를 없애버림. 그리고 해당 엔티티의 렌더러(Renderer) 클래스에서 직접 font.drawInBatch 메소드를 써서 레벨, 체력 같은 글자를 그리도록 코드를 옮김. 훨씬 직관적이고 안정적으로 바뀜.
- 숫자가 두 개로 겹쳐 보이는 현상
- 현상: 체력이나 레벨 숫자가 유령처럼 두 개로 겹쳐서 보임.
- 원인: 부모 클래스의 렌더링 메소드(super.render())를 호출해서 기본 UI를 그리고, 그 위에 내가 만든 커스텀 UI를 또 그리면서 같은 내용이 두 번 그려지고 있었음.
- 해결: super.render()를 호출하는 부분을 지우거나, 내가 직접 그리는 UI에서 부모가 그려주는 내용은 빼고 그리는 방식으로 해결.
- 경험치 바, 레벨업 로직 문제
- 현상: 서버에서는 분명 레벨업을 했는데, 클라이언트(내 화면)의 경험치 바나 레벨 표시에 반영이 안 됨.
- 원인: 데이터 동기화 부재. 서버와 클라이언트는 별개의 세상이라, 서버에서 일어난 일을 클라이언트에게 "알려줘야만" 함.
- 해결: 네트워크 패킷 시스템을 사용함. 주민이 레벨업 하는 순간, 서버에서 "이 주민, ID XXX번, 레벨 Y로 올랐음!"이라는 정보가 담긴 편지(패킷)를 만들어서 클라이언트로 발송함. 편지를 받은 클라이언트는 그제야 해당 주민의 UI를 업데이트함.
3. 충돌과 마법: 게임이 터지거나 이상하게 변할 때
가장 황당했던 문제들.

- 번개 마법사가 마녀로 변하는 현상
- 현상: 내가 만든 번개 마법사 주민이 자기 번개에 스치기만 하면 갑자기 마녀로 변해버림.
- 원인: 마인크래프트 기본 설정. 바닐라 주민은 번개를 맞으면 무조건 마녀로 변함. 내가 만든 마법사도 결국 '주민'을 상속받았기 때문에 이 특성까지 그대로 물려받은 것.
- 해결: 주민 클래스에 있는 thunderHit() (번개 맞았을 때) 메소드를 내 마법사 클래스에서 재정의(@Override)하고, 내용을 아무것도 없는 빈 상태로 둠. "너는 번개 맞아도 아무것도 하지 마"라고 명시적으로 알려주니 해결됨.
- 아군끼리 때려도 데미지 0 (Friendly Fire)
- 현상: 눈사람이 좀비를 열심히 때리는데 데미지가 전혀 안 들어감.
- 원인: 아군 판별 시스템의 로직 충돌. AllyDamageHandler(좀비 동맹용)와 VillagerAllyDamageHandler(주민 동맹용)가 있었는데, AllyDamageHandler가 너무 넓은 범위로 주민까지 '아군'으로 취급해버림. 그래서 '주민 팀'인 눈사람이 '좀비 팀'인 좀비를 때리자, 시스템이 "어? 둘 다 isAlly()가 true네? 아군끼리 공격했으니 데미지 무효!" 라고 판단해버림.
- 해결: 각 데미지 핸들러가 자기 팀만 책임지도록 역할을 명확히 분리함. AllyDamageHandler는 isZombieAlly(), VillagerAllyDamageHandler는 isVillagerAlly() 메소드만 보도록 수정. 그리고 눈사람 AI가 공격 대상을 정할 때 VillagerAllyDamageHandler.isAlly()를 기준으로 "우리 팀이 아닌 적"을 공격하도록 명시해줌.
4. 컴파일 지옥: 코드 한 줄이 아쉬울 때
- IMob vs Enemy, resetPose vs loadPose 등: 1.18.2 버전의 클래스/메소드 이름을 최신 버전과 헷갈려서 생긴 문제들. 이건 그냥 버전에 맞는 올바른 이름을 찾아서 바꿔주면 해결됨.
- 생성자 오류 (::new): EntityType.Builder.of(클래스::new, ...) 문법이 계속 오류. 이 문법은 해당 클래스 안에 public 클래스이름(EntityType type, Level level) 형태의 생성자가 '정확하게' 있어야만 작동하는 거였음. 파라미터가 다르거나 public이 아니면 못 찾음. 엔티티 클래스에 정해진 형식의 생성자를 추가해주니 해결됨.
'모딩 > 마인크래프트 모드 개발 일지' 카테고리의 다른 글
| [마인크래프트 모딩]#20 전방에 충격파를 날리는 주민 (15) | 2025.07.06 |
|---|---|
| [마인크래프트 모딩]#19 '궁수 타워' 만들기 (15) | 2025.07.04 |
| [마인크래프트 모딩]#17 나만의 소환사 주민 만들기 (9) | 2025.07.02 |
| [마인크래프트 모딩]#16 나만의 RPG 파티 만들기! (마법사 주민 편) (12) | 2025.07.01 |
| [마인크래프트 모딩]#15 상속이용및 기타 자잘한것들 수정 (15) | 2025.07.01 |