VRゲームの作成

VRゲームの作成

Roblox はVRでプレイできるだけではなく、ゲームを作り公開することもできます。いきなり、Roblox でVRゲームを作るのはハードルが高いので、まずはゲームを作ろうからご覧ください。

ここではVRゲームを作るにあたり、基本的なことを書いていくことにします。

VRの検出

まずは、VR以外のプラットフォームではプレイできなくします。VRから実行されていなかった場合は、ゲームから強制退出させます。

  1. テンプレート「Baseplate」から新規作成します。
  2. StarterPlayer の StarterPlayerScripts の中に LocalScript を追加します。
  3. 名前を VRcheck とし、以下のプログラムを入力します。
local Players = game:GetService("Players")
local VRService = game:GetService("VRService")

if VRService.VREnabled then    -- VR機の検出
    print("VR in enabled")
else
    print("VR not enabled")
    Players.LocalPlayer:kick("このゲームはVR専用です")
end

プレイヤー視点にする

デフォルトでは、三人称視点(キャラクターの後ろからの眺め)での開始となります。ゲームに入った瞬間から、キャラクター目線でプレイさせたい場合は、一人称視点に変更しなくてはなりません。こちらはプログラムではなく設定で対応できます。

  1. StarterPlayer の CameraMode プロパティを「LockFirstPerson」に変更します。

これで一人称視点になります。(コントローラーを使っての三人称視点への切り替えは不可)

コントローラーからの入力

VRのコントローラーは、UserInputService の InputBegan と InputEnded のイベントを使用します。
InputBegan はボタンが押されたときに発生するイベントで、InputEnded はボタンが離されたときに発生するイベントです。
テストとして、ボタンが正しく認識されているかどうかを調べるために、パーツにキーコードを表示するプログラムを作成してみます。

  1. Workspace に Part を1つ追加します。
  2. Part の中に SurfaceGui を追加します。
  3. SurfaceGui の中にTextLabelを追加します。
  4. StarterPlayer の StarterPlayerScripts に LocalScriptを追加します。
  5. 名前を VRinput にし、以下のプログラムを入力します。
local UserInputService = game:GetService("UserInputService")
local VRService = game:GetService("VRService")

-- ボタンを押したときに呼ばれる
local function onInputBegan(input, processed)
    workspace.Part.SurfaceGui.TextLabel.Text = tostring(input.KeyCode)
end

-- ボタンを離したときに呼ばれる
local function onInputEnded(input, processed)
    workspace.Part.SurfaceGui.TextLabel.Text = ""
end

UserInputService.InputBegan:Connect(onInputBegan)
UserInputService.InputEnded:Connect(onInputEnded)

パーツの色を変える

次に、特定のボタンが押されたら、パーツの色が変わるようにしてみたいと思います。まず、上記で挿入したパーツの色を変えてみます。VRinput を以下のように変更します。

local UserInputService = game:GetService("UserInputService")
local VRService = game:GetService("VRService")

-- ボタンを押したときに呼ばれる
local function onInputBegan(input, processed)
    workspace.Part.SurfaceGui.TextLabel.Text = tostring(input.KeyCode)

    if input.KeyCode == Enum.KeyCode.ButtonR2 then
        workspace.Part.BrickColor = BrickColor.random()
    end
end

-- ボタンを離したときに呼ばれる
local function onInputEnded(input, processed)
    workspace.Part.SurfaceGui.TextLabel.Text = ""
end

UserInputService.InputBegan:Connect(onInputBegan)
UserInputService.InputEnded:Connect(onInputEnded)

押されたボタンは、input.KeyCode に入ります。「Enum.KeyCode.〇〇〇〇」で判断できます。〇〇〇〇の部分は以下の名称になります。

VRコントローラーからの入力

上記のプログラムはローカル側で実行しますので、他のプレーヤーにはパーツの色が変わったように見えません。Robloxはマルチプレイヤーゲームなので、全プレイヤーに同じものを見せるにはサーバー側でパーツの色を変えなくてはなりません。
もちろんソロプレイのゲームでしたら、この方法で問題ないでしょう。

パーツの色を変える(サーバー処理)

ローカル(クライアント)からサーバーのプログラムを実行したい場合は、RemoteEvent を使います。せっかくなのでパーツの色を変えるだけではなく、他のプロパティも操作できるようにしてみます。

  1. ReplicatedStorage に RemoteEvent を追加し、名前を ChangePartEvent にします。
  2. ServerScriptService に Script を追加し、名前を EventScript にします。
  3. 以下のプログラムを入力します。
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local changePartEvent = ReplicatedStorage.ChangePartEvent

changePartEvent.OnServerEvent:Connect(function(player,part,properties)
    for name,value in pairs(properties) do
        part[name] = value
    end
end)

RemoteEvent の OnServerEvent が、クライアントから呼ばれるものになります。第1パラメーターはPlayer になり、第2パラメータ以降はユーザーが自由に設定することができます。今回は変更したいパーツと、プロパティとその値をテーブルで指定できるようにしました。

呼ぶ方のプログラムは VRinput を少し変更するだけです。

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local VRService = game:GetService("VRService")

-- ボタンを押したときに呼ばれる
local function onInputBegan(input, processed)
    workspace.Part.SurfaceGui.TextLabel.Text = tostring(input.KeyCode)

    if input.KeyCode == Enum.KeyCode.ButtonR2 then
        ReplicatedStorage.ChangePartEvent:FireServer(workspace.Part,{ BrickColor = BrickColor.random() })
    end
end

-- ボタンを離したときに呼ばれる
local function onInputEnded(input, processed)
    workspace.Part.SurfaceGui.TextLabel.Text = ""
end

UserInputService.InputBegan:Connect(onInputBegan)
UserInputService.InputEnded:Connect(onInputEnded)

RemoteEvent の FireServer でサーバープログラムを呼ぶことができます。ただし、FireServer はイベントをキューに入れるだけです。FireServer を多用するとラグが発生し、画面の反応が悪くなるので注意が必要です。そんなこともあり、この ChangePartEvent は、一度に複数個のプロパティが変更できるような仕様にしました。

ChangePartEvent:FireServer(workspace.Part,{ BrickColor = BrickColor.random() , Anchored = false } )

このようにカンマで区切ることで、複数のプロパティが同時に指定できます。

ビームを使う

今度は、コントローラーのビームが当たっているパーツを変化させようと思います。ビームは標準で出ていますのでそのまま利用します。
空中にパーツを複数個設置し、ビームが当たっているパーツのアンカーをオフにし、落下させようと思います。

  1. 複数のパーツを空中に設置し、すべてAnchoredをONにします。
  2. VRinput を以下のように変更します。
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local VRService = game:GetService("VRService")
local Players = game:GetService("Players")

local mouse = Players.LocalPlayer:GetMouse()

-- ボタンを押したときに呼ばれる
local function onInputBegan(input, processed)
    if input.KeyCode == Enum.KeyCode.ButtonR2 then

        if mouse.Target then
            ReplicatedStorage.ChangePartEvent:FireServer(mouse.Target,{ Anchored = false })
        end
    end
end

UserInputService.InputBegan:Connect(onInputBegan)

VRでも、GetMouse() が使用できます。これはクリック(タップ)した場所の情報が取得できるものです。mouse.Target にクリックされたオブジェクトが入りますのでそれが利用できます。ただし上記のプログラムでは、Baseplate もアンカーオフの対象になっていますので、地面をクリックすると落下してしまうでしょう。この辺りはVRだからというものではないので、ご自身で修正してください。

パーツを移動させる

ビームとボタンを使って、パーツを動かしてみようと思います。VRでも DragDetector が使えるようなのでそちらを使用したいところなのですが、ここでは上記のプログラムを追加する形で行ってみたいと思います。

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local VRService = game:GetService("VRService")
local Players = game:GetService("Players")
local mouse = Players.LocalPlayer:GetMouse()

local dragPart = nil
local offset = nil

-- ボタンを押したときに呼ばれる
local function onInputBegan(input, processed)
    if input.KeyCode == Enum.KeyCode.ButtonR2 then
        local target = mouse.Target
        if target and target.Locked == false then
            dragPart = target
            offset = target.Position - mouse.Hit.p
        end
    end
end

-- ボタンを離したときに呼ばれる
local function onInputEnded(input, processed)
    if input.KeyCode == Enum.KeyCode.ButtonR2 then
        if dragPart then
            ReplicatedStorage.ChangePartEvent:FireServer(dragPart,{ Position = dragPart.Position })
            dragPart = nil
        end
    end
end

mouse.Move:Connect(function()
    if dragPart then
        local newPosition = mouse.Hit.p + offset
        dragPart.Position = newPosition
        -- (A)
    end
end)

UserInputService.InputBegan:Connect(onInputBegan)
UserInputService.InputEnded:Connect(onInputEnded)

「target.Locked == false」を入れることでBaseplateが無視されるようにしています。このプログラムでは、ボタンを離したときにRemoteEventを呼んでサーバー側のパーツの位置を変更しています。どのプレイヤーからでもリアルタイムに動かしている様子を見せたい場合は、(A)の部分に、「 ReplicatedStorage.ChangePartEvent:FireServer(dragPart,{ Position = dragPart.Position })」を入れます。ただし、これを行うと重くなるかも知れません。
なお、このプロググラムはパーツの位置に制限を設けていませんので、かなり遠くの方に移動でき、地面にも埋まってしまうでしょう。この辺りはゲームの仕様により異なりますので、ご自身で修正してください。

ステップアップ

VRゲームで有名な Beat Saber というものがあります。これこそVRならではのゲームではないでしょうか。そこで今度はビームサーベルを持ち、自由に動かしてみたいと思います。

VRゲームの作成(2)


ゲーム設定

1つ肝心なことを忘れていました。Steam VRを使えば、Roblox Studio 上でVRゲームの動作確認ができますが、Quest の Roblox から入って実行したい場合は、「ゲーム設定」を変更しなくてはなりません。
ファイルメニューのゲーム設定を実行し、Basic info(基本情報)のPlayable Devices(プレイできるデバイス)の「VR」の項目にチャックを入れます。
最後にファイルメニューの「Publish to Roblox(Robloxに公開)」を実行すれば、Quest の Roblox でプレイできるようになります。

作成したゲームのプレイ方法

Quest の Roblox に入っても、作った自身のゲームが表示されないためすぐにプレイできません。事前にパソコンで一度プレイしておけば、ホームの「続ける」に表示されますのでこれを活用します。

  1. パソコンのブラウザで、Robloxのホーム に行き、「作成」をクリックします。
  2. バーチャル空間の中から作成したゲームをさがし、「…」をクリックします。
  3. メニューから「Robloxで表示」をクリックすると、そのゲームに移動します。

そのゲームをプレイすれば、次からは「続ける」の方に表示されますので、Quest の Roblox 上にも表示されるでしょう。

コメントを残す