アドオン作成 - Molang 上級
アドオンの色んなところで色んな「値」を指定しますが、指定する値が動的であってほしいこともあります。 たとえば、残りHPに応じて見た目や色が変化するなどといったシチュエーションにも、1つの「値」として「Molang」を使って表すことができます。
しかし、Molangはどこでも使えるわけではなく、値の種類としてMolangでの指定が許されている場所でのみ使うことができます。
● 基本的な演算子
記号 | 概要 |
---|---|
+ | 足し算 |
- | 引き算 |
* | 掛け算 |
/ | 割り算 |
!A | Aではない |
A && B | AかつB |
A || B | AまたはB |
x < a | xはaより小さい |
x <= a | xはaであるまたはaより小さい |
x >= a | xはaであるまたはaより大きい |
x > a | xはaより大きい |
x == y | xとyは等しい |
x != y | xとyは等しくない |
● カッコ
カッコ (・)を使って演算の順序をコントロールします。
● 三項演算子
?の前に条件式を書き、後ろにコロン(
:
)を挟んで返す値を指定します。条件が真ならコロンの前の値、偽なら後ろの値になります。
たとえば以下の式は100を返します。
● 数学関数
記号 | 概要 |
---|---|
math.abs(x) | xの絶対値 |
math.acos(x) | xのアークコサイン |
math.asin(x) | xのアークサイン |
math.atan(x) | xのアークタンジェント |
math.atan2(x, y) | x/yのアークタンジェント |
math.ceil(x) | xを下回らない最小の整数 |
math.clamp(x, a, b) | xがaより小さいとa、bより大きいとb、間ならx |
math.cos(x) | xの余弦 |
math.die_roll(n, a, b) | n個のa~bのランダムな小数の合計 |
math.die_roll_integer(n, a, b) | n個のa~bのランダムな整数の合計 |
math.exp(x) | ネイピア数が底の指数関数 |
math.floor(x) | xを越えない最大の整数 |
math.hermite_blend(x) | 3x²-2x³(エルミート補間) xは0~1 |
math.lerp(x) | |
math.lerprotate(x) | |
math.ln(x) | xの自然対数 |
math.max(a, b) | aとbの大きいほう |
math.min(a, b) | aとbの小さいほう |
math.min_angle(x) | -180°~180°の角度に変換 |
math.mod(x, k) | xをkで割ったあまり |
math.pi | 円周率 |
math.pow(x, a) | xのa乗 |
math.random(a, b) | a~bのランダムな小数 |
math.random_integer(a, b) | a~bのランダムな整数 |
math.round(x) | xの四捨五入 |
math.sin(x) | xの正弦 |
math.sqrt(x) | xの正の平方根 |
math.trunc(x) | xの小数点以下切り捨て |
Molangでは変数を定義することができます。変数名は必ず variable.(省略形: v.)から始まるようにしてください。
変数定義の式は複雑表現(Complex Expression)となり、式の終わりに必ずセミコロン( ; )を書かないといけません。
● return文
Molangを書く場所は、一部のフィールドを除いて何らかの「値」を返す必要があるはずですが、変数を定義すると定義するだけして何も値を返しません。 そこで、最終的にどんな値を返すのか指定するのがreturn文です。
● 一時的な変数
temp.(省略形: t.)で始まる変数は一時的な変数として定義されます。 variable変数は別の場所からアクセスできますが、temp変数は定義されたその場所からしかアクセスできません。
● 定数
定数はcontext.(省略形: c.)で始まる名前で定義します。variable変数やtemp変数と違って一度定義したら中身を変更できません。
Molangは演算できることが強みではありますが、多くのクリエイターがMolangを重宝しているのは「Molangで特殊な値を取得できる」ことがあるからでもあります。
クエリ関数は、ゲーム内の様々な値を取得するための関数です。これがあることによって、エンティティがアニメーションしたりイベントの条件をMolangで書くことが実用的になったりします。
クエリ名は必ず query.(省略形: q.)で始まります。
クエリ関数の種類は大量にあるので、一覧はここでは紹介せず各自リファレンスを参照してもらうこととします。
● 上級者の知識
ゲーム内にある様々な「値」を取得するのがクエリ関数だと説明しましたが、実はvariable変数にそういった値が入っていることがあります。 つまり、内部で定義されている(ハードコードされている)がクエリ関数と同様に扱えるvariable変数があるということです。
??の前にある変数が未定義(Null)だった場合、後ろの数が採用されます。 たとえば、以下の例は v.xが未定義なら 0.0を、定義されていたら v.xの値をそのまま返します。
特にloopやfor_eachで { }を使って一連のステートメントを1つのグループにまとめることができます。以下の例では v.mooが0より大きいときカッコ内の処理をするというものです。
loopの中に書いた式を指定した回数だけ処理します。
上記の例はフィボナッチ数列の第11項(87)を返します。
● break
breakを使って条件に応じて繰り返し処理を抜け出すことができます。以下の例では、 v.yが20より大きくなるとloopの処理を抜けます(最終的な値は21)。
● continue
continueを使って条件に応じて処理をスキップすることができます。以下の例では v.xが5より大きいときの処理はスキップされます(最終的な値は6)。
たとえば、クエリ関数 q.get_nearby_entitiesはエンティティの配列を返します。 for_eachはそのような配列の要素それぞれに対して処理を行うことができます。以下の例では周囲4マス以内のブタの数を返します。
● breakとcontinue
for_eachでもloopのようにbreakとcontinueを使うことができます。
いくつかのクエリ関数またはtemp/entity/context変数は別のエンティティへの参照を格納していることがあります。
プレイヤーに関するJSONの中で q.is_on_fireを使うと「プレイヤーが炎上状態かどうか」が取得できます。 もし、定義した変数 v.pigがワールド内にいる、ある1匹のブタへの参照を格納していたならば、
という式をそのブタに関係ないJSONで書いても、この式は「(その)ブタが炎上状態かどうか」を示すことになります。
● 実用例
この式はプレイヤーのJSONに書かれているとします。
まず、プレイヤーの周囲4マス以内にいるブタを取得します。1匹ずつ
v.pigに格納して、for_each内の式の処理をします。最終的にこの式はそれらのブタのうち何匹の足元が
"flammable"タグをもったブロックだったのかを返します。
Molangで扱う「値」の型のほとんどは数です。特に、真偽値も数で表されることに注意してください。 エンティティや文字列など数でない値を扱うのはまれです。
● 真偽値
クエリ関数から真偽値が渡されるときは、trueが1.0、falseが0.0となります。 逆に、0.0以下の数はfalse、それ以外の数はtrueとして扱われます。
● 文字列
MolangはJSONでは文字列として扱われるため、 " "で囲まれているので、Molangの値としての文字列は ' 'で囲みます。
また、Molangの文字列に対して使える演算子は ==と !=のみです。
以下の表の上が優先度最大です
演算処理 | 概要 |
---|---|
論理否定 | 否定! |
乗算・除算 | 掛け算*・割り算/ |
加算・減算 | 足し算+・引き算- |
比較演算(不等号) | 不等号 < <= > >= |
比較演算(等号) | 等号== != |
論理積 | AND(かつ)&& |
論理和 | OR(または)|| |
三項演算 | 三項演算子? :(入れ子になっている場合は右から左に評価する) |
Null合体演算 | Null合体演算子?? |
クエリ関数などで取得した値はしばしば深層データをもっていることがあります。ドット( . )でプロパティ名をつなげるとその深層データにアクセスできます。
以下はその他の例です。どれも返す値は1.23になります。