🌐

【Roblox】ネットワーク所有権を操る

2024/03/10に公開

はじめに

こんにちは、まつさこ です。

Roblox Studioでは、通常 Workspace に配置したPartを動かしたい場合、サーバースクリプトを使用する必要があります。

そのためプレイヤーのキー入力などで Workspace 内のPartを動かしたい場合、

  1. LocalScriptでプレイヤー入力を取得
  2. RemoteEventでサーバースクリプトにデータ送信
  3. サーバースクリプトでPartを動かす

という方法をとるのが一般的です。

しかしこの方法だと、ネットワーク環境によっては入力と動作に遅延が発生してしまい、プレイヤーの体験を損なってしまいます。

そこで今回は、Partのネットワーク所有権を適切に移譲することで、 ローカル環境での入力操作を遅延なく行うと同時に、プレイヤー間でPartが同期されている状態 を実現します。

実装方法

■ 手順1

まず Workspace 内にPartを配置してください。分かりやすいようにMyPartという名前にしておきます。


シンプルにPartを一つ配置。この後動かすので、Anchoredはfalseにしておきます。

■ 手順2

MyPartを ReplicatedStorage に移動させます。

ゲームに参加したプレイヤーそれぞれが自分用のMyPartを操作できるように、サーバースクリプトでプレイヤー参加時にMyPartをクローンし、プレイヤーに紐づけるようにします。

CloneMyPart … ServerScriptServiceにScriptとして作成

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local myPart = ReplicatedStorage:WaitForChild("MyPart")
local Players = game:GetService("Players")

local function CloneMyPart(player)
	local clone = myPart:Clone()
	clone.Name = "MyPart_"..player.Name
	clone.Parent = workspace
end

-- すでにゲームにいるプレイヤーに対して実行
for _, player in pairs(Players:GetPlayers()) do
	CloneMyPart(player)
end

-- 新しいプレイヤーが参加した時に実行
Players.PlayerAdded:Connect(CloneMyPart)


MyPart_ユーザー名 という名前のPartが Workspace 内に複製されていることが確認できます。

■ 手順3

ローカルスクリプトで MyPart_ユーザー名 を取得しWASDキーで操作できるようにします。
今回は、 VectorForce を使って力を加えることで MyPart を動かします。

StarterPlayerScripts に次のようなコードを作成します。

MyPartMover

local UserInputService = game:GetService("UserInputService")
local playerName = game.Players.LocalPlayer.Name
local myPart = workspace:WaitForChild("MyPart_"..playerName, 10)

-- MyPartにかける力の方向
local inputVector = Vector3.zero
local speed = 500


UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then return end

	if input.KeyCode == Enum.KeyCode.W then
		inputVector = inputVector + Vector3.new(0, 0, 1)
	elseif input.KeyCode == Enum.KeyCode.S then
		inputVector = inputVector + Vector3.new(0, 0, -1)
	elseif input.KeyCode == Enum.KeyCode.A then
		inputVector = inputVector + Vector3.new(1, 0, 0)
	elseif input.KeyCode == Enum.KeyCode.D then
		inputVector = inputVector + Vector3.new(-1, 0, 0)
	end
end)

UserInputService.InputEnded:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then return end
	if input.KeyCode == Enum.KeyCode.W then
		inputVector = inputVector - Vector3.new(0, 0, 1)
	elseif input.KeyCode == Enum.KeyCode.S then
		inputVector = inputVector - Vector3.new(0, 0, -1)
	elseif input.KeyCode == Enum.KeyCode.A then
		inputVector = inputVector - Vector3.new(1, 0, 0)
	elseif input.KeyCode == Enum.KeyCode.D then
		inputVector = inputVector - Vector3.new(-1, 0, 0)
	end
end)

-- MyPartを動かすためのBodyVelocityを追加
local A = Instance.new("Attachment", myPart)
local vF = Instance.new("VectorForce", myPart)
vF.Attachment0 = A
vF.ApplyAtCenterOfMass = true
vF.RelativeTo = Enum.ActuatorRelativeTo.World
vF.Force = Vector3.new(0, 0, 0) -- 初期速度は0

-- キー入力に応じてMyPartに力を加える
local function UpdateMoveDirection()
	vF.Force = inputVector * speed
	print(tostring(inputVector * speed))
end

game:GetService("RunService").Heartbeat:Connect(function()
	UpdateMoveDirection()
end)

しかしこのままだと、MyPartを動かすことはできません。MyPartのネットワーク所有権がユーザーではなくサーバー側にあるためです。

物理挙動をするPartについて、誰がOwnerであるかをRobloxStudio上で可視化することが出来ます。

File > Studio Settings から、Physics > Are Owners Shown にチェックを入れてください。


自身のアバターは緑色でローカルプレイヤーがOwnerですが、MyPartは白色になっており、サーバーがOwnerであることが分かります。

■ 手順4

サーバースクリプトで対象のPartのネットワーク所有権をプレイヤーに移譲します。

CloneMyPart スクリプトを次のように編集します。

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local myPart = ReplicatedStorage:WaitForChild("MyPart")
local Players = game:GetService("Players")

local function CloneMyPart(player)
	local clone = myPart:Clone()
	clone.Name = "MyPart_"..player.Name
	clone.Parent = workspace
	
	-- ネットワーク所有権をプレイヤーに移譲
	clone:SetNetworkOwner(player)
end

-- すでにゲームにいるプレイヤーに対して実行
for _, player in pairs(Players:GetPlayers()) do
	CloneMyPart(player)
end

-- 新しいプレイヤーが参加した時に実行
Players.PlayerAdded:Connect(CloneMyPart)

すると、MyPartのOwnerカラーが緑になり、WASDキーの入力でプレイヤーアバターと一緒に動くようになりました!

https://youtu.be/w-UWVPPc_0g

まとめ

今回は、ネットワーク所有権を操作することで、Workspace内のPartをプレイヤー入力で遅延なく操作する方法を紹介しました。

タッチ入力と組み合わせたり、乗り物の移動に応用したりすることで、よりゲームの幅が広がりそうですね!

読んでくださりありがとうございました🤗

moze テックブログ

Discussion