#はじめに
この記事は、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つ動いています
#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()関数内のコードを実行します。
#テンプレート
所有権を貫通する銃弾について
にあるコードをcytanb.luaのEmitMessageとOnInstanceMessageに変えて記載しました。このように使います。
---銃弾
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)