모딩/마인크래프트 모드 개발 일지

[마인크래프트 모딩]#14 주변 아군에게 광역 버프를 주는 '좀비 지휘관'

kimchangmin02 2025. 6. 29. 11:32

오늘은 좀비 군단에 '지휘관' 역할을 하는 몹을 추가한 과정을 기록해보겠음. 이 녀석의 임무는 전투에 직접 참여하기보다, 주변 아군들을 강화해서 전선을 단단하게 만드는 거임. 이름은 '좀비 지휘관(Zombie Commander)'.

처음 기획한 핵심 기능은 10초마다 주변의 아군 좀비들에게 최대 체력 +5 버프를 계속 걸어주는 거였음. 이걸 구현하기 위해 어떤 개념들이 필요했는지 이론 중심으로 정리해봄.

핵심 이론 1: 고유 행동 만들기 - 커스텀 AI Goal

몹에게 "10초마다 버프를 줘"라는 행동을 시키려면, 먼저 그런 행동 자체를 정의해야 함. 이건 바닐라에 없는 로직이라 직접 만들어야 했음.

  • AuraBuffGoal.java 라는 클래스를 만듦.
    • 이 클래스는 마인크래프트의 Goal 클래스를 상속받음. 즉, 몹이 할 수 있는 하나의 '행동 단위'가 되는 거임.
    • 이 Goal의 핵심은 내부에 타이머를 두는 거임. tick() 메소드가 매 틱(1/20초)마다 호출되는데, 이 타이머를 1씩 계속 증가시킴.
    • 타이머가 200틱(10초)이 되면, 주변의 엔티티를 스캔하는 로직을 실행하고 타이머를 0으로 리셋함.
    • 이렇게 '주기적인 행동'의 뼈대를 만들었음.

핵심 이론 2: 다른 엔티티 능력치 수정 - Attribute 시스템

주변 좀비들의 최대 체력을 어떻게 올릴까? 여기서 setter, getter를 직접 건드리는 건 구식이고 위험한 방식임. 마인크래프트의 표준 방식은 '속성(Attribute)' 시스템을 이용하는 거임.

  • 모든 엔티티의 최대 체력, 이동 속도, 공격력 등은 Attributes.MAX_HEALTH 같은 '속성'으로 관리됨.
  • 우리가 할 일은 버프를 줄 대상의 AttributeInstance를 가져와서, 거기에 AttributeModifier라는 '수정치'를 더해주는 거임.
  • 이 '수정치'에는 고유한 UUID를 부여할 수 있음. 이걸로 나중에 "내가 준 버프가 어떤 거지?"라고 식별할 수 있음. 매우 중요한 부분임.

핵심 이론 3: '왜 안 되지?'의 주범 - 서버와 클라이언트 동기화

처음 만들었을 때, 분명히 버프는 들어가는데 클라이언트(내 화면)의 체력바는 전혀 변하지 않는 문제가 있었음. 파티클은 잘만 보이는데 말이지.

  • 원인: AI Goal 로직은 서버에서만 돌아감. 서버는 주변 좀비의 최대 체력이 25, 30, 35로 오르는 걸 알고 있지만, 클라이언트는 그 사실을 전혀 통보받지 못했기 때문에 계속 20으로 그림.
  • 해결책: 클라이언트에게 "이 속성 바뀌었으니 새로 그려!"라고 알려줘야 함. 이걸 트리거하는 방법은 바로 AttributeModifier를 올바르게 업데이트하는 거임.
    1. healthAttribute.removeModifier(OUR_BUFF_UUID): 먼저 내가 이전에 줬던 버프를 제거함.
    2. double newAmount = oldAmount + 5.0;: 이전 버프 값에 5를 더해서 새로운 누적값을 만듦.
    3. healthAttribute.addPermanentModifier(newModifier): 이 '새로운 누적값'으로 Modifier를 만들어 다시 적용함.
  • 이렇게 remove -> add 과정을 거치니까, 마인크래프트 시스템이 "어? 속성이 진짜로 바뀌었네?"라고 감지하고 이 정보를 클라이언트로 보내줌. 덕분에 체력바가 정상적으로 업데이트됨. 이게 이번 개발의 가장 큰 수확이었음.

핵심 이론 4: AI 개선과 밸런스 조절

완성하고 보니 몇 가지 문제가 보였음.

  1. 밸런스: 3초마다 체력 5 증가는 너무 사기였음. AuraBuffGoal의 타이머를 60틱에서 200틱(10초)으로 늘려서 간단히 해결함.
  2. 멍청한 AI: 주변에 아군이 하나도 없는데 혼자 버프를 쓰고 있으면 너무 바보 같아 보임.

이걸 해결하기 위해 새로운 AI Goal, FollowAlliesGoal을 추가함.

  • 역할: 주변에 버프를 줄 대상이 없을 때, 가장 가까운 아군 좀비를 찾아 그쪽으로 걸어가게 만듦.
  • 우선순위: 이 FollowAlliesGoal의 우선순위를 AuraBuffGoal보다 높게 설정함.
  • 작동 방식:
    1. AI는 항상 우선순위가 높은 행동부터 하려고 함. 먼저 FollowAlliesGoal을 체크함.
    2. "주변에 아군이 없나?" -> FollowAlliesGoal canUse() true가 됨 -> 아군을 찾아 이동 시작.
    3. "주변에 아군이 있네?" -> FollowAlliesGoal canUse() false가 됨 -> 이 행동은 건너뛰고, 다음 우선순위인 AuraBuffGoal이 실행되어 버프를 줌.
  • 이렇게 AI 우선순위를 이용해 "아군 없으면 찾아가고, 있으면 버프 주고"라는 더 지능적인 행동 패턴을 만들었음.

결론

'좀비 지휘관'을 만들면서 배운 건, 결국 '고유 행동(Goal) 정의', '표준 시스템(Attribute) 활용', '동기화 원리 이해' 이 세 가지가 커스텀 몹 제작의 핵심이라는 거임. 여기에 AI 우선순위를 조절해서 더 똑똑한 몹을 만드는 재미까지 챙길 수 있었음.