ルームでVCIが全部読み込まれるまで、待ってて欲しい!
ルームでは、ロケーションを含めて、複数のVCIで構成されていると思います。
Vキャスでは、すべてのアイテムが読み込まれる前から、ルームに入ることができるので、
- モデルの一部が読み込まれる前の、景観が悪い状態で散策されてしまう
- 本来、コライダーがある場所を突破されてしまう
- イベントのトリガーを踏んだ際に、連携するアイテムがないため、エラーが発生してしまう
などといった事が発生してしまいます。
これらを防ぐために、自分の作ったルームでは↓のような、通せんぼをする看板とコライダーを設置しています。
ここでは、どのようにこちらのVCIを実装したか、ご紹介します。
読み込みを待っている間も楽しんで欲しい!
Vキャスのいい点の一つとして、ロケーションが読み込まれれば、ルームに入れる点が挙げられます!
(ミクランドとかでも思いましたけど、待ち時間を最小限にして、ロケーションを楽しめるっていいですよね!)
このいい点が先ほど挙げた、問題に繋がってしまうのですが、このVキャスのいい点を活かしたロケーションの構成にしていきたいと思います!
まず、ロケーション自体をリスポーン地点を中心に構成し、読み込みを待つアイテムVCIが見えないような構造にしておきます。
今回は、このような袋小路を作って、ここをリスポーン地点として、待ってもらいます。
さらに袋小路の先は、道が曲がるようにして、ロードしているアイテムVCI(この先にある建物)が見えないようにしました。
待っていただいている間に楽しんでもらうために、雰囲気に合うBGMも用意します。
今回はフリーBGMを使うと、「あ、この曲は、あの動画で使われてるBGMだ」というような、違うところに意識が取られてしまう恐れがあったため、有償BGMを使用しました。
Audiostock様のこちらのBGMを使わせて頂いてます。
続いて、待っていただいている間、風景も楽しんでもらうため、亞希乃さん作の素敵な星空も用意しました。
これで、建物の間から見える星空がいい感じになりました!
これで、待っている間に楽しんで頂ける風景と音楽の用意できました!
VCIの読み込みに対応して、通せんぼするVCI
冒頭でご紹介したこちらのVCIは、リスポーン位置から少し離れた位置にあり、限りなく軽くしてあるので、ルームに入った瞬間にいち早くロードさせ、通せんぼする仕組みとなっています。
厳密には、こちらのVCIは2つのアイテムで構成されていて、「通せんぼするコライダーVCI」と「コライダーが機能しているかどうかを表すエフェクトVCI」となってます。
これは、前者のVCIをなるべく早くロードして、確実に通せんぼするためです。
さらに、確実に狙い通りの位置で、来訪者を通せんぼできるよう、messageで移動位置情報を飛ばして、移動させるようにします!
こんな感じのやり取りを、VCI同士でやらせて移動させます。
実際のスクリプトは以下のような感じで、「通せんぼVCI」のvci.message.Emit("EntranceBlockTransformPlz", ...)が上図①、「ロケーションVCI」のfunction blockTransformReturn ...が上図②、「通せんぼVCI」のfunction blockTransform ...が上図③に対応してて動いてます。
ロード関係は、他者の環境は関係なく、自分の環境(ロードされたか、されないか)が重要となるため、ローカルで処理されるように、自分の名前も一緒に飛ばして、自分から送られたメッセージのみをトリガーとして、処理されるようにしています。
「エフェクトVCI」は「通せんぼVCI」と同様に、移動させ、エフェクト再生のスクリプトを追加するだけでOKです。
(ルームは位置情報が記録されるので、毎回スクリプトで移動を実行する必要はありませんが、念のため毎回実行するようにしています。)
local block = vci.assets.GetTransform("Block")--”Block”は通せんぼするSubItem
local blockPos = Vector3.zero
local blockRot = Quaternion.identity
local transformFlag = false
--入場制限のブロックの位置情報取得
function blockTransform(sender, name, message)
if vci.studio.GetLocalAvatar().GetName() == message[1] then
blockPos.x = message[2]
blockPos.y = message[3]
blockPos.z = message[4]
blockRot.x = message[5]
blockRot.y = message[6]
blockRot.z = message[7]
blockRot.w = message[8]
block.SetPosition(blockPos)
block.SetRotation(blockRot)
transformFlag = true
end
end
vci.message.On("EntranceBlockTransformReturn", blockTransform)
function updateAll()
if transformFlag == false then
vci.message.Emit("EntranceBlockTransformPlz", vci.studio.GetLocalAvatar().GetName())
end
end
local entranceBlockPos = vci.assets.GetTransform("EntranceBlockPos")--"EntranceBlockPos"は通せんぼVCIの位置情報の空オブジェクト
--入場制限のブロックの位置情報
function blockTransformReturn(sender, name, message)
if vci.studio.GetLocalAvatar().GetName() == message then
vci.message.Emit("EntranceBlockTransformReturn", {
vci.studio.GetLocalAvatar().GetName(),
entranceBlockPos.GetPosition().x,
entranceBlockPos.GetPosition().y,
entranceBlockPos.GetPosition().z,
entranceBlockPos.GetRotation().x,
entranceBlockPos.GetRotation().y,
entranceBlockPos.GetRotation().z,
entranceBlockPos.GetRotation().w
})
end
end
vci.message.On("EntranceBlockTransformPlz", blockTransformReturn)
続いて、ルーム内アイテムがすべてロードされたことを確認し、通せんぼを解除する工程になります。
ここでは、新たに「管制VCI」が出てきて、VCIの状況を確認したり、「通せんぼVCI」に通せんぼの解除をお願いしたりします。
上記のイラストをスクリプトにすると以下のような感じとなり、「管制VCI」の vci.message.Emit("BovoloInitializeCheck",...が上図①、「アイテムVCI」のfunction initialize(...が上図②、「管制VCI」のvci.message.Emit("ALLVCISetOK",...が上図③、「通せんぼVCI」のblock.SetActive(false)が上図④に対応して動いてます。
上図にはありませんが、その後、「通せんぼVCI」からvci.message.Emit("BlockOFF",...を出して、「管制VCI」からの③を停止させてます。
(「エフェクトVCI」は、ほとんど「通せんぼVCI」と一緒なので、省略)
「アイテムVCI」は、読み込みが完了しない限り、上図②が動かないので、すべてのアイテムVCIが読み込まれて、すべての上図②が実行されることで、すべてのアイテム読み込み→通せんぼの解除、となります。
--他のVCIの初期化フラグ
local initialFlag = false
local initialize1 = false
local initialize2 = false
local entranceFlag = false
local effectFlag = true
local blockFlag = true
--他のVCIの初期化チェック
function initializeCheck(sender, name, message)
if vci.studio.GetLocalAvatar().GetName() == message then
if "Bovolo1InitializeOK" == name then
initialize1 = true
end
if "Bovolo2InitializeOK" == name then
initialize2 = true
end
end
end
vci.message.On("Bovolo1InitializeOK", initializeCheck)
vci.message.On("Bovolo2InitializeOK", initializeCheck)
--入場可否チェック
function entranceCheck(sender, name, message)
if vci.studio.GetLocalAvatar().GetName() == message then
if "EffectOFF" == name then
effectFlag = false
end
if "BlockOFF" == name then
blockFlag = false
end
end
end
vci.message.On("EffectOFF", entranceCheck)
vci.message.On("BlockOFF", entranceCheck)
function updateAll()
if initialFlag == false then
vci.message.Emit("BovoloInitializeCheck", vci.studio.GetLocalAvatar().GetName())
if initialize1 == true and initialize2 == true then
initialFlag = true
end
elseif initialFlag == true and entranceFlag == false then
vci.message.Emit("ALLVCISetOK", vci.studio.GetLocalAvatar().GetName())
if effectFlag == false and blockFlag == false then
entranceFlag = true
end
end
end
--VCIの読み込み判断関数、ローカルで実行
function initialize(sender, name, message)
if vci.studio.GetLocalAvatar().GetName() == message then
vci.message.Emit("Bovolo1InitializeOK", vci.studio.GetLocalAvatar().GetName())
end
end
vci.message.On("BovoloInitializeCheck", initialize)
function blockStop(sender, name, message)
if vci.studio.GetLocalAvatar().GetName() == message then
block.SetActive(false)
vci.message.Emit("BlockOFF", vci.studio.GetLocalAvatar().GetName())
end
end
vci.message.On("ALLVCISetOK", blockStop)
おわりに
これで、すべてのアイテムが読み込まれまで、待ってもらうような準備が整いました。
よろしければ、みなさんもこんな感じの”待機場所”をルームに作ってもませんか?
実は、「エフェクトVCI」のほうでも少し一工夫があるのですが、それはまた別の機会がありましたら、ご紹介します!