◆Cobblemon Wiki

애드온 제작

Poser

서문

poser JSON은 기존 Poser처럼 포켓몬의 모든 애니메이션을 제어합니다. 포켓몬이 어떤 애니메이션을 언제 수행할지에 대한 같은 정보를 담고 있지만, 요청이 많았던 여러 개선점도 포함합니다. 예를 들어 여러 본을 사용하는 시선 애니메이션, 기술 애니메이션 지원, 개성 표현용 애니메이션 풀 선택 등이 있습니다. 새 Poser의 기능은 계속 유지될 예정이며, 애드온 제작자도 하드코딩된 Kotlin Poser와 같은 선택지를 사용할 수 있게 해 줍니다.

Poser 속성

Poser 파일의 각 섹션을 살펴보기 전에, 다양한 속성과 사용 방법을 먼저 알아봅니다. 이 섹션에서는 poser의 여러 함수, 각 함수에서 설정할 수 있는 옵션, 그리고 함수 작성 방식을 설명합니다. 이제 poser에는 q.<function> 형식의 항목이 들어갑니다. 이들은 molang 함수이며 여러 새로운 작업을 가능하게 합니다. q는 query를 뜻하고, 새 함수들의 표준 형식 일부입니다. 어떤 함수는 다른 함수 안에 넣을 수도 있습니다. 각 함수가 하는 일을 읽고 나면 그리 복잡하지 않으며, 애드온 제작자가 이전에는 할 수 없던 많은 작업을 할 수 있게 해 줍니다.

루트 본

rootBone 속성은 진화 애니메이션처럼 poser에 따로 지정되지 않은 범용 애니메이션에서 모델의 어떤 본을 루트 본으로 사용할지 지정합니다. 모델이 표준 본 형식을 따라 만들어졌다면, 이 값은 포켓몬 이름을 소문자로 쓴 것이면 됩니다. 구두점과 대소문자가 중요하므로 모델의 루트 본 이름과 정확히 일치하는지 확인하세요.

이 루트 본은 반드시 올바르게 지정해야 합니다. 그렇지 않으면 특정 범용 애니메이션에서 모델이 망가질 수 있습니다. 이런 애니메이션은 루트 본을 움직이고, 끝난 뒤 원래 위치로 되돌리지 않습니다. 그 결과 진화 후 모델 위치가 어긋날 수 있습니다.

아래는 간단한 rootBone 속성의 구성 예시입니다:

 "rootBone": "charizard",

초상화/프로필과 스케일/이동

Portrait와 Profile은 GUI나 메뉴에서 포켓몬을 렌더링할 때 사용하는 포즈입니다. Portrait는 왼쪽 파티 화면, 즉 파티 오버레이에서 사용되고, Profile은 파티 메뉴에서 사용됩니다. poser 파일은 이 포즈들에 Scale과 Translation 값을 지정해 포켓몬 렌더링용 카메라 위치를 제어합니다. 설정에서 활성화할 수 있는 개발 도구를 사용하면, 메뉴 안에서 포켓몬 주변의 카메라를 사용자 지정 키로 움직일 수 있습니다. 이 도구는 관련 단축키를 누를 때 Scale과 Translation 값을 출력합니다.

Scale 값은 Portrait 또는 Profile의 확대/축소 정도를 제어합니다. 1보다 작으면 축소되고, 1보다 크면 확대됩니다. 큰 모델의 경우 아무리 축소해도 카메라가 포켓몬 전체를 렌더링하지 못할 수 있습니다. 포켓몬의 뒷부분이 보이지 않는다면 Translation의 z 값을 늘려야 한다는 뜻입니다.

Translation 값은 Portrait 또는 Profile용 카메라 위치를 제어합니다. Translation은 xyz 좌표를 나타내는 3개의 값입니다. 주로 처음 두 값, 즉 x축과 y축 값을 조정하게 됩니다. X는 좌우, Y는 상하를 담당합니다. Z 값은 자주 쓰이지 않지만, 메뉴에서 완전히 렌더링되지 않는 매우 큰 모델에는 중요합니다. 보통 5의 배수인 음수 Z 값이 필요합니다.

아래는 앞서 언급한 속성들의 간단한 예시입니다:

   "portraitScale": 1.65,
   "portraitTranslation": [0, -0.6, 0],
   "profileScale": 1,
   "profileTranslation": [0, 0.15, 0],

포즈와 애니메이션

애니메이션을 만들 수 있는 포즈 타입과 애니메이션 타입이 몇 가지 있습니다. Poses는 대기 중이거나 이동 중인 상태처럼 포켓몬의 상태를 뜻합니다. 포즈에는 지상 대기, 지상 걷기, 물 위 대기 같은 애니메이션을 지정합니다. animation types는 각 포켓몬에 애니메이션을 지정할 수 있는 배틀 중 이벤트를 뜻합니다.

명확성을 위해 쓰러짐, 울음소리, 물리 공격 같은 애니메이션은 항상 이름 있는 애니메이션이라고 부르는 것이 좋습니다. 포즈에 적용되는 애니메이션과 구분하기 위해서입니다. 이 구분은 중요합니다. 하나의 포즈에 animations와 namedAnimations를 모두 지정할 수 있기 때문입니다. 이를 통해 떠 있거나 나는 포즈처럼 서로 다른 포즈에 다른 울음소리, 쓰러짐, 공격 애니메이션을 지정할 수 있습니다. 애니메이션이 지원한다면 물속 공격 애니메이션도 만들 수 있습니다. 이 과정은 뒤에서 자세히 설명합니다. 아래는 현재 선택할 수 있는 이름 있는 애니메이션 타입과 포즈 목록입니다.

애니메이션과 이름 있는 애니메이션

  • faint: animation.<pokemon>.faint - 포켓몬이 쓰러질 때 재생되는 애니메이션입니다.
  • cry: animation.<pokemon>.cry - 포켓몬을 꺼내거나 배틀이 시작될 때 재생되는 애니메이션입니다.
  • recoil: animation.<pokemon>.recoil - 포켓몬이 배틀에서 피해를 받을 때 재생되는 애니메이션입니다.
  • physical: animation.<pokemon>.physical - 포켓몬이 배틀에서 물리 기술을 사용할 때 재생되는 애니메이션입니다.
  • special: animation.<pokemon>.special - 포켓몬이 배틀에서 특수 기술을 사용할 때 재생되는 애니메이션입니다.
  • status: animation.<pokemon>.status - 포켓몬이 배틀에서 변화 기술을 사용할 때 재생되는 애니메이션입니다.
  • <배틀_기술>: animation.&lt;pokemon>.&lt;battle_move_name> - 포켓몬이 배틀에서 특정 기술을 사용할 때 재생되는 애니메이션입니다. 이 애니메이션 속성은 포켓몬의 애니메이션을 기존 액션 효과에 연결합니다. 예를 들어 리자몽의 커스텀 화염방사 애니메이션이나 포켓몬의 전용기 같은 식입니다.

포즈

  • “STAND”: animation.&lt;pokemon>.ground_idle - 포켓몬이 지상에서 대기할 때 재생되는 애니메이션입니다.
    • 이 포즈 타입은 배틀 대기에도 사용됩니다: animation.&lt;pokemon>.battle_idle
  • “PORTRAIT”: animation.&lt;pokemon>.portrait - 파티 오버레이, 즉 왼쪽 파티 GUI에서 재생되는 애니메이션입니다.
    • 이 포즈는 전용 애니메이션 대신 ground_idle을 사용하는 경우가 많습니다.
  • “PROFILE”: animation.&lt;pokemon>.profile - 파티 메뉴 또는 M 키를 눌렀을 때 재생되는 애니메이션입니다.
    • 이 포즈는 전용 애니메이션 대신 ground_idle을 사용하는 경우가 많습니다.
  • “WALK”: animation.&lt;pokemon>.ground_walk - 포켓몬이 지상에서 이동할 때 재생되는 애니메이션입니다.
  • “HOVER”: animation.&lt;pokemon>.air_idle - 포켓몬이 공중에서 대기할 때 재생되는 애니메이션입니다.
  • “FLY”: animation.&lt;pokemon>.air_fly - 포켓몬이 공중에서 이동할 때 재생되는 애니메이션입니다.
  • “FLOAT”: animation.&lt;pokemon>.water_idle - 포켓몬이 물속이나 물 위에서 대기할 때 재생되는 애니메이션입니다.
  • “SWIM”: animation.&lt;pokemon>.water_swim - 포켓몬이 물속이나 물 위에서 이동할 때 재생되는 애니메이션입니다.
  • “SLEEP”: animation.&lt;pokemon>.sleep - 포켓몬이 잠들었을 때 재생되는 애니메이션입니다. 보통 지상에서 사용됩니다.
  • “SHOULDER_LEFT”: animation.&lt;pokemon>.shoulder_left - 포켓몬이 플레이어의 왼쪽 어깨에 있을 때 재생되는 애니메이션입니다.
  • “SHOULDER_RIGHT”: animation.&lt;pokemon>.shoulder_right - 포켓몬이 플레이어의 오른쪽 어깨에 있을 때 재생되는 애니메이션입니다.

기본 애니메이션 호출 함수

Pose 또는 namedAnimation 애니메이션을 호출하는 방법은 세 가지입니다. 각각은 포켓몬 위에 애니메이션을 겹쳐 재생할 때 서로 다른 목적을 가집니다. Pose 애니메이션은 호출된 다른 애니메이션에 의해 덮어쓸 수 있는 기본 애니메이션으로 항상 q.bedrock()을 사용해야 합니다. NamedAnimations는 q.bedrock_stateful()로 기본 애니메이션 위에 겹치거나, q.bedrock_primary()로 재생 중 기본 애니메이션을 덮어쓸 수 있습니다. 각 이름 있는 애니메이션 타입에서 사용하는 기본 함수는 애니메이션이 지원한다면 바꿀 수 있습니다. 울음소리를 겹치지 않고 덮어쓰게 만들고 싶다면 그에 맞게 애니메이션을 제작하면 됩니다.

q.bedrock

q.bedrock() 함수는 구 Poser에서 익숙하던 애니메이션 호출 형식을 molang 함수로 바꾼 것입니다. 겉모습만 새로워졌을 뿐 이전과 같은 방식입니다. 괄호 안에 포켓몬과 애니메이션을 차례대로 적으면 됩니다. 이 함수는 주로 포즈에 애니메이션을 지정하는 데 사용됩니다. 이 애니메이션들은 필요할 때 Primary 또는 Stateful 애니메이션으로 덮어쓰도록 설계되어 있습니다.
아래는 "WALK" 포즈 타입에 걷기 애니메이션을 지정하는 q.bedrock 함수 예시입니다:

   "walking": \{
     "poseTypes": ["WALK"],
     "animations": [
       "q.bedrock('blastoise', 'ground_walk')"
     ]
   \},
q.bedrock_stateful

q.bedrock_stateful() 함수는 애니메이션 타입에 stateful 애니메이션을 지정할 수 있게 해 줍니다. Stateful animations는 포켓몬의 몇몇 본만 움직이고 현재 포즈 위에 겹쳐 재생되도록 만들어집니다. 예를 들어 울음소리 애니메이션이 포켓몬의 입이나 머리만 움직이는 식입니다. stateful 애니메이션은 애니메이션을 재생하기 위해 모델 전체의 제어권을 가져가지 않습니다.

아래는 poser에서 두 stateful 애니메이션인 cry와 recoil을 지정하는 예시입니다:

   "cry": "q.bedrock_stateful('blastoise', 'cry')",
   "recoil": "q.bedrock_stateful('blastoise', 'recoil')",
q.bedrock_primary

q.bedrock_primary() 함수는 애니메이션 타입에 primary 애니메이션을 지정할 수 있게 해 줍니다. Primary animations는 모델 전체의 제어권을 가져와 애니메이션을 재생하고, 이전에 재생 중이던 애니메이션을 지웁니다. 예를 들어 포켓몬의 물리 공격 애니메이션이 여기에 해당합니다. 포켓몬이 물리 기술을 사용하면 배틀 대기 애니메이션을 지우고 물리 공격 애니메이션을 재생해야 합니다. 이런 애니메이션은 보통 몸 전체와 여러 팔다리를 움직입니다. 물리 애니메이션이 끝나면 모델 제어권은 배틀 대기로 돌아가며, 그 사이에 짧은 전환 애니메이션을 재생하는 것이 좋습니다.

q.bedrock_primary에는 몇 가지 추가 속성이 있으며 다음 순서로 작성해야 합니다:

  1. group: 'blastoise' - 게임이 다음 애니메이션을 찾을 애니메이션 JSON입니다. 항상 포켓몬 이름이어야 합니다.
  2. 애니메이션: 'status' - 앞에서 지정한 애니메이션 JSON에서 게임이 호출할 애니메이션입니다. Primary 애니메이션은 보통 공격 애니메이션이나 쓰러짐 애니메이션이지만, 원한다면 다른 이름 있는 애니메이션으로 지정할 수도 있습니다.
  3. (optional) excluded labels: 'look' - 이 primary 애니메이션에 의해 덮어쓰이지 않을 독점 라벨 애니메이션입니다. excluded labels의 합리적인 용도는 look 애니메이션이 덮어쓰이지 않게 제외하는 것입니다. 이렇게 하면 애니메이션을 사용할 때도 대상을 계속 바라볼 수 있습니다.
  4. curve: 'q.curve('symmetrical_wide')' - 이 primary 애니메이션이 자신이 작성된 포즈로 들어가고 나올 때 사용할 보간 곡선입니다.

Primary 애니메이션은 포즈를 교체하는 것과 비슷하게 동작하므로, 하위 속성 안에 작성하는 q.curve 속성을 통해 특수한 보간 곡선 타입을 사용할 수 있습니다. 이 값들은 보간의 부드러움을 다르게 만들며, 다음 섹션에서 설명합니다.

아래는 poser에서 흔히 쓰는 primary 애니메이션 4개의 예시입니다:

   "faint": "q.bedrock_primary('blastoise', 'faint', q.curve('one'))",
   "physical": "q.bedrock_primary('blastoise', 'physical', q.curve('symmetrical_wide'))",
   "special": "q.bedrock_primary('blastoise', 'special', q.curve('symmetrical_wide'))",
   "status": "q.bedrock_primary('blastoise', 'status', 'look', q.curve('symmetrical_wide'))"
q.curve

q.curve() 함수는 q.bedrock_primary()의 하위 함수로, 애니메이션이 기본 포즈로 다시 보간되도록 합니다. 이를 통해 애니메이션 간 전환이 애니메이션 제작 시의 선형 키프레임이나 부드러운 키프레임과 비슷하게 동작합니다.

현재 q.curve 함수에는 세 가지 옵션이 있습니다:

  • one: 전혀 보간하지 않습니다. 한 애니메이션에서 다음 애니메이션으로 바로 넘어갑니다. 쓰러짐 애니메이션에 적합합니다.
  • symmetric: Blockbench의 부드러운 키프레임 두 개와 비슷한 방식으로 보간합니다. 권장되지는 않지만 선택지는 될 수 있습니다.
  • symmetrical_wide: Blockbench의 부드러운 키프레임 두 개와 비슷하게 보간하지만, 여유 폭이 더 넓습니다. 기술에서 전환할 때 권장되는 선택지입니다.

아래는 주요 q.curve 타입 2개의 예시입니다:

   "faint": "q.bedrock_primary('blastoise', 'faint', q.curve('one'))",
   "physical": "q.bedrock_primary('blastoise', 'physical', q.curve('symmetrical_wide'))",
q.array, q.random, math.random

앞서 언급한 함수 중 하나가 함수 안에서 'faint' 같은 애니메이션 타입 매개변수를 호출할 때, 그 값을 여러 애니메이션 중 하나를 호출할 수 있는 다른 함수로 대체할 수 있습니다. 포즈, 이름 있는 애니메이션, quirk를 뒷받침할 애니메이션이 충분하다면 이 세 함수로 무작위 애니메이션처럼 보이게 만들 수 있습니다.

  • q.array() - 이 함수는 호출될 때 나열된 애니메이션 타입 중 하나를 선택합니다. 각 옵션이 같은 가중치를 갖는 quirk 애니메이션 풀을 만들 때 자주 사용됩니다.
    • 다음 예시는 폴리곤Z가 1~10초마다 서로 다른 움찔 애니메이션 6개 중 하나를 quirk로 사용하게 합니다.
"q.bedrock_quirk('porygon-z', q.array('twitch1', 'twitch2', 'twitch3', 'twitch4', 'twitch5', 'twitch6'), 1, 10, 1)"
  • q.random() - 이 함수는 리소스가 로드될 때 나열된 애니메이션 타입 중 하나를 선택합니다. 테스트 결과, 게임 시작 시 또는 F3+T로 에셋을 새로고침할 때 애니메이션이 선택된다는 뜻입니다. 개발자에 따르면 이는 버그로 보입니다.
    • 다음 예시는 에셋을 새로고침하기 전까지 폴리곤Z가 1~10초마다 두 가지 움찔 애니메이션 중 하나만 quirk로 사용하도록 제한합니다.
"q.bedrock_quirk('porygon-z', q.random('twitch1', 'twitch2'), 1, 10, 1)"
  • math.random(0, 1) <  ?  : - math.random 함수와 삼항 조건 연산자(?와 : 부분)를 조합하면 게임이 숫자를 굴려 어떤 애니메이션 또는 애니메이션 묶음을 재생할지 결정하게 할 수 있습니다. 특정 애니메이션에 가중 확률을 주고 싶을 때 좋은 옵션입니다. 한 상황 안에 흔한, 드문, 희귀 애니메이션 묶음을 만들고 싶다면 옵션 중 하나로 또 다른 math.random 함수나 q.random 함수를 넣어 확률과 옵션을 계속 쌓을 수도 있습니다. 이 함수를 제대로 사용하려면 최소 2개의 애니메이션이 필요하며, 이론적으로는 원하는 만큼 많은 애니메이션을 호출하게 만들 수 있습니다. 아마 그러면 안 되겠지만요. 아래 예시에는 각 값이 무엇을 하는지 밑줄 친 부분으로 설명되어 있습니다.
"faint": "q.bedrock_primary('porygon-z', math.random(0, 1) &lt; 0.1 ? 'faint2' : 'faint', q.curve('one'))"

조건

conditions를 사용하면 포켓몬이 가질 수 있는 애니메이션 수와 그 애니메이션이 재생될 시점을 확장할 수 있습니다. standing과 battle-idle 포즈가 모두 "STAND" 포즈 타입을 사용하더라도 배틀 애니메이션을 구분할 수 있는 이유가 조건입니다. 일반적으로 같은 포즈 타입에서 서로 다른 애니메이션을 사용하려면 한 포즈의 조건을 true로, 같은 포즈 타입을 공유하는 다른 포즈의 대응 조건을 false로 설정해야 합니다. 조건을 섞어, 예를 들어 해질녘에 비가 올 때만 배틀 중 재생되는 애니메이션 같은 것도 만들 수 있습니다.

사용할 수 있는 조건 방식은 두 가지입니다. 하나는 각 조건 이름을 딴 속성을 사용하는 기존의 true/false 조건이고, 다른 하나는 새로운 Molang 조건입니다. Molang 조건은 하나 이상의 molang 함수를 사용해 포켓몬의 능력치나 서 있는 블록 같은 특정 속성을 게임이 검사하게 할 수 있습니다. Cobblemon의 커스텀 molang 함수 목록은 사용 가능한 일부 함수가 빨간색으로 강조된 이곳에서 확인할 수 있습니다. molang은 복잡하고 Cobblemon에서는 아직 새 기능이라, 사실상 무한한 가능성을 모두 설명하기는 어렵습니다. 앞으로 참고할 수 있는 예시가 많이 추가될 예정입니다. 필요하다면 Molang 연산자를 사용해 문자열을 확장할 수도 있습니다.

How to write a Molang 조건:

  • "condition": "&lt;insert molang function(s)>"
    • 몇 안 되는 예시 중 하나:

"condition": "q.is_standing_on_blocks(2, 'minecraft:sand', 'minecraft:red_sand')"

아래는 루나톤의 poser 안에서 molang 조건을 사용해 서로 다른 수면 애니메이션 2개를 배정하는 예시입니다. 하나는 모래를 검사해 모래 속에 박히도록 하고, 다른 하나는 잠자는 동안 떠 있도록 합니다. 두 번째 포즈의 molang 조건 앞에 ! 연산자를 사용하면, 게임은 해당 조건이 false일 때만 애니메이션을 재생하도록 보장합니다.

   "sand-sleep": \{
     "poseTypes": ["SLEEP"],
     "condition": "q.is_standing_on_blocks(2, 'minecraft:sand', 'minecraft:red_sand')",
     "namedAnimations": \{
       "cry": "q.bedrock_stateful('dummy', 'cry')"
     \},
     "animations": ["q.bedrock('lunatone', 'sleep')"]
   \},
   "sleep": \{
     "poseTypes": ["SLEEP"],
     "condition": "!q.is_standing_on_blocks(2, 'minecraft:sand', 'minecraft:red_sand')",
     "namedAnimations": \{
       "cry": "q.bedrock_stateful('dummy', 'cry')"
     \},
     "animations": ["q.bedrock('lunatone', 'sleep_alt')"]
   \}

현재 구현된 true/false 조건 목록:

  • "isBattle": The 포켓몬 must be in a 배틀.
  • "isTouchingWater": 포켓몬이 물에 닿아 있어야 합니다. 반드시 물속일 필요는 없습니다.
  • "isInWaterOrRain": 포켓몬이 물에 닿아 있거나 비를 맞고 있어야 합니다. 마찬가지로 반드시 물속일 필요는 없습니다.
  • "isUnderWater": 포켓몬이 물속에 있어야 합니다. 히트박스의 빨간 선이 수면 아래에 있어야 합니다.
  • "isStandingOnRedSand": 포켓몬이 붉은 모래 위에 서 있어야 합니다.
  • "isStandingOnSand": 포켓몬이 모래 위에 서 있어야 합니다.
  • "isStandingOnSandOrRedSand": 포켓몬이 모래 또는 붉은 모래 위에 서 있어야 합니다.
  • "isDusk": 월드 시간이 “황혼”이거나 대략 해질녘이어야 합니다.

아래는 "STAND" 포즈 타입과 Conditions를 사용해 배틀 대기 애니메이션과 지상 대기 애니메이션을 분리하는 두 포즈의 예시입니다:

  • 이런 상황에서는 한 포즈의 조건을 true로 설정하고, 같은 포즈 타입을 공유하는 다른 포즈의 조건은 false로 설정해야 합니다.
   "battle-standing": \{
     "poseTypes": ["STAND"],
     "isBattle": true,
     "animations": [
       "q.bedrock('blastoise', 'battle_idle')"
     ]
   \},
   "standing": \{
     "poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
     "isBattle": false,
     "animations": [
       "q.bedrock('blastoise', 'ground_idle')"
     ]
   \},

변형된 파트

이 함수는 포켓몬이 특정 포즈에 있을 때 모델의 일부를 변형할 수 있게 해 줍니다. 각 포즈마다 본의 위치, 회전, 표시 여부를 바꿀 수 있습니다. 이를 통해 애니메이션 자체를 수정하지 않고도 게임 안 애니메이션을 조금 조정할 수 있습니다. 이 함수의 예시는 많지 않지만, 가장 흔한 사용법은 포켓몬이 배틀 대기 상태가 아닐 때 모델 파트를 숨기는 것입니다. 고릴타와 드럼이 이런 사례입니다.

위치와 회전 변형은 어깨 애니메이션을 조정할 때 특히 유용합니다. 애니메이션을 만들 때 플레이어 어깨 위의 모델 위치까지 미리 맞출 필요는 없습니다. 게임 안에서 위치가 맞지 않으면 이 함수를 사용해 모델 전체를 조정할 수 있습니다.

가시성 변형은 포켓몬이 현재 특정 포즈에 있을 때 모델의 특정 본을 숨길 수 있게 해 줍니다. 필요하다면 특정 본을 숨기는 데 사용할 수 있습니다. 이를 통해 고릴타가 배틀 대기 상태에서만 드럼을 사용하게 하거나, 블레이범의 불꽃이 배틀 중에만 켜지게 만들 수 있습니다. 기억해야 할 점은 특정 본이 배틀 중에만 보이게 하고 싶다면, 다른 모든 포즈에서는 그 본을 보이지 않도록 설정해야 한다는 것입니다. poser 파일 설명에서 transformedParts가 모든 포즈 아래에 작성된 이유가 이것입니다.

아래는 변형 파트 속성을 모두 사용한 예시입니다. 이 함수로 어떤 옵션을 사용할 수 있는지 보여 주기 위한 예시입니다. 이 예시를 게임에 적용하면 리자몽의 날개가 몸에서 분리되고, 왼쪽 날개만 보이지 않게 됩니다. 현실적으로 이런 설정을 실제로 쓰고 싶을 일은 거의 없을 것입니다.

"transformedParts": [
         \{
           "part": "wing_right",
           "position": [10, 0, 0],
           "rotation": [0, 0, 0],
           "isVisible": true
         \},
         \{
           "part": "wing_left",
           "position": [-10, 0, 0],
           "rotation": [0, 0, 0],
           "isVisible": false
         \}
        ]

바라보기 애니메이션

새 Poser는 look 애니메이션을 여러 방식으로 조작할 수 있게 해 줍니다. 이제 제작자는 여러 look 애니메이션을 나열할 수 있으며, 각 애니메이션은 자체 머리 본을 정의하고 look 애니메이션의 일부 속성을 편집할 수 있습니다. 속성을 바꾸면 원할 경우 포켓몬의 시야 원뿔을 조작할 수 있습니다. 이를 통해 이상한 클리핑을 방지하거나 위아래, 좌우로 바라볼 수 있는 범위를 늘리거나 줄일 수 있습니다. 여러 look 애니메이션을 사용하면 머리가 여러 개인 포켓몬의 각 머리를 개별적으로 돌릴 수 있습니다. 몸통과 머리 본이 동시에 바라보게 하면서 각 범위를 제한할 수도 있습니다. 목이 거의 없거나 아예 없어 머리보다 몸으로 더 많이 바라봐야 하는 포켓몬에게 유용합니다.

q.look() 함수는 이 새 look 애니메이션의 형식입니다. 이 함수를 사용할 때는 모든 속성을 특정 순서로 나열해야 하며, 본 이름은 작은따옴표로 감싸야 합니다(아포스트로피 키).

  • pitch, yaw, 원점을 시각적으로 이해하려면 아래 이미지를 참고하세요.
  • 게임 안에서 F3+B를 누르면 히트박스를 볼 수 있습니다. 파란 선은 포켓몬이 바라보는 방향을 나타내며, 아무것도 바라보지 않을 때는 pitch와 yaw가 0인 중앙에 놓입니다. 이를 원점이라고 부를 수 있습니다.
기본 시야 원뿔 시각화.

q.look의 속성은 다음 순서로 작성해야 합니다:

  • 본 이름을 제외하면, 이 값들은 각 속성의 기본값이기도 합니다.
  1. 뼈 name: 'head_ai' - look 애니메이션을 수행할 모델의 본 이름
  2. Pitch Multiplier - 1 - 얻는 pitch 양에 이 값을 곱합니다. -1을 사용하면 pitch를 반전할 수 있습니다.
  3. Yaw Multiplier - 1 - 얻는 yaw 양에 이 값을 곱합니다. -1을 사용하면 yaw를 반전할 수 있습니다.
  4. 맥스 Pitch - 70 - 포켓몬이 원점에서 아래로 바라볼 수 있는 각도입니다.
  5. Min Pitch - -45 - 포켓몬이 원점에서 위로 바라볼 수 있는 각도입니다.
  6. 맥스 Yaw - 45 - 포켓몬이 원점에서 오른쪽으로 바라볼 수 있는 각도입니다.
  7. Min Yaw - -45 - 포켓몬이 원점에서 왼쪽으로 바라볼 수 있는 각도입니다.

앞서 나열한 값을 사용하는 look 애니메이션은 standing 포즈 안에서 다음과 비슷하게 보입니다:

   "standing": \{
     "poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
     "animations": [
       "q.look('head_ai', 1, 1, 70, -45, 45, -45)",
       "q.bedrock('riolu', 'ground_idle')"
     ],

기본값을 사용하고 짧게 유지하고 싶다면 다음처럼 쓸 수도 있습니다:

   "standing": \{
     "poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
     "animations": [
       "q.look('head_ai')",
       "q.bedrock('riolu', 'ground_idle')"
     ],

여러 머리 본을 나열하고 싶다면 q.look 함수를 여러 번 작성할 수 있습니다:

   "standing": \{
     "poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
     "animations": [
       "q.look('head_ai')",
       "q.look('torso')",
       "q.bedrock('riolu', 'ground_idle')"
     ],

특이 동작

Quirk 애니메이션은 보통 포즈의 기본 애니메이션 위에 겹쳐 재생할 수 있는 stateful 애니메이션입니다. 새 poser 형식에는 primary quirk 애니메이션과 q.bedrock_quirk() 형식으로 quirk 애니메이션을 짧게 작성하는 방법이 도입되었습니다. 구 Poser의 quirk 방식은 이 함수를 사용해 한 줄로 압축할 수 있습니다. 이 함수를 사용할 때는 모든 속성을 정해진 순서로 나열해야 하며, 숫자가 아닌 값은 작은따옴표(아포스트로피 키) 안에 넣고 쉼표로 구분해야 합니다.

poser와 애니메이션을 알맞게 만들면 한 포켓몬이 여러 quirk 애니메이션을 동시에 실행하게 할 수 있습니다. 거북왕처럼 애니메이션이 많다면 아래 quirk 예시들을 원하는 대로 조합할 수 있다는 점을 기억하세요.

상태 유지 특이 동작

Stateful quirk는 현재 재생 중인 idle 애니메이션 위에 레이어로 겹쳐지는 애니메이션입니다.

q.bedrock_quirk의 속성은 다음 순서여야 합니다:

  1. 애니메이션 그룹: 'blastoise' - 포켓몬 이름입니다.
  2. 애니메이션 이름: 'quirk_ground_idle' - 애니메이션 이름입니다. q.array 함수를 사용해 애니메이션 풀을 지원합니다.
  3. 발생 사이 최소 초: 20 - 특수 행동이 한 번 재생된 뒤 다시 재생되기까지 필요한 최소 초입니다. 소수도 사용할 수 있습니다.
  4. 발생 사이의 최대 초: 60 - 말 그대로입니다.
  5. 반복 횟수: 1 - quirk에서 애니메이션을 재생할 횟수입니다.

앞서 나열한 속성은 quirk로 다음과 같이 작성됩니다:

     "quirks": [
       "q.bedrock_quirk('blastoise', 'quirk_ground_idle', 20, 60, 1)"
     ]

quirk 사이의 기본값인 8~30초를 사용하려는 것뿐이라면 모든 속성을 포함할 필요는 없습니다. 기본값을 사용하고 짧게 유지하려면 다음처럼 쓸 수 있습니다:

     "quirks": [
       "q.bedrock_quirk('blastoise', 'blink')"
     ]
q.array

애니메이션 이름을 q.array() 함수로 바꾸면 quirk가 재생할 애니메이션 목록 중 하나를 고르게 할 수 있습니다. 한 포즈 아래에서 재생하고 싶은 quirk가 많을 때 유용합니다. 괄호 안에 애니메이션 목록을 넣고, 각 애니메이션 이름을 작은따옴표 안에 적은 뒤 쉼표로 구분하면 됩니다.

  • 예: q.array('quirk_battle_idle', 'quirk_battle_idle2')
    • 이 quirk들은 거북왕이 각 대포를 조정하는 동작입니다. 이렇게 작성하면 거북왕이 한 번에 대포 하나만 조정하지만, 매번 무작위 대포를 조정하게 됩니다.

이를 특수 행동으로 만들면 다음과 같은 형태가 됩니다.

     "quirks": [
       "q.bedrock_quirk('blastoise', q.array('quirk_battle_idle', 'quirk_battle_idle2'), 30, 60, 1)"
     ]

Primary Quirks

Primary quirk는 전체 애니메이션 길이 동안 idle 애니메이션 위에서 재생되는 애니메이션입니다. Primary quirk 애니메이션은 재생 중 모델 전체를 제어할 수 있으므로, 포켓몬이 완전히 뒤집히는 동작 등을 하게 한 뒤 q.curve 함수를 사용해 idle 포즈로 다시 보간할 수 있습니다.

q.bedrock_primary_quirk의 속성은 다음 순서여야 합니다:

  1. Animation Group: 'porygon2' - 포켓몬의 이름
  2. 애니메이션 이름: 'idle_quirk' - 애니메이션의 이름입니다. q.array 함수를 사용한 애니메이션 풀도 지원합니다.
  3. 발생 사이 최소 초: 20 - 특수 행동이 한 번 재생된 뒤 다시 재생되기까지 필요한 최소 초입니다. 소수도 사용할 수 있습니다.
  4. 발생 사이 최대 초: 40 - 어떻게 생각하시나요?
  5. 반복 횟수: 1 - quirk에서 애니메이션을 재생할 횟수입니다.
  6. (optional) excluded labels: 'look' - 이 primary 애니메이션에 의해 덮어쓰이지 않을 독점 라벨 애니메이션입니다. excluded labels의 합리적인 용도는 look 애니메이션이 덮어쓰이지 않게 제외하는 것입니다. 이렇게 하면 애니메이션을 사용할 때도 대상을 계속 바라볼 수 있습니다.
  7. 곡선: q.curve('symmetrical') - 포즈의 idle 애니메이션으로 돌아갈 때 사용하는 곡선형 사인파 타입입니다.

이를 특수 행동으로 만들면 다음과 같은 형태가 됩니다.

     "quirks": [
       "q.bedrock_primary_quirk('porygon2', q.array('idle_quirk', 'idle_quirk2'), 20, 40, 1, q.curve('symmetrical'))"
     ]

이 예시는 폴리곤2가 두 quirk 중 하나를 primary 애니메이션으로 사용하게 합니다. idle 애니메이션으로 돌아가기 전에 뒤집히거나 회전합니다.

Placeholder Animations

새 poser는 제작자가 이전 JSON poser에서 접근할 수 없던 placeholder 애니메이션을 사용할 수 있게 해 줍니다. 이 placeholder 애니메이션은 포켓몬의 몸 타입이나 팔다리 특징을 기반으로 합니다. 각 placeholder는 팔다리를 앞뒤로 흔드는 매우 단순한 애니메이션입니다.

아래는 현재 placeholder 애니메이션, 기본값, 그리고 애니메이션 목록에 바로 복사할 수 있는 예시 목록입니다:

  • q.quadruped_walk - 다리가 4개인 포켓몬을 위한 기본 걷기 애니메이션입니다.

"q.quadruped_walk(0.66, 1.4, 'leg_front_left', 'leg_front_right', 'leg_back_left', 'leg_back_right')"

  • q.biped_walk - 두 다리로 서는 포켓몬을 위한 기본 걷기 애니메이션입니다.

"q.biped_walk(0.66, 1.4, 'leg_left', 'leg_right')"

  • q.bimanual_swing - 보통 두 다리로 서는 팔 2개짜리 포켓몬을 위한 기본 팔 흔들기 애니메이션입니다.

"q.bimanual_swing(0.66, 1.4, 'arm_left', 'arm_right')"

  • q.sine_wing_flap - 포켓몬의 한 쌍의 날개를 위한 기본 날갯짓 애니메이션입니다. 이 애니메이션은 지정한 본의 외형 요소를 조금 더 제어할 수 있게 해 줍니다. “날개”가 어느 축으로 회전해야 날갯짓처럼 보이는지 확인하는 것이 중요하므로, 모델을 꼭 참고하세요.

"q.sine_wing_flap(0.9, 0.9, 25, 'z', 'wing_left', 'wing_right')"

날갯짓 placeholder를 제외하면, 이 함수들에서 첫 번째 값은 팔다리가 얼마나 빠르게 흔들리는지를 제어하며 period 값이라고도 부릅니다. 두 번째 값은 amplitude, 즉 팔다리가 얼마나 크게 흔들리는지를 뜻합니다. 둘 다 코사인 파형에 곱해지는 값입니다. 기본값으로 팔다리가 잘 맞지 않는다면 이 값들을 조정하세요.

Poser 파일 Breakdown

Soon™

Poser 파일 Example

매번 poser 파일을 처음부터 만들기보다, 다른 커스텀 포켓몬 poser를 틀로 사용할 수 있습니다. 다만 각 포켓몬이 가진 애니메이션을 확인해야 하며, 모든 포켓몬에 head라는 본이 있는 것은 아니라는 점도 기억하세요.

아래는 현재 구현된 모든 포즈와 그에 맞는 애니메이션을 포함한 커스텀 riolu poser 파일 예시입니다.

  • 리오르는 당연히 날 수 없습니다. 현재 모든 것을 할 수 있는 포켓몬은 없으므로, 이것은 예시일 뿐입니다.
  • 깜빡임 애니메이션은 수면 포즈에 적용되지 않습니다. 잠을 잘 때는 눈을 깜빡이지 않기 때문입니다.
\{
 "portraitScale": 1,
 "portraitTranslation": [0, 0, 0],
 "profileScale": 1,
 "profileTranslation": [0, 0, 0],
 "animations": \{
   "faint": "q.bedrock_primary('riolu', 'faint', q.curve('one'))",
   "cry": "q.bedrock_stateful('riolu', 'cry')",
   "recoil": "q.bedrock_stateful('riolu', 'recoil')",
   "physical": "q.bedrock_primary('riolu', 'physical', q.curve('symmetrical_wide'))",
   "special": "q.bedrock_primary('riolu', 'special', q.curve('symmetrical_wide'))",
   "status": "q.bedrock_primary('riolu', 'status', q.curve('symmetrical_wide'))"
 \},
 "poses": \{
   "battle-standing": \{
     "poseTypes": ["STAND"],
     "isBattle": true,
     "animations": [
       "q.look('head')",
       "q.bedrock('riolu', 'battle_idle')"
     ],
     "quirks": ["q.bedrock_quirk('riolu', 'blink')"]
   \},
   "standing": \{
     "poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
     "isBattle": false,
     "animations": [
       "q.look('head')",
       "q.bedrock('riolu', 'ground_idle')"
     ],
     "quirks": [
       "q.bedrock_quirk('riolu', 'blink')"
     ]
   \},
   "walking": \{
     "poseTypes": ["WALK"],
     "animations": [
       "q.look('head')",
       "q.bedrock('riolu', 'ground_walk')"
     ],
     "quirks": ["q.bedrock_quirk('riolu', 'blink')"]
   \},
   "hover": \{
     "poseTypes": ["HOVER"],
     "animations": [
       "q.look('head')",
       "q.bedrock('riolu', 'air_idle')"
     ],
     "quirks": ["q.bedrock_quirk('riolu', 'blink')"]
   \},
   "fly": \{
     "poseTypes": ["FLY"],
     "animations": [
       "q.look('head')",
       "q.bedrock('riolu', 'air_fly')"
     ],
     "quirks": ["q.bedrock_quirk('riolu', 'blink')"]
   \},
   "float": \{
     "poseTypes": ["FLOAT"],
     "animations": [
       "q.look('head')",
       "q.bedrock('riolu', 'water_idle')"
     ],
     "quirks": ["q.bedrock_quirk('riolu', 'blink')"]
   \},
   "swim": \{
     "poseTypes": ["SWIM"],
     "animations": [
       "q.look('head')",
       "q.bedrock('riolu', 'water_swim')"
     ],
     "quirks": ["q.bedrock_quirk('riolu', 'blink')"]
   \},
   "sleep": \{
     "poseTypes": ["SLEEP"],
     "animations": ["q.bedrock('riolu', 'sleep')"]
   \},
   "shoulder_left": \{
     "poseTypes": ["SHOULDER_LEFT"],
     "animations": [
       "q.look('head')",
       "q.bedrock('riolu', 'shoulder_left')"
     ],
     "quirks": ["q.bedrock_quirk('riolu', 'blink')"]
   \},
   "shoulder_right": \{
     "poseTypes": ["SHOULDER_RIGHT"],
     "animations": [
       "q.look('head')",
       "q.bedrock('riolu', 'shoulder_right')"
     ],
     "quirks": ["q.bedrock_quirk('riolu', 'blink')"]
   \}
 \}
\}

Addon Creation

튜토리얼

커스텀 포켓몬 만들기 모델 만들기 커스텀 스폰 만들기 발광 텍스처 애니메이션 텍스처 Texture Replacement 애니메이션 교체 리전 폼여러 시각 Variants 애니메이션에 소리 추가하기

Asset Files

리졸버 구 Poser 신 Poser 소리

데이터 Files

종 종 특징 종 특징 할당 종 추가 스폰 Detail Presets 스폰 Pool 월드 화석 Datapackable Move Effects

Properties

행동 스폰 조건 발전 과제