LoginSignup
4
2

More than 3 years have passed since last update.

cytanb.luaのススメ 2.同一VCIのmessage競合対策

Last updated at Posted at 2019-12-10

はじめに

この記事は、VCI Advent Calendar 2019の11日目の記事です。

使用方法について

cytanb.luaのススメ 1.導入編
こちらにあります。

同一VCIのmessage競合問題

VCIのメッセージの仕様についてははちらに記載があります。
vci.message(VCI間の通信)

関数一覧
Emit()
メッセージを送信します。
メッセージは、自分自身を含む全ユーザーの全VCIに送信されます。
On()
メッセージを受信します。
メッセージを送信したのと同じVCIでも、別のVCIでもOK。
Onの第1引数と Emitの第1引数 が一致したものを受け取ります。
受け取ったメッセージを第2引数の関数に渡します。
Onは第2引数で指定した受信関数よりも後に定義してください。受信関数よりも前に定義するとエラーとなります。

問題は、Emitが全ユーザーの全VCIにメッセージを送る点です。
つまり、同じVCIが2つあって、片方が「右へ動け」というメッセージを送った場合、2つ両方とも「右へ動け」というメッセージを受信してしまいます。

画像による解説

二人いて2つの同名VCIがある画像。luaファイルは4つ動いています

Untitled Diagram (1).png

自身のVCIのlua全部にメッセージを送りたい!!

Untitled Diagram (3).png

現実(なんでやぁ・・・)

Untitled Diagram (4).png

cytanbのmessage関数を使おう

そこで、cytanbのmessage関数である、

  • cytanb.EmitMessage()
  • cytanb.OnInstanceMessage()

を使います。

cytanb.EmitMessage()

cytanb_annotations.luaにはこのように記載されています。

EmitMessage fun (name: string, parameterMap: table) @パラメーターを JSON シリアライズして vci.message.Emit する。name はメッセージ名を指定する。parameterMap は送信するパラメーターのテーブルを指定する(省略可能)。また、InstanceID がパラメーターフィールド __CYTANB_INSTANCE_ID として付加されて送信される。

cytanb.luaを導入すると、自動的に__CYTANB_INSTANCE_IDが生成され、vci.stateに保存されます。
これはUUIDで、簡単に言うとこのVCIだけのIDが付与されます。この値が被ることは理論上無いです。
cytanb.EmitMessageでは、この__CYTANB_INSTANCE_IDをメッセージに追加してメッセージを送信します。

cytanb.OnInstanceMessage()

cytanb_annotations.luaにはこのように記載されています。

---@field OnInstanceMessage fun (name: string, callback: fun(sender: table, name: string, parameterMap: table)) @自身のインスタンスから送信されたメッセージを受信するコールバック関数を登録する。パラメーターフィールド __CYTANB_INSTANCE_ID を利用してインスタンスの判定を行う。その他の事項については OnMessage を参照。

cytanb.EmitMessage()で送信したメッセージはこの関数で受信します。
cytanb.EmitMessage()で送信したメッセージをこの関数で受信すると、__CYTANB_INSTANCE_IDを照合してメッセージの送受信が同じVCI(同名なだけじゃ駄目)のメッセージを送信した時だけOnInstanceMessage()関数内のコードを実行します。

つまり画像で表すと

UUIDがあるおかげで

Untitled Diagram (7).png

メッセージは届くけど破棄される

Untitled Diagram (6).png

テンプレート

所有権を貫通する銃弾について
にあるコードをcytanb.luaのEmitMessageとOnInstanceMessageに変えて記載しました。このように使います。

messageTemplate.lua

---銃弾
local bullet = vci.assets.GetSubItem('Bullet')
---銃口
local bullet_out = vci.assets.GetSubItem('BulletOut')

---[SubItemの所有権&Use状態]アイテムをグラッブしてグリップボタンを押すと呼ばれる。
---@param use string @押されたアイテムのSubItem名
function onUse(use)
    ---SubItem名'Gun'をuseしたらメッセージ全員に送信
    if use == 'Gun' then
        cytanb.EmitMessage('GUN_SHOT', true)
    end
end

---射撃メッセージ処理(全員に処理)
function onShot(sender, name, message)
    ---銃弾が銃口に移動
    bullet.SetPosition(bullet_out.GetPosition())
    ---銃弾の速度を消す
    bullet.SetVelocity(Vector3.zero)
    bullet.SetAngularVelocity(Vector3.zero)
    ---銃弾を銃口のz軸方向に飛ばす
    bullet.AddForce(bullet_out.GetForward() * 1500)
end
cytanb.OnInstanceMessage('GUN_SHOT', onShot)
4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2