演算が全てを制する「MoLang」【第5回パーティクル講座】

どうも、アドオンパーティクル講座第5回となります。
第4回の講座ではテクスチャに関するカスタマイズを行いました。

前回の記事はこちら!


今回の講座ではパーティクルの自由度の鍵を握っていると言ってもおかしくない、MoLangについて解説していこうと思います。

※1.10.0format対応記事です。

1.無限の可能性「MoLang」

MoLangとは、Minecraft側で定義された数学演算の事を指します。

今まで解説してきた内容ではコンポーネントの中に単純に値を入れるだけでしたが、ダブルクォーテーション(“”)で挟むことで演算子を使った複雑な計算を行うことが可能になります。
数学関数や、Minecraft専用の関数もいくつか用意されており、関数の名前を値に入れることで設定された値を自動的に反映させてくれます。
モデルのアニメーションリソースパックのエンティティカスタマイズ、もちろんパーティクルにも使うことができ、複雑なカスタマイズを可能にします。

例えばvariable.Particle_Ageという関数は、パーティクルが誕生してからの存在時間を値に入れてくれます。
これを、“minecraft:particle_appearance_billboard”“size”に入れてあげることで、時間経過と共にパーティクルが大きくなるといった演出が可能になります。

"minecraft:particle_appearance_billboard": {
"size": [ "variable.Particle_Age", "variable.Particle_Age"]
}

演算子を挟んで、より複雑な出力方法も。

"minecraft:particle_appearance_billboard": {
"size": [ "variable.Particle_Lifetime - (math.floor(variable.Particle_Age))", "variable.Particle_Lifetime - (math.floor(variable.Particle_Age))"]
}

variable.Particle_Lifetimeは、設定されたパーティクルが生存する時間が値に入ります。
それにvariable.Particle_Age、出現後の経過時間を減算するため、寿命が近づくとどんどん小さくなっていきます。
数学関数のmath.floorは括弧の中の値の小数点以下を切り捨てるため、じわじわと小さくなるのではなく整数単位で小さくなっていきます。

2.MoLang関数一覧

(見やすさのために、ピリオド以降の頭文字を大文字にしています。記述する際は小文字大文字どちらでもOK)

variable.Particle_Lifetime // 他のコンポーネントで指定されたLifetimeの固定値。
variable.Particle_Age      // パーティクルが誕生してからの存在時間。
variable.Particle_Random1  // パーティクル一つに与えられる変動しない乱数。0.0~1.0の値が入る。
variable.Particle_Random2  // 上とは別のもう一つの乱数。
variable.Emitter_Lifetime  // 他のコンポーネントで指定されたLifetimeの固定値。
variable.Emitter_Age       // エミッターが誕生してからの存在時間。
variable.Emitter_Random1   // エミッター一つに与えられる変動しない乱数。0.0~1.0の値が入る。
variable.Emitter_Random2   // 上とは別のもう一つの乱数。

3.jsonファイルの中身

記述例を載せていきます。MoLangのもっと細かな記述方法についても説明したいですが、とても幅が広く解説も大変なため、まずはシンプルな例から入っていきましょう。

(パーティクル名:particle_test_tip_5)

{
  "format_version":"1.10.0",
  "particle_effect": {
    "description": {
      "indentifier": "particle_test_tip_5",
      "basic_render_parameters": {
        "material": "particles_alpha",
        "texture": "textures/particle/particles"
      },
      "components": {
        "minecraft:emitter_shape_point": {
          "offset": [0.0, 0.0, 0.0],
          "direction": ["math.random(-1.0,1.0)", 2.0, "math.random(-1.0,1.0)"]
        },
        "minecraft:particle_motion_dynamic": {
        },
        "minecraft:particle_initial_speed": 2.0,

        "minecraft:emitter_rate_instant": {
          "num_particles": 1
        },
        "minecraft:emitter_lifetime_once": {
          "active_time": 0
        },
        "minecraft:particle_lifetime_expression": {
          "max_lifetime": 3.0
        },
        "minecraft:particle_appearance_billboard": {
          "size": [ "variable.Particle_Lifetime / 3 - variable.Particle_Age / 3", "variable.Particle_Lifetime / 3 - variable.Particle_Age / 3"],
          "facing_camera_mode": "lookat_xyz",

          "uv": {
            "texturewidth": 128,
            "textureheight": 128,

            "flipbook": {
              "base_UV": [ 56, 0 ],
              "size_UV": [ 8, 8 ],
              "step_UV": [ -8, 0 ],
              "frames_per_second": 8,
              "max_frame": 8,
              "stretch_to_lifetime": true,
              "loop": false
            }
          }
        },
        "minecraft:particle_appearance_tinting": {
          "color":[ "variable.Particle_Random_1", 0.0 ,"variable.Particle_Random_2" ,1.0]
        }
      }
    }
  }
}

MoLangに入ると急に難易度が上がります。しかし、使いこなすことができたらもうパーティクルマスターと言っても過言ではないはず!頑張っていきましょう。

4.コンポーネント解説

"minecraft:emitter_shape_point": {
"offset": [0.0, 0.0, 0.0],
"direction": ["math.random(-1.0,1.0)", 2.0, "math.random(-1.0,1.0)"]
}

地味に初登場のコンポーネントです。“minecraft:emitter_shape_sphere”と違うのは一点の場所から出力するというところです。
“offset”はパーティクルの出現位置を指定します。手前からXYZの相対座標で指定されます。
“direction”はパーティクルの向きを指定します。相対座標で向く座標を指定します。
“minecraft:emitter_shape_sphere”よりはシンプルなコンポーネントですが見た目は分かりやすいです(MoLangは別)。
“direction”内のMoLangには数学関数のmath.randomを利用しています。括弧内の一つ目と二つ目の値の間の乱数を発生させます。

"minecraft:particle_appearance_billboard": {
"size": [ "variable.Particle_Lifetime / 3 - variable.Particle_Age / 3", "variable.Particle_Lifetime / 3 - variable.Particle_Age / 3"]
}

パーティクルのサイズを指定するコンポーネントになります。
最初に出した例と近い構造で、パーティクルの指定された生存時間を出力してから存在した時間で減算します。
減算の前に3で割っています(“variable./ 3″)が、こちらは元の値が大きすぎるため、どちらの値も小さくして大きさを調節しています。

"minecraft:particle_appearance_tinting": {
"color":[ "variable.Particle_Random_1", 0.0 ,"variable.Particle_Random_2" ,1.0]
}

パーティクルの色を指定するコンポーネントです。赤色(一つ目の値)と青色のところ(三つ目の値)にvariable.Particle_Randomが入っており、赤色と青色の要素がランダムに決まります。

5.注意点

MoLangは、値を途中で変動させることのできる唯一の手段です。
しかし、その変動は関数やコンポーネントの条件によって常に変わり続けるものや、今後変動することがないものもあったりします。
例えば“minecraft:emitter_shape_point”“direction”math.randomが使われていますが、こちらは最初の一回だけパーティクルを出力するので最初の一回以降、変動しないコンポーネントと変動する関数です。
variable.ParticleRandomは貴重な変動しない乱数であるため、使う場所は考えたいところです。

他に変動するコンポーネントは“minecraft:particle_appearance_billboard”“size”“minecraft:particle_appearance_tinting”の”color”などです。
“color”math.random(0.0,1.0)を入れると常時変動するため、目に悪くなるような見た目になってしまいます。


さて、解説は以上となります。
今回の例ではパーティクルを出力するたびに赤色と青色の要素がランダムなパーティクルが上の方向へ広がるように飛んでいきます。

6.終わりに

アドオンパーティクルの要素は、ここまででだいたい解説し終わりました。まだ解説していないコンポーネントもありますが、表現の可能性のカギを握るのは今まで解説してきた内容とそれを応用することだと思います。
とは言え、これでパーティクル解説は終わりではなく、これからも応用的な内容を執筆していけたらなと思っています。その時はまた見ていただければ幸いです。

そして…次に新しいパーティクルを作るのは、あなた自身です!

それではお疲れ様でした!


前回↓

次回↓
更新をお待ちください。