커스텀 모델과 감정 표현

플러그인이 플레이어를 자기 모델로 그리고, 가만히 서 있을 때 감정 표현을 재생합니다. 샘플: custom_model.

모델은 게임의 뼈대를 그대로 써야 합니다. 그래서 걷기, 달리기, 수영, 잠들기, 도구 휘두르기 같은 게임의 모든 동작이 따로 만들지 않아도 그대로 재생됩니다. 뼈가 다르면 맞춰 주지 않고 거절합니다.

  1. 빠르게 만들기
  2. 등록
  3. 코드
  4. 동작 규칙
    1. 모델
    2. 감정 표현
  5. 검사 규칙
    1. 공통
    2. 뼈대
    3. 모델
    4. 감정 표현
  6. 조심할 것

빠르게 만들기

  1. template.glb를 블렌더에서 엽니다. (파일 › 가져오기 › glTF 2.0, Bone Dir는 Blender)
  2. 뼈는 그대로 두고 메시만 새로 만들어 스키닝합니다. 뼈의 이름, 개수, 부모 관계를 바꾸면 안 됩니다.
  3. 파일 › 내보내기 › glTF 2.0, 형식 glTF Binary (.glb), 애니메이션 끄기, +Y Up 켜기.
  4. fix_model.py와 rig.json을 같은 폴더에 두고 정규화합니다.

    python fix_model.py my_model.glb out.glb
    
  5. out.glb를 플러그인 assets/plugins/<플러그인 이름>/에 넣고 rules.json에 등록합니다.

4번을 건너뛰면 대부분 거절됩니다. 블렌더는 뼈의 기준 회전을 정확히 보존하지 못합니다. 아래를 향한 뼈(발, 엄지)가 20°쯤 틀어지고, 가져오기 옵션에 따라 더 많은 뼈가 돌아갑니다. 그대로 쓰면 발목이 꼬이므로 서버가 거절합니다. fix_model.py는 뼈 위치와 메시 모양은 그대로 둔 채 회전을 게임 값으로 되돌리고, 바인드 행렬과 애니메이션 값을 다시 계산합니다.

체형은 바꿀 수 있습니다. 뼈의 위치를 옮기면 정규화 후에도 그대로 남습니다. 단, 뼈 길이는 원래의 0.5~2배 안이어야 합니다.

등록

{
  "models_add": {
    "blue_cat": {"model": "res://plugins/custom_model/blue_cat.glb", "name": "파란 고양이"}
  },
  "emotes_add": {
    "wave": {"file": "res://plugins/custom_model/wave.glb", "name": "손 흔들기", "loop": false}
  }
}
키 값
표의 키 (id) 영문 소문자, 숫자, _, 32자 이하
model / file 플러그인 자기 폴더의 .glb: res://plugins/<플러그인 이름>/..., 실제 파일은 assets/plugins/<플러그인 이름>/...
name 표시 이름
loop (감정 표현) 끝나도 반복

다른 폴더나 게임의 파일은 쓸 수 없습니다.

코드

use greenhaven_plugin::*;

#[command("변신", "파란 고양이가 돼요")]
fn change(c: Command) {
    c.player().set_model("blue_cat");
}

#[command("인사", "가만히 서서 손을 흔들어요")]
fn wave(c: Command) {
    c.player().play_anim("wave");
}

#[on(Join)]
fn dress(e: Join) {
    e.player().set_model("blue_cat"); // 접속할 때마다 입히려면
}
함수 하는 일
Player::set_model(id) 이 서버에서 이 모델로 그림. 같은 월드의 모두에게 바로 보임
Player::clear_model() 원래 모습으로
Player::play_anim(id) 감정 표현 재생
Player::stop_anim() 재생 중인 감정 표현 끝내기

동작 규칙

모델

  • 연결되어 있는 동안만 유지됩니다. 계정의 옷차림은 바뀌지 않고 저장되지도 않습니다. 계속 입히려면 Join에서 다시 부르세요.
  • 서버를 나가면 아무것도 남지 않습니다. 다른 서버나 싱글플레이에 영향이 없습니다.
  • 모델을 입는 동안 게임의 옷과 장식은 표시되지 않습니다.
  • 도구는 게임과 같은 자리(오른손)에 들립니다.
  • 없는 id는 아무 일도 하지 않고 서버 로그에 남습니다.

감정 표현

감정 표현은 가만히 서 있을 때만 재생되는 동작입니다.

  • 걷기, 달리기, 점프, 수영, 잠자기, 도구 사용 중이면 시작되지 않습니다.
  • 재생 중에 움직이거나 어떤 행동이든 하면 바로 끝나고 게임의 동작으로 돌아갑니다. loop: true도 마찬가지입니다.
  • 같은 월드의 다른 플레이어에게도 보이고, 그 사람이 움직이면 똑같이 끝납니다.
  • 모델을 입지 않은 기본 동물에게도 재생됩니다. 뼈대가 같기 때문입니다.

검사 규칙

모든 파일은 서버 시작 때 검사하고, 게임이 받을 때 다시 검사합니다.

  • 서버에서 실패하면 그 항목만 빠지고 플러그인은 그대로 켜집니다. 로그에 이유가 나옵니다.
    plugin my_plugin: models_add knight refused: the bone RightFoot is turned 26.4° from the rig's rest (at most 1°): export it from the template
    
  • 게임에서 실패하면 그 플레이어는 원래 모습으로 그려집니다.

공통

항목 규칙
형식 GLB (glTF 2.0 바이너리). 전체 길이가 맞아야 하고 JSON + BIN 청크만
버퍼 파일 안에 하나. 외부 파일 경로 불가
접근자 모든 데이터가 범위 안. sparse 불가
확장 extensionsRequired 불가. 재질과 노드의 확장 불가
그 외 금지 카메라, 조명, 노드의 matrix

뼈대

항목 규칙
뼈 rig.json의 81개 전부. 이름과 부모 관계 일치
기준 회전 뼈마다 1° 이내
배율 1 (±1%)
길이 원래의 0.5~2배
노드 수 96개 이하

모델

항목 규칙
파일 크기 16MB 이하
삼각형 20,000개 이하
메시 / 재질 각각 4개 이하
스킨 정확히 1개, 조인트는 81개 뼈 전부. 모든 메시가 이 스킨에 묶임
정점 모든 정점의 조인트가 스킨 안의 뼈
프리미티브 삼각형만. 모프 타깃 불가
크기 높이는 게임 모델의 0.25~2배, 폭과 깊이는 2배 이하
이미지 4장 이하, PNG 또는 JPEG, 한 변 2048 이하, 파일에 내장
애니메이션 불가. 게임의 동작이 재생되고, 감정 표현은 별도 파일

감정 표현

항목 규칙
파일 크기 2MB 이하
내용 뼈대와 클립 1개. 메시, 스킨, 재질, 이미지 불가
채널 뼈의 회전. 이동은 Hips만. 크기 채널 불가
보간 LINEAR 또는 STEP
길이 30초 이하, 채널당 키 4096개 이하

블렌더의 감정 표현도 정규화합니다. 메시를 빼고 불필요한 채널을 지웁니다.

python fix_model.py --emote wave.glb out.glb

조심할 것

용량과 성능은 서버의 책임입니다. 받을 파일의 합이 200MB를 넘으면 서버 목록에 고사양으로 표시됩니다.

유료 상품을 흉내 낸 모델이나 저작권이 있는 캐릭터를 공개 서버에 올리면 서버 목록에서 제외될 수 있습니다.