この記事で作るもの
ドアに近づいて「開く」を操作すると板が右へ滑り、次の「閉じる」で元へ戻る仕組みを作ります。Roblox Studioの新規Baseplateと、サーバー側のScriptを使います。最初は壁を作り込まず、1枚のPartの動きを確かめます。
TweenServiceは、指定した時間をかけてプロパティを目標値へ変える仕組みです。ここではドアのCFrameを0.8秒かけて移動します。クライアントだけで動かさず、サーバーで変更するので、同じサーバー内のプレイヤーが同じドアを見ます。TweenServiceの公式資料
1. ドアと操作表示を置く
WorkspaceへPartを作り、SlidingDoorと名付けます。次の数値はBaseplateの上面がY=0の場合です。床を移動している場合は高さも合わせます。
| 対象 | Propertiesの設定 |
|---|---|
| SlidingDoor | Size (6, 8, 1)、Position (0, 4, -8)、Orientation (0, 0, 0) |
| SlidingDoor | Anchoredオン、CanCollideオン |
| 子のProximityPrompt | ObjectText スライドドア、ActionText 開く |
| ProximityPrompt | KeyboardKeyCode E、HoldDuration 0 |
| ProximityPrompt | MaxActivationDistance 10、Enabledオン |
| ProximityPrompt | RequiresLineOfSightオフ |
PromptをSlidingDoorの直接の子にします。RequiresLineOfSightをオフにするのは、板の裏側からも試しやすくするためです。この教材では見通しを操作条件に含めません。壁越しの操作を防ぐ設計へ進める場合は、その条件も追加します。ProximityPromptの公式資料
Workspace
Baseplate
SlidingDoor (Part)
ProximityPrompt
ServerScriptService
SlidingDoorServer (Script)
ServerScriptServiceへ通常のScriptを追加し、SlidingDoorServerと名付けます。ドアを動かす別のScriptやTweenは、この例に重ねません。
2. サーバーで開閉する
local TweenService = game:GetService("TweenService")
local door = workspace:WaitForChild("SlidingDoor")
assert(door:IsA("BasePart"), "SlidingDoorはPartにしてください")
local prompt = door:WaitForChild("ProximityPrompt")
assert(prompt:IsA("ProximityPrompt"), "ProximityPromptを追加してください")
local closedCFrame = door.CFrame
local openCFrame = closedCFrame + Vector3.new(8, 0, 0)
local tweenInfo = TweenInfo.new(0.8, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut)
local isOpen = false
local busy = false
prompt.ActionText = "開く"
prompt.Triggered:Connect(function(player)
if busy or not prompt.Enabled then
return
end
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
if not root or not root:IsA("BasePart") or not humanoid or humanoid.Health <= 0 then
return
end
if (root.Position - door.Position).Magnitude > prompt.MaxActivationDistance + 2 then
return
end
busy = true
prompt.Enabled = false
local target = isOpen and closedCFrame or openCFrame
local tween = TweenService:Create(door, tweenInfo, { CFrame = target })
tween:Play()
local playbackState = tween.Completed:Wait()
if playbackState == Enum.PlaybackState.Completed then
isOpen = not isOpen
end
prompt.ActionText = isOpen and "閉じる" or "開く"
busy = false
prompt.Enabled = true
end)
移動先は、開始時の位置を基準に固定しています。押すたびに現在位置へ8を足す構成ではないので、開閉を繰り返してもドアが遠くへずれていきません。ここでいう右はワールド座標の+X方向です。ドアの向きを変えても移動方向は変わりません。
3. 動作中の再受付を止める
busyで処理の重なりを防ぎ、prompt.Enabled = falseで移動中の操作表示を消します。Promptの表示設定だけに頼らず、サーバー側でも受付状態、キャラクターの生存、距離を確認します。距離の+ 2は、この教材で設けた2 studsの余裕です。クライアントからの操作を検証する公式ガイド
Completedは、途中でキャンセルされた場合にも発火します。そのため、戻り値がEnum.PlaybackState.Completedのときだけ開閉状態を切り替えます。この例ではキャンセル処理を追加していませんが、完了通知をそのまま成功と扱わない形にしています。TweenBase.Completedの公式資料
開いている間は「閉じる」、閉じている間は「開く」と表示します。ドアと一緒にPromptも動くため、開いた後に離れすぎた場合は、動いたドアの近くへ歩くと再び表示されます。
動作確認
キャラクターが出現するTest(F5)で確認します。Runではキャラクターが作られないので、近づいて操作する確認はできません。
| 操作 | 期待する結果 |
|---|---|
| 閉じたドアへ近づく | 「スライドドア」「開く」が表示される |
| Eで操作する | 表示が消え、0.8秒で+Xへ8 studs移動する |
| 移動中に操作を繰り返す | 逆方向のTweenが重ならない |
| 開いたドアへ近づく | 「閉じる」が表示される |
| 再び操作する | 元の位置へ戻り、「開く」になる |
| 開閉を数回繰り返す | 閉じる位置が最初の位置からずれない |
次にTestを終了し、Server & Clientsでクライアント2人を起動します。片方が操作したドアの位置を、もう片方からも確認します。Studioのテストモード
うまく動かないとき
- ドアが落ちる:Anchoredをオンにします。AnchoredでもコードやTweenで位置は変えられます。
- 操作表示が出ない:Promptの親、Enabled、MaxActivationDistanceを確認し、ドアへ近づきます。
- WaitForChildの警告が出る:Workspace直下のSlidingDoorと、その子ProximityPromptの名前を確認します。
- 開く方向が想定と違う:この例はワールド+Xへ動かします。ローカル方向への移動とは区別します。
- 2人の画面で位置が違う:ScriptがServerScriptServiceにあり、LocalScriptや別の移動処理を使っていないか確認します。
この例は鍵・権限・挟み込みの検知を含みません。閉まる場所にプレイヤーがいる場合の停止や押し戻しは、実ゲームへ組み込む際に別途設計します。固定したPartの設定はPartとAnchoredの基本でも確認できます。
この記事のまとめ
Roblox Studioで近づいて操作できるスライドドアを作ります。PartとPromptの配置、サーバーの距離確認、Tween完了待ち、動作中の連打防止を図とコードで解説します。