【Roblox】ProximityPromptのカスタムUI(2)~タップ入力とボタンアイコン~
1. はじめに
前回の記事で、ProximityPromptのカスタムUIの表示の仕組みを作成しました。
まだ前回の記事を読んでいない方は、先にこちらをご覧ください。
前回までの形だとまだ表示非表示の切り替えしかできていないため、今回はその続きとして、各ProximityPromptInputTypeへの対応を行います。
ProximityPromptInputTypeとはユーザーの操作の入力方式のことで、Touchはスマートデバイスのタッチ操作、Gamepadはゲームパッド(いわゆるコントローラ)、Keyboardはそのままキーボードを示しています。
Robloxはマルチプラットフォームなのでこのようにさまざまな入力方式があるため、汎用的なUIを作る場合、入力の受付はもちろん、UIに表示する操作ガイドのボタンアイコンも、現在のProximityPromptInputTypeとProximityPromptの設定を元に適切なものが表示されるようにする必要があるわけです。
ちなみに、今後はPromptUIの作業中の一時的な配置変更については省略しますので、構築作業の際は確認用Partの子に配置、実行時の動作確認の際はPromptUIFolderの子に配置して行うものとして、適宜対応してください。
バージョン:0.672.0.6720706
2. クリック、タップを可能にする
まずは、PromptUIにクリックやタップでアクセスできるようにしましょう。
PromptUIの子にTextButtonを追加してください。
ただの判定用ボタンなので、名前はそのままで大丈夫です。
BackgroundTransparencyは1、Textは空の状態にして、何も表示されなくします。
SizeはScaleで(1, 1)に設定し、PromptUIのサイズと同じになるようにします。
この状態になったら、TextButtonをPromptUIControllerの子に移動してください。
前回少し触れましたが、クリックできるかどうかはデバイスやProximityPromptの設定によって変動するため、TextButtonを付けるかどうかもScriptで処理します。
PromptUIControllerのCreateメソッドに以下のコードを追加してください。
-- UIに対して動作を設定し、破棄関数を返します.
function promptUIController:Create(prompt: ProximityPrompt, promptUI: BillboardGui, inputType: Enum.ProximityPromptInputType)
----------- 省略 -----------
-- BaseFrameの設定.
local baseFrame = promptUI:WaitForChild("BaseFrame")::Frame
do
------- 省略 -------
end
+ -- ProximityPromptInputTypeがタッチの場合か、ProximityPromptがクリック可能設定である場合、入力受付用のボタンを設定する.
+ if inputType == Enum.ProximityPromptInputType.Touch or prompt.ClickablePrompt then
+ -- TextButtonを複製.
+ local button = script:WaitForChild("TextButton"):Clone()::TextButton
+ button.Parent = promptUI
+
+ local buttonDown = false -- 入力状態を示すフラグ.
+
+ -- 入力時の処理.
+ button.InputBegan:Connect(function(input: InputObject)
+ if (input.UserInputType == Enum.UserInputType.Touch
+ or input.UserInputType == Enum.UserInputType.MouseButton1)
+ and input.UserInputState ~= Enum.UserInputState.Change
+ then
+ -- 入力の開始をProximityPromptに伝える.
+ prompt:InputHoldBegin()
+ buttonDown = true
+ end
+ end)
+
+ -- 入力終了時の処理.
+ button.InputEnded:Connect(function(input: InputObject)
+ if input.UserInputType == Enum.UserInputType.Touch
+ or input.UserInputType == Enum.UserInputType.MouseButton1
+ then
+ if buttonDown then
+ -- 入力の終了をProximityPromptに伝える.
+ buttonDown = false
+ prompt:InputHoldEnd()
+ end
+ end
+ end)
+
+ -- BillboardGuiが入力を受付けるようにActiveをtrueに.
+ promptUI.Active = true
+ end
+
-- イベントを接続.
local connections = {}
----------- 省略 -----------
end
入力を受け付けるために必要な処理を追加しました。
入力可能になる条件は、現在のProximityPromptInputTypeがTouchである場合か、ProximityPrompt.ClickablePromptがtrueの場合としています。
ClickablePromptは、ProximityPromptのUIをクリックでの入力を受け付けるかどうかを設定するプロパティなのですが、カスタムUIの場合、こういったプロパティの反映も自分で行う必要があります。
入力可能にする処理では、TextButtonの複製だけではなく、GuiObject.InputBeganとGuiObject.InputEndedに接続し、入力された際の処理も追加しています。
コールバック関数の中では、ProximityPrompt:InputHoldBeginとProximityPrompt:InputHoldEndを実行しています。
InputHoldBegin, InputHoldEnd
これらのメソッドは、通常ProximityPrompt側で処理している入力に関する情報を、ScriptからProximityPromptに通知できるメソッドです。
InputHoldBeginは入力が開始されたことをProximityPromptに通知して、InputHoldEndが実行されるまでは入力され続けているものとして処理します。
そのままHoldDurationの分時間が経過すれば(0なら即時)Triggerdが発火します。
基本的には、今回のようにカスタムUI上のボタンを押したときの制御に用いるメソッドです。
さて、それではさっそく実行して確認してみましょう。
これで、タップやクリックでの入力が可能になりました!
ちなみに、この後の作成するボタンアイコンにも関係するのですが、UIが表示されている時にProximityPromptInputTypeが変わった場合、PromptHiddenとPromptShownが発火するようになっているため、新しいProximityPromptInputTypeに応じたUIが作り直されることになります。
よって、動的にボタンアイコンやタップでの入力の可否を更新する必要はありません。
3. ボタンアイコンを追加する
では次に、入力すべき操作をユーザーに示すボタンアイコンを表示しましょう。
このアイコンはなかなか手間のかかる部分で、その時のユーザーのProximityPromptInputTypeによって表示を変える必要がある上、キーボードやGamepadの場合、ProximityPromptに設定しているキーやボタンに応じた表示にも対応しなければなりません。
ひとつずつ作っていきましょう。
画像については、Defaultと同じ、公式に用意されているものを使用します。
ボタンアイコンのベースを作る
まずはボタンアイコン用のFrameを追加します。
BaseFrameの子にFrameを一つ追加してください。
名前は「InputFrame」としておきます。
InputFrameのSizeContextをRelativeYYにしてください。
SizeContextとは、SizeをScaleで設定する際に、親のどのSizeを基準にするかを決めるプロパティで、RelativeYYにすると、XもYもどちらも親のYを基準にするようになります。
この状態でSizeをScaleで(1, 1)にしてください。
親のYを基準にした正方形になるはずです。
そして、このFrameはあくまで枠として使うだけですので、BackgroundTransparencyを1にして透明にしてください。
次に、InputFrameの子にもう一つFrameを追加してください。
名前は「RoundFrame」としておきます。
これは、ボタンアイコンの背景になるグレーの円になります。
SizeはOffsetで(48, 48)にしてください。
そして、AnchorPointとPositionをScaleで全て0.5に設定して中央に来るようにしたら、BackgroundColor3はグレー(163, 162, 165)、BackgroundTransparencyは0.5に設定してください。
最後に、RoundFrameの子にUICornerを追加し、CornerRadiusをScaleで1に設定してください。
これで、グレーの円になったはずです。
以下の画像のようになっていればOKです。
続いて、このグレーの円の動作を設定します。
PromptUIControllerのCreateメソッドに以下内容を追記してください。
-- UIに対して動作を設定し、破棄関数を返します.
function promptUIController:Create(prompt: ProximityPrompt, promptUI: BillboardGui, inputType: Enum.ProximityPromptInputType)
------- 省略 -------
-- BaseFrameの設定.
local baseFrame = promptUI:WaitForChild("BaseFrame")::Frame
do
------- 省略 -------
end
+ -- RoundFrameのUIの表示と終了のTweenを作成しリストに追加.
+ do
+ local roundFrame = baseFrame:WaitForChild("InputFrame"):WaitForChild("RoundFrame")::Frame
+ table.insert(tweensForFadeOut, TweenService:Create(roundFrame, tweenInfoFast, { BackgroundTransparency = 1 }))
+ table.insert(tweensForFadeIn, TweenService:Create(roundFrame, tweenInfoFast, { BackgroundTransparency = roundFrame.BackgroundTransparency }))
+
+ -- 初期の透明度を1に.
+ roundFrame.BackgroundTransparency = 1
+ end
+
-- ProximityPromptInputTypeがタッチの場合か、ProximityPromptがクリック可能設定である場合、入力受付用のボタンを設定する.
if inputType == Enum.ProximityPromptInputType.Touch or prompt.ClickablePrompt then
------- 省略 -------
end
BaseFrameと同様、Fadeを設定しました。
これでボタンアイコンのベースの作成は完了です。
タッチ用アイコン
さて、ここから実際に表示するアイコンを作っていきます。
まずは、タッチ操作の場合のアイコンです。
InputFrameの子にImageLabelを一つ追加します。
名前は「TouchButtonImage」としておきます。
RoundFrameと同様にAnchorPointとPositionを中央に来るようにしたら、BackgroundTransparencyを1にして背景を透過してください。
そして、Imageを「rbxasset://textures/ui/Controls/TouchTapIcon.png」に設定してください。
これは、Defaultの場合にタップ時のアイコンに使われているものです。
最後に、Sizeをこの画像に合わせてOffsetで(25, 31)に設定します。
以下の画像のようになっていればOKです。
これで、タップ用のアイコンのImageLabelができました。
ただし、実際にどのアイコンを付けるかはScriptで動的に処理することになります。
適切なボタンアイコンを選択する処理は、他のカスタムUIを作成した際にも流用できそうですので、ModuleScriptとして切り出そうと思います。
というわけで、PromptUIFolderにModuleScriptを追加してください。
名前は「ButtonImageProvider」としておきます。
そして、先ほど作成したTouchButtonImageをButtonImageProviderの子に移動します。
そして、ButtonImageProviderに以下のコードを追加してください。
--!strict
-- ProximityPromptとProximityPromptInputTypeの情報から、適切なボタンアイコンを複製して、
-- FadeのTweenと一緒に返すメソッドを持つモジュールです.
-- Service
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
local ButtonIconProvider = {}
export type ButtonImageTable = {
ButtonImage: ImageLabel,
TweensForFadeIn: {Tween},
TweensForFadeOut: {Tween}
}
-- 適切なボタンアイコンを複製し、FadeのTweenと一緒に返すメソッド.
function ButtonIconProvider:GetButtonImage(prompt: ProximityPrompt, inputType: Enum.ProximityPromptInputType, tweenInfo: TweenInfo): ButtonImageTable?
local buttonImage
local tweensForFadeOut = {}
local tweensForFadeIn = {}
-- ボタンアイコンの生成.
-- タッチ入力の場合.
if inputType == Enum.ProximityPromptInputType.Touch then
-- タッチ入力用のボタンアイコンを作成.
buttonImage = script:WaitForChild("TouchButtonImage"):Clone()
end
-- ボタンアイコン用の表示と終了のTweenを作成.
if buttonImage then
table.insert(tweensForFadeOut, TweenService:Create(buttonImage, tweenInfo, { ImageTransparency = 1 }))
table.insert(tweensForFadeIn, TweenService:Create(buttonImage, tweenInfo, { ImageTransparency = buttonImage.ImageTransparency }))
-- 初期の透明度を1に.
buttonImage.ImageTransparency = 1
else
-- ボタンアイコンを生成できていなかったら終了.
return nil
end
-- tableにして返す.
local result = {
ButtonImage = buttonImage,
TweensForFadeIn = tweensForFadeIn,
TweensForFadeOut = tweensForFadeOut
}::ButtonImageTable
return result
end
return ButtonIconProvider
さらに、PromptUIControllerに以下のコードを追加してください。
--!strict
-- PromptUIの動作を設定するModule
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local Folder = script.Parent
+local ButtonImageProvider = require(Folder:WaitForChild("ButtonImageProvider"))
local promptUIController = {}
------- 省略 -------
-- UIに対して動作を設定し、破棄関数を返します.
function promptUIController:Create(prompt: ProximityPrompt, promptUI: BillboardGui, inputType: Enum.ProximityPromptInputType)
------- 省略 -------
-- RoundFrameのUIの表示と終了のTweenを作成しリストに追加.
do
------- 省略 -------
end
+ -- ボタンアイコンの生成.
+ do
+ local buttonTable = ButtonImageProvider:GetButtonImage(prompt, inputType, tweenInfoFast)
+
+ if buttonTable then
+ -- ボタンアイコンをセット.
+ buttonTable.ButtonImage.Parent = inputFrame
+
+ -- FadeのTweenを配列に追加.
+ table.move(buttonTable.TweensForFadeIn, 1, #buttonTable.TweensForFadeIn, #tweensForFadeIn + 1, tweensForFadeIn)
+ table.move(buttonTable.TweensForFadeOut, 1, #buttonTable.TweensForFadeOut, #tweensForFadeOut + 1, tweensForFadeOut)
+ end
+ end
+
-- ProximityPromptInputTypeがタッチの場合か、ProximityPromptがクリック可能設定である場合、入力受付用のボタンを設定する.
if inputType == Enum.ProximityPromptInputType.Touch or prompt.ClickablePrompt then
------- 省略 -------
end
ButtonImageProviderでは、まずProximityPromptInputTypeを見てボタンアイコンを生成しています。
タッチ用の場合は単純にCloneしているだけです。
ここに各ProximityPromptInputTypeやProximityPromptの設定に応じたボタンアイコンの生成処理が追加されていくイメージです。
生成したらTweenを設定して、テーブルにして返しています。
タプルで返してもよいのですが、Tween配列のどちらがFadeInでどちらがFadeOutなのかが明確になるため、テーブルにしてメンバ名を付けた上で返しています。
PromptUIControllerの方では、ButtonImageProviderをRequireしてメソッドを使用し、返ってきたテーブルからボタンアイコンを設定し、Tweenを配列に追加しています。
これで、タッチ用のボタンアイコンが表示できるようになりました。
ゲームパッド用アイコン
次はゲームパッド(コントローラ)用のアイコンです。
ただし、どのようなコントローラが接続されているかを確認する方法は今のところ提供されていません。
一応、ボタン入力があった際のキーコードから、PS系かXbox系かを判定する方法もなくはないようなのですが、今回はXbox配置を想定した表示にのみ対応することにします。
まずはImageLabelを作成します。
といっても、ほぼタッチ用の流用でOKです。
先ほど作ったTouchButtonImageをコピーし、InputFrameの子に追加して、名前を「GamepadButtonImage」に変更してください。
次に、SizeをOffsetで(24, 24)に変更してください。
そしてImageはScriptで設定するため空白でよいのですが、見え方の確認のため、一旦「rbxasset://textures/ui/Controls/xboxX.png」を付けてみます。
これも、Defaultの場合に使われている画像です。以降も、アイコン画像にはDefaultの画像を用います。
以下の画像のようになっていればOKです。
確認できたら、Imageは空白にして、先ほどと同様ButtonImageProviderの子に移動します。
そして、ButtonImageProviderに以下のソースコードを追加してください。
--!strict
-- ProximityPromptとProximityPromptInputTypeの情報から、適切なボタンアイコンを複製して、
-- FadeのTweenと一緒に返すメソッドを持つモジュールです.
-- Service
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
+-- ボタンアイコン画像.
+local GamepadButtonImage = {
+ [Enum.KeyCode.ButtonX] = "rbxasset://textures/ui/Controls/xboxX.png",
+ [Enum.KeyCode.ButtonY] = "rbxasset://textures/ui/Controls/xboxY.png",
+ [Enum.KeyCode.ButtonA] = "rbxasset://textures/ui/Controls/xboxA.png",
+ [Enum.KeyCode.ButtonB] = "rbxasset://textures/ui/Controls/xboxB.png",
+ [Enum.KeyCode.DPadLeft] = "rbxasset://textures/ui/Controls/dpadLeft.png",
+ [Enum.KeyCode.DPadRight] = "rbxasset://textures/ui/Controls/dpadRight.png",
+ [Enum.KeyCode.DPadUp] = "rbxasset://textures/ui/Controls/dpadUp.png",
+ [Enum.KeyCode.DPadDown] = "rbxasset://textures/ui/Controls/dpadDown.png",
+ [Enum.KeyCode.ButtonSelect] = "rbxasset://textures/ui/Controls/xboxView.png",
+ [Enum.KeyCode.ButtonStart] = "rbxasset://textures/ui/Controls/xboxmenu.png",
+ [Enum.KeyCode.ButtonL1] = "rbxasset://textures/ui/Controls/xboxLB.png",
+ [Enum.KeyCode.ButtonR1] = "rbxasset://textures/ui/Controls/xboxRB.png",
+ [Enum.KeyCode.ButtonL2] = "rbxasset://textures/ui/Controls/xboxLT.png",
+ [Enum.KeyCode.ButtonR2] = "rbxasset://textures/ui/Controls/xboxRT.png",
+ [Enum.KeyCode.ButtonL3] = "rbxasset://textures/ui/Controls/xboxLS.png",
+ [Enum.KeyCode.ButtonR3] = "rbxasset://textures/ui/Controls/xboxRS.png",
+ [Enum.KeyCode.Thumbstick1] = "rbxasset://textures/ui/Controls/xboxLSDirectional.png",
+ [Enum.KeyCode.Thumbstick2] = "rbxasset://textures/ui/Controls/xboxRSDirectional.png",
+}
+
local ButtonIconProvider = {}
export type ButtonImageTable = {
ButtonImage: ImageLabel,
TweensForFadeIn: {Tween},
TweensForFadeOut: {Tween}
}
-- 適切なボタンアイコンを複製し、FadeのTweenと一緒に返すメソッド.
function ButtonIconProvider:GetButtonImage(prompt: ProximityPrompt, inputType: Enum.ProximityPromptInputType, tweenInfo: TweenInfo): ButtonImageTable?
local buttonImage
local tweensForFadeOut = {}
local tweensForFadeIn = {}
-- ボタンアイコンの生成.
-- タッチ入力の場合.
if inputType == Enum.ProximityPromptInputType.Touch then
-- タッチ入力用のボタンアイコンを作成.
buttonImage = script:WaitForChild("TouchButtonImage"):Clone()
+ -- ゲームパッド入力の場合.
+ elseif inputType == Enum.ProximityPromptInputType.Gamepad then
+ -- ProximityPromptに紐づけられているGamepadのKeyCodeに応じた画像のボタンアイコンを作成.
+ if GamepadButtonImage[prompt.GamepadKeyCode] then
+ buttonImage = script:WaitForChild("GamepadButtonImage"):Clone()
+ buttonImage.Image = GamepadButtonImage[prompt.GamepadKeyCode]
+ end
+
end
------- 省略 -------
end
return ButtonIconProvider
最初にGamepad用のアイコン画像のリストが追加され、生成の時にProximityPrompt.GamepadKeyCodeから画像が選択されるようになっています。
これで、ゲームパッド用のボタンアイコンが表示できるようになりました。
キーボード用アイコン
最後に、キーボード用のアイコンです。
他とはちょっと構成が変わり、一番手間のかかるところなのですが、順番にやっていきましょう。
ベースのImageLabel
まずはベースのImageLabelを作ります。
この部分は先ほどと同様にほぼ流用でOKです。
TouchButtonImageをコピーして、InputFrameの子に追加し、名前を「KeyButtonImage」に変更してください。
次に、SizeをOffsetで(28, 30)に変更してください。
そしてImageは「rbxasset://textures/ui/Controls/key_single.png」に設定してください。
これがキーボードのアイコンの土台になります。この画像の上にキー名などを表示するわけです。
以下の画像のようになっていればOKです。
専用の画像を用いるキーのImageLabel
続いて、専用の画像を用いるキーのためのImageLabelを作ります。
KeyButtonImageをコピーして、KeyButtonImageの子に追加し、名前を「KeyIconImage」に変更してください。
次に、SizeをOffsetで(36, 36)に変更してください。
Imageはゲームパッドのものと同様Scriptで設定するのですが、見え方の確認のため、一旦「rbxasset://textures/ui/Controls/return.png」を付けてみます。
これはエンターキーの場合の画像です。
以下の画像のようになっていればOKです。
完成したら、Imageは空白にして、KeyIconImageだけをButtonImageProviderの子に移動してください。
テキストを用いるキーのTextLabel
さらに、画像ではなくテキストで表示する場合のためのTextLabelを作ります。
多くの一般的なキーはこちらで表示することになります。
TextLabelをKeyButtonImageの子に追加してください。
名前は「KeyIconText」としておきます。
BackgroundTransparencyは1、SizeはScaleで(1, 1)にしてください。
そして、位置の微調整のため、PositionはOffsetで(0, -1)にします。
TextColor3は白(255, 255, 255)にしてください。
FontFaceは、Defaultと同じものにするならBuilder Sansなのですが、こちらのフォントは最初はインストールされていないフォントになっています。
とはいえRobloxから配布されているため、追加する場合は、ツールボックスを開きフォントを選択してBuilder Sansで検索すればインストールできるかと思います。
最後に、TextはやはりScriptで設定するのですが、確認のため「E」などのアルファベットを一文字入れてみましょう。
以下の画像のようになっていればOKです。
完成したら、Textは空白にして、KeyIconTextとKeyButtonImageを両方ButtonImageProviderの子に移動します。
配置に注意してください。
そして、ButtonImageProviderに以下のコードを追加してください。
--!strict
-- ProximityPromptとProximityPromptInputTypeの情報から、適切なボタンアイコンを複製して、
-- FadeのTweenと一緒に返すメソッドを持つモジュールです.
-- Service
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
-- ボタンアイコン画像.
local GamepadButtonImage = {
------- 省略 -------
}
+-- キーボードアイコン画像.
+local KeyboardButtonImage = {
+ [Enum.KeyCode.Backspace] = "rbxasset://textures/ui/Controls/backspace.png",
+ [Enum.KeyCode.Return] = "rbxasset://textures/ui/Controls/return.png",
+ [Enum.KeyCode.LeftShift] = "rbxasset://textures/ui/Controls/shift.png",
+ [Enum.KeyCode.RightShift] = "rbxasset://textures/ui/Controls/shift.png",
+ [Enum.KeyCode.Tab] = "rbxasset://textures/ui/Controls/tab.png",
+}
+
+-- キーボード特殊文字アイコン画像.
+local KeyboardButtonIconMapping = {
+ ["'"] = "rbxasset://textures/ui/Controls/apostrophe.png",
+ [","] = "rbxasset://textures/ui/Controls/comma.png",
+ ["`"] = "rbxasset://textures/ui/Controls/graveaccent.png",
+ ["."] = "rbxasset://textures/ui/Controls/period.png",
+ [" "] = "rbxasset://textures/ui/Controls/spacebar.png",
+}
+
+-- 一部キーコードとテキストのマッピング.
+local KeyCodeToTextMapping = {
+ [Enum.KeyCode.LeftControl] = "Ctrl",
+ [Enum.KeyCode.RightControl] = "Ctrl",
+ [Enum.KeyCode.LeftAlt] = "Alt",
+ [Enum.KeyCode.RightAlt] = "Alt",
+ [Enum.KeyCode.F1] = "F1",
+ [Enum.KeyCode.F2] = "F2",
+ [Enum.KeyCode.F3] = "F3",
+ [Enum.KeyCode.F4] = "F4",
+ [Enum.KeyCode.F5] = "F5",
+ [Enum.KeyCode.F6] = "F6",
+ [Enum.KeyCode.F7] = "F7",
+ [Enum.KeyCode.F8] = "F8",
+ [Enum.KeyCode.F9] = "F9",
+ [Enum.KeyCode.F10] = "F10",
+ [Enum.KeyCode.F11] = "F11",
+ [Enum.KeyCode.F12] = "F12",
+}
+
local ButtonIconProvider = {}
export type ButtonImageTable = {
ButtonImage: ImageLabel,
TweensForFadeIn: {Tween},
TweensForFadeOut: {Tween}
}
-- 適切なボタンアイコンを複製し、FadeのTweenと一緒に返すメソッド.
function ButtonIconProvider:GetButtonImage(prompt: ProximityPrompt, inputType: Enum.ProximityPromptInputType, tweenInfo: TweenInfo): ButtonImageTable?
local buttonImage
local tweensForFadeOut = {}
local tweensForFadeIn = {}
-- ボタンアイコンの生成.
-- タッチ入力の場合.
if inputType == Enum.ProximityPromptInputType.Touch then
-- タッチ入力用のボタンアイコンを作成.
buttonImage = script:WaitForChild("TouchButtonImage"):Clone()
-- ゲームパッド入力の場合.
elseif inputType == Enum.ProximityPromptInputType.Gamepad then
-- ProximityPromptに紐づけられているGamepadのKeyCodeに応じた画像のボタンアイコンを作成.
if GamepadButtonImage[prompt.GamepadKeyCode] then
buttonImage = script:WaitForChild("GamepadButtonImage"):Clone()
buttonImage.Image = GamepadButtonImage[prompt.GamepadKeyCode]
end
+ -- それ以外(キーボード入力)の場合.
+ else
+ -- キーボード入力用のボタンアイコンのベースを作成.
+ buttonImage = script:WaitForChild("KeyButtonImage"):Clone()
+
+ -- ProximityPromptに紐づけられているKeyCodeを文字列で取得.
+ local buttonTextString = UserInputService:GetStringForKeyCode(prompt.KeyboardKeyCode)
+
+ -- 専用画像を用いるキーボード用ボタンアイコン画像を取得.
+ local buttonTextImage = KeyboardButtonImage[prompt.KeyboardKeyCode]
+
+ -- 取得できなかった場合、特殊文字用のボタンアイコン画像を取得.
+ if buttonTextImage == nil then
+ buttonTextImage = KeyboardButtonIconMapping[buttonTextString]
+ end
+
+ -- さらに取得できなかった場合、専用画像を用いないキーとしての処理を行う.
+ if buttonTextImage == nil then
+ -- Ctrlなどの一部のキーコード用の文字列を取得しなおす.
+ if KeyCodeToTextMapping[prompt.KeyboardKeyCode] then
+ buttonTextString = KeyCodeToTextMapping[prompt.KeyboardKeyCode]
+ end
+ end
+
+ -- この時点で画像が取得できている(専用画像を用いるキーコードだった)場合.
+ if buttonTextImage then
+ local icon = script:WaitForChild("KeyIconImage"):Clone()
+ icon.Image = buttonTextImage
+
+ -- アイコン部分用の表示と終了のTweenを作成.
+ table.insert(tweensForFadeOut, TweenService:Create(icon, tweenInfo, { ImageTransparency = 1 }))
+ table.insert(tweensForFadeIn, TweenService:Create(icon, tweenInfo, { ImageTransparency = icon.ImageTransparency }))
+
+ -- 初期の透明度を1に.
+ icon.ImageTransparency = 1
+
+ -- ButtonImageの子にする.
+ icon.Parent = buttonImage
+
+ -- 専用画像を用いないキーで、文字列が取得できている場合.
+ elseif buttonTextString ~= nil and buttonTextString ~= "" then
+ local buttonText = script:WaitForChild("KeyIconText"):Clone()
+ buttonText.Text = buttonTextString
+
+ -- 二文字以上ならTextSizeを12に下げる.
+ if string.len(buttonTextString) > 2 then
+ buttonText.TextSize = 12
+ end
+
+ -- アイコン部分用の表示と終了のTweenを作成.
+ table.insert(tweensForFadeOut, TweenService:Create(buttonText, tweenInfo, { TextTransparency = 1 }))
+ table.insert(tweensForFadeIn, TweenService:Create(buttonText, tweenInfo, { TextTransparency = buttonText.TextTransparency }))
+
+ -- 初期の透明度を1に.
+ buttonText.TextTransparency = 1
+
+ -- ButtonImageの子にする.
+ buttonText.Parent = buttonImage
+
+ else
+ -- 非対応のキーコードなので破棄して終了.
+ buttonImage:Destroy()
+ return nil
+ end
end
------- 省略 -------
end
return ButtonIconProvider
最初に、専用画像を用いるキーの画像リスト、一部の特殊な文字の画像リスト、一部のキーコードとテキストをマップしたリストの三つが追加されています。
処理の部分では、ボタンアイコンのベースを複製した後、ProximityPrompt.KeyboardKeyCodeをUserInputService:GetStringForKeyCodeに渡して、KeyCodeを表示用のstringで取得します。
さらに、KeyboardButtonImageのリストから専用画像を用いるボタンアイコン画像を取得します。
この時、リストにキーが無く取得したのがnilだったなら、専用画像を用いるものではないとして、次にKeyboardButtonIconMappingのリストから一部の特殊文字用のボタンアイコン画像を取得します。
それでも取得できなかった場合、画像を使うものではないということになりますが、一部のキーは表示用にテキストを調整したいものがあるため、KeyCodeToTextMappingのリストにあるものはstringを取得しなおします。
これで、「表示する画像のID」または「表示するstring」が取得できました。
その上で、「使用する画像のID」がnilかどうかで、画像とstringどちらを表示するのかを区別できます。
その後は、画像であればKeyIconImageを、stringであればKeyIconTextを生成し、設定を行っています。
stringの場合、文字数が二文字以上ならTextLabel.TextSizeを12にしています。
デフォルトでは14なので、Textが長くなる分、少し小さくしている感じです。
最後に、一応ここまでの間で画像もstringも取得できていなかった場合、非対応のキーコードとして終了してnilを返しています。
この場合、エラーを出すようにしてもよいでしょう。
動作確認
ようやく各ボタンアイコンの作成が終わったので、さっそく実行して確認してみましょう。
実行する際は、タッチ入力を検証するため、テストタブからデバイスの仮想化をONにし、iPhone 14 Proなどのスマートデバイスを選択してください。
仮想的に選択したデバイスで実行している状態になります。
この状態で実行すると、マウスクリックが仮想的にタッチ入力として扱われ、ProximityPromptInputTypeはTouchになります。
このままでもキーボードで操作するとProximityPromptInputTypeはKeyboardになるので、そちらも検証可能です。
さらに、同じくテストタブからコントローラの仮想化をONにすると、キーボード入力が仮想的にコントローラ入力として扱われ、ProximityPromptInputTypeはGamepadになります。
これらの仮想化機能を使って、各ProximityPromptInputTypeでの表示を確認してみます。
これで、ボタンアイコンの表示ができました!
確認する際は、ProximityPromptのKeyboardKeyCodeやGamepadKeyCodeを色々と変えて、きちんと対応できているかを確かめておきましょう。
4. サンプルコード
今回作成した最終的なサンプルコードを掲載しておきます。
PromptUIDispatcher
--!strict
-- Service
local ProximityPromptService = game:GetService("ProximityPromptService")
local Players = game:GetService("Players")
-- Variable
local LocalPlayer = Players.LocalPlayer
local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")
local Folder = game:GetService("ReplicatedStorage"):WaitForChild("PromptUIFolder")
-- プロンプト用のScreenGuiを取得する関数.
local function getScreenGui()
-- プロンプト用のScreenGui取得.
local screenGui = PlayerGui:FindFirstChild("ProximityPrompts")
-- 存在しなかったら作成.
if screenGui == nil then
screenGui = Instance.new("ScreenGui")
screenGui.Name = "ProximityPrompts"
screenGui.ResetOnSpawn = false
screenGui.Parent = PlayerGui
end
-- 取得ないし作成したScreenGuiを返す.
return screenGui
end
-- PromptのUIを作成し、破棄関数を返します.
local function createPrompt(prompt: ProximityPrompt, inputType: Enum.ProximityPromptInputType, gui: ScreenGui)
-- UIを複製.
local promptUI = Folder:WaitForChild("PromptUI"):Clone()
-- BillboardGuiのターゲットと親を設定.
promptUI.Adornee = prompt.Parent
promptUI.Parent = gui
-- PromptUIControllerをrequire
local promptController = require(Folder:WaitForChild("PromptUIController"))
-- 動作を設定して破棄関数を返す.
return promptController:Create(prompt, promptUI, inputType)
end
-- ProximityPromptService.PromptShownに、カスタムUIの表示を接続します.
local function onLoad()
-- ProximityPromptService.PromptShownに接続.
ProximityPromptService.PromptShown:Connect(function(prompt: ProximityPrompt, inputType: Enum.ProximityPromptInputType)
-- デフォルトだったら(カスタムじゃなかったら)処理しない.
if prompt.Style == Enum.ProximityPromptStyle.Default then
return
end
-- プロンプト用のScreenGuiを取得.
local gui = getScreenGui()
-- カスタムUI作成、戻り値で破棄関数が渡される.
local cleanupFunction = createPrompt(prompt, inputType, gui)
-- PromptHidden待ち.
-- PromptHiddenはProximityPromptから離れた時等だけではなく、InputTypeが切り替わった時にも発火する.
prompt.PromptHidden:Wait()
-- 破棄関数を実行.
cleanupFunction()
end)
end
-- 実行.
onLoad()
PromptUIController
--!strict
-- PromptUIの動作を設定するModule
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local Folder = script.Parent
local ButtonImageProvider = require(Folder:WaitForChild("ButtonImageProvider"))
local promptUIController = {}
-- Tweenの配列を全てPlayする関数.
local function tweenPlayAll(tweens: {Tween})
for _, v in ipairs(tweens) do
v:Play()
end
end
-- UIに対して動作を設定し、破棄関数を返します.
function promptUIController:Create(prompt: ProximityPrompt, promptUI: BillboardGui, inputType: Enum.ProximityPromptInputType)
-- 各Tweenを一斉実行するための配列.
local tweensForButtonHoldBegin = {}
local tweensForButtonHoldEnd = {}
local tweensForFadeOut = {}
local tweensForFadeIn = {}
local fadeDuration = 0.2
local tweenInfoFast = TweenInfo.new(fadeDuration)
-- BaseFrameの設定.
local baseFrame = promptUI:FindFirstChild("BaseFrame")::Frame
do
-- Tweenの作成.
local fadeOut = TweenService:Create(baseFrame, tweenInfoFast, {BackgroundTransparency = 1})
local fadeIn = TweenService:Create(baseFrame, tweenInfoFast, {BackgroundTransparency = baseFrame.BackgroundTransparency})
-- リストに追加.
table.insert(tweensForButtonHoldBegin, fadeOut)
table.insert(tweensForButtonHoldEnd, fadeIn)
table.insert(tweensForFadeOut, fadeOut)
table.insert(tweensForFadeIn, fadeIn)
-- 初期の透明度を1に.
baseFrame.BackgroundTransparency = 1
end
-- RoundFrameのUIの表示と終了のTweenを作成しリストに追加.
local inputFrame = baseFrame:FindFirstChild("InputFrame")::Frame
do
local roundFrame = inputFrame:FindFirstChild("RoundFrame")::Frame
table.insert(tweensForFadeOut, TweenService:Create(roundFrame, tweenInfoFast, { BackgroundTransparency = 1 }))
table.insert(tweensForFadeIn, TweenService:Create(roundFrame, tweenInfoFast, { BackgroundTransparency = roundFrame.BackgroundTransparency }))
-- 初期の透明度を1に.
roundFrame.BackgroundTransparency = 1
end
-- ボタンアイコンの生成.
do
-- ボタンアイコンとそのTweenを取得.
local buttonTable = ButtonImageProvider:GetButtonImage(prompt, inputType, tweenInfoFast)
if buttonTable then
-- ボタンアイコンの親をInputFrameに.
buttonTable.ButtonImage.Parent = inputFrame
-- FadeのTweenを配列に追加.
table.move(buttonTable.TweensForFadeIn, 1, #buttonTable.TweensForFadeIn, #tweensForFadeIn + 1, tweensForFadeIn)
table.move(buttonTable.TweensForFadeOut, 1, #buttonTable.TweensForFadeOut, #tweensForFadeOut + 1, tweensForFadeOut)
end
end
-- InputTypeがタッチの場合か、ProximityPromptがクリック可能設定である場合、入力受付用のボタンを設定する.
if inputType == Enum.ProximityPromptInputType.Touch or prompt.ClickablePrompt then
-- TextButtonを複製.
local button = script:WaitForChild("TextButton"):Clone()::TextButton
button.Parent = promptUI
local buttonDown = false -- 入力状態を示すフラグ.
-- 入力時の処理.
button.InputBegan:Connect(function(input: InputObject)
if (input.UserInputType == Enum.UserInputType.Touch
or input.UserInputType == Enum.UserInputType.MouseButton1)
and input.UserInputState ~= Enum.UserInputState.Change
then
-- 入力の開始をProximityPromptに伝える.
prompt:InputHoldBegin()
buttonDown = true
end
end)
-- 入力終了時の処理.
button.InputEnded:Connect(function(input: InputObject)
if input.UserInputType == Enum.UserInputType.Touch
or input.UserInputType == Enum.UserInputType.MouseButton1
then
if buttonDown then
-- 入力の終了をProximityPromptに伝える.
buttonDown = false
prompt:InputHoldEnd()
end
end
end)
-- BillboardGuiが入力を受付けるようにActiveをtrueに.
promptUI.Active = true
end
-- イベントを接続.
local connections = {}
-- Holdが必要なProximityPromptの場合.
if prompt.HoldDuration > 0 then
table.insert(connections, prompt.PromptButtonHoldBegan:Connect(function(playerWhoTriggered: Player)
tweenPlayAll(tweensForButtonHoldBegin)
end))
table.insert(connections, prompt.PromptButtonHoldEnded:Connect(function(playerWhoTriggered: Player)
tweenPlayAll(tweensForButtonHoldEnd)
end))
end
table.insert(connections, prompt.Triggered:Connect(function(playerWhoTriggered: Player)
tweenPlayAll(tweensForFadeOut)
end))
table.insert(connections, prompt.TriggerEnded:Connect(function(playerWhoTriggered: Player)
tweenPlayAll(tweensForFadeIn)
end))
-- ProximityPromptの情報を元にUIを更新する関数を定義.
local function updateUIFromPrompt()
-- AutomaticSizeが反映されるのはRenderStepped直前のため、次のRenderSteppedまで待機する.
RunService.RenderStepped:Wait()
-- Size.XはBaseFrameのXに合わせる.
promptUI.Size = UDim2.fromOffset(baseFrame.AbsoluteSize.X, promptUI.Size.Y.Offset)
-- Prompt.UIOffsetを反映.
-- ProximityPrompt.UIOffsetはピクセル単位の値だが、BillboardGui.SizeOffsetはBillboardGui自体の大きさを基準としたScaleの値なので、BillboardGuiのサイズで割ることで変換している.
promptUI.SizeOffset = Vector2.new(prompt.UIOffset.X / promptUI.Size.X.Offset, prompt.UIOffset.Y / promptUI.Size.Y.Offset)
end
-- Changedイベントに接続し、ProximityPromptプロパティが変更された際にUIを更新.
table.insert(connections, prompt.Changed:Connect(updateUIFromPrompt))
-- 一度実行しておき、UIを更新.
updateUIFromPrompt()
-- 開幕のFadeInを実行.
tweenPlayAll(tweensForFadeIn)
-- 後始末を行う関数を定義.
local function cleanup()
-- イベント接続を破棄.
for _, v in ipairs(connections) do
v:Disconnect()
end
-- FadeOut.
tweenPlayAll(tweensForFadeOut)
task.wait(fadeDuration)
-- 破棄.
promptUI:Destroy()
end
-- 破棄関数を返す.
return cleanup
end
return promptUIController
ButtonImageProvider
--!strict
-- ProximityPromptとProximityPromptInputTypeの情報から、適切なボタンアイコンを複製して、
-- FadeのTweenと一緒に返すメソッドを持つモジュールです.
-- Service
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
-- ボタンアイコン画像.
local GamepadButtonImage = {
[Enum.KeyCode.ButtonX] = "rbxasset://textures/ui/Controls/xboxX.png",
[Enum.KeyCode.ButtonY] = "rbxasset://textures/ui/Controls/xboxY.png",
[Enum.KeyCode.ButtonA] = "rbxasset://textures/ui/Controls/xboxA.png",
[Enum.KeyCode.ButtonB] = "rbxasset://textures/ui/Controls/xboxB.png",
[Enum.KeyCode.DPadLeft] = "rbxasset://textures/ui/Controls/dpadLeft.png",
[Enum.KeyCode.DPadRight] = "rbxasset://textures/ui/Controls/dpadRight.png",
[Enum.KeyCode.DPadUp] = "rbxasset://textures/ui/Controls/dpadUp.png",
[Enum.KeyCode.DPadDown] = "rbxasset://textures/ui/Controls/dpadDown.png",
[Enum.KeyCode.ButtonSelect] = "rbxasset://textures/ui/Controls/xboxView.png",
[Enum.KeyCode.ButtonStart] = "rbxasset://textures/ui/Controls/xboxmenu.png",
[Enum.KeyCode.ButtonL1] = "rbxasset://textures/ui/Controls/xboxLB.png",
[Enum.KeyCode.ButtonR1] = "rbxasset://textures/ui/Controls/xboxRB.png",
[Enum.KeyCode.ButtonL2] = "rbxasset://textures/ui/Controls/xboxLT.png",
[Enum.KeyCode.ButtonR2] = "rbxasset://textures/ui/Controls/xboxRT.png",
[Enum.KeyCode.ButtonL3] = "rbxasset://textures/ui/Controls/xboxLS.png",
[Enum.KeyCode.ButtonR3] = "rbxasset://textures/ui/Controls/xboxRS.png",
[Enum.KeyCode.Thumbstick1] = "rbxasset://textures/ui/Controls/xboxLSDirectional.png",
[Enum.KeyCode.Thumbstick2] = "rbxasset://textures/ui/Controls/xboxRSDirectional.png",
}
-- キーボードアイコン画像.
local KeyboardButtonImage = {
[Enum.KeyCode.Backspace] = "rbxasset://textures/ui/Controls/backspace.png",
[Enum.KeyCode.Return] = "rbxasset://textures/ui/Controls/return.png",
[Enum.KeyCode.LeftShift] = "rbxasset://textures/ui/Controls/shift.png",
[Enum.KeyCode.RightShift] = "rbxasset://textures/ui/Controls/shift.png",
[Enum.KeyCode.Tab] = "rbxasset://textures/ui/Controls/tab.png",
}
-- キーボード特殊文字アイコン画像.
local KeyboardButtonIconMapping = {
["'"] = "rbxasset://textures/ui/Controls/apostrophe.png",
[","] = "rbxasset://textures/ui/Controls/comma.png",
["`"] = "rbxasset://textures/ui/Controls/graveaccent.png",
["."] = "rbxasset://textures/ui/Controls/period.png",
[" "] = "rbxasset://textures/ui/Controls/spacebar.png",
}
-- 一部キーコードとテキストのマッピング.
local KeyCodeToTextMapping = {
[Enum.KeyCode.LeftControl] = "Ctrl",
[Enum.KeyCode.RightControl] = "Ctrl",
[Enum.KeyCode.LeftAlt] = "Alt",
[Enum.KeyCode.RightAlt] = "Alt",
[Enum.KeyCode.F1] = "F1",
[Enum.KeyCode.F2] = "F2",
[Enum.KeyCode.F3] = "F3",
[Enum.KeyCode.F4] = "F4",
[Enum.KeyCode.F5] = "F5",
[Enum.KeyCode.F6] = "F6",
[Enum.KeyCode.F7] = "F7",
[Enum.KeyCode.F8] = "F8",
[Enum.KeyCode.F9] = "F9",
[Enum.KeyCode.F10] = "F10",
[Enum.KeyCode.F11] = "F11",
[Enum.KeyCode.F12] = "F12",
}
local ButtonIconProvider = {}
export type ButtonImageTable = {
ButtonImage: ImageLabel,
TweensForFadeIn: {Tween},
TweensForFadeOut: {Tween}
}
-- 適切なボタンアイコンを複製し、FadeのTweenと一緒に返すメソッド.
function ButtonIconProvider:GetButtonImage(prompt: ProximityPrompt, inputType: Enum.ProximityPromptInputType, tweenInfo: TweenInfo): ButtonImageTable?
local buttonImage
local tweensForFadeOut = {}
local tweensForFadeIn = {}
-- ボタンアイコンの生成.
-- タッチ入力の場合.
if inputType == Enum.ProximityPromptInputType.Touch then
-- タッチ入力用のボタンアイコンを作成.
buttonImage = script:WaitForChild("TouchButtonImage"):Clone()
-- ゲームパッド入力の場合.
elseif inputType == Enum.ProximityPromptInputType.Gamepad then
-- ProximityPromptに紐づけられているGamepadのKeyCodeに応じた画像のボタンアイコンを作成.
if GamepadButtonImage[prompt.GamepadKeyCode] then
buttonImage = script:WaitForChild("GamepadButtonImage"):Clone()
buttonImage.Image = GamepadButtonImage[prompt.GamepadKeyCode]
end
-- それ以外(キーボード入力)の場合.
else
-- キーボード入力用のボタンアイコンのベースを作成.
buttonImage = script:WaitForChild("KeyButtonImage"):Clone()
-- ProximityPromptに紐づけられているKeyCodeを文字列で取得.
local buttonTextString = UserInputService:GetStringForKeyCode(prompt.KeyboardKeyCode)
-- 専用画像を用いるキーボード用ボタンアイコン画像を取得.
local buttonTextImage = KeyboardButtonImage[prompt.KeyboardKeyCode]
-- 取得できなかった場合、特殊文字用のボタンアイコン画像を取得.
if buttonTextImage == nil then
buttonTextImage = KeyboardButtonIconMapping[buttonTextString]
end
-- さらに取得できなかった場合、専用画像を用いないキーとしての処理を行う.
if buttonTextImage == nil then
-- Ctrlなどの一部のキーコード用の文字列を取得しなおす.
if KeyCodeToTextMapping[prompt.KeyboardKeyCode] then
buttonTextString = KeyCodeToTextMapping[prompt.KeyboardKeyCode]
end
end
-- この時点で画像が取得できている(専用画像を用いるキーコードだった)場合.
if buttonTextImage then
local icon = script:WaitForChild("KeyIconImage"):Clone()
icon.Image = buttonTextImage
-- アイコン部分用の表示と終了のTweenを作成.
table.insert(tweensForFadeOut, TweenService:Create(icon, tweenInfo, { ImageTransparency = 1 }))
table.insert(tweensForFadeIn, TweenService:Create(icon, tweenInfo, { ImageTransparency = icon.ImageTransparency }))
-- 初期の透明度を1に.
icon.ImageTransparency = 1
-- ButtonImageの子にする.
icon.Parent = buttonImage
-- 専用画像を用いないキーで、文字列が取得できている場合.
elseif buttonTextString ~= nil and buttonTextString ~= "" then
local buttonText = script:WaitForChild("KeyIconText"):Clone()
buttonText.Text = buttonTextString
-- 二文字以上ならTextSizeを12に下げる.
if string.len(buttonTextString) > 2 then
buttonText.TextSize = 12
end
-- アイコン部分用の表示と終了のTweenを作成.
table.insert(tweensForFadeOut, TweenService:Create(buttonText, tweenInfo, { TextTransparency = 1 }))
table.insert(tweensForFadeIn, TweenService:Create(buttonText, tweenInfo, { TextTransparency = buttonText.TextTransparency }))
-- 初期の透明度を1に.
buttonText.TextTransparency = 1
-- ButtonImageの子にする.
buttonText.Parent = buttonImage
else
-- 非対応のキーコードなので破棄して終了.
buttonImage:Destroy()
return nil
end
end
-- ボタンアイコン用の表示と終了のTweenを作成.
if buttonImage then
table.insert(tweensForFadeOut, TweenService:Create(buttonImage, tweenInfo, { ImageTransparency = 1 }))
table.insert(tweensForFadeIn, TweenService:Create(buttonImage, tweenInfo, { ImageTransparency = buttonImage.ImageTransparency }))
-- 初期の透明度を1に.
buttonImage.ImageTransparency = 1
else
-- ボタンアイコンを生成できていなかったら終了.
return nil
end
-- tableにして返す.
local result = {
ButtonImage = buttonImage,
TweensForFadeIn = tweensForFadeIn,
TweensForFadeOut = tweensForFadeOut
}::ButtonImageTable
return result
end
return ButtonIconProvider
5. まとめ
- ProximityPromptInputTypeは、Touch, Gamepad, Keyboardの三種類がある
- ProximityPrompt:InputHoldBegin, InputHoldEndで、入力があったこと、離されたことをProximityPromptに通知することができる
- Touch用のアイコンは一種類でOK
- Gamepad用のアイコンは、ProximityPrompt.GamepadKeyCodeに応じて選ぶ
- Keyboard用のアイコンは、ProximityPrompt.KeyboardKeyCodeに応じて選び、物によって画像とテキストを使い分ける
- Roblox Studioの仮想化機能を使う事で、仮想的に特定のデバイスで実行している状態で動作確認ができる
- コントローラの仮想化をONにすると、キーボード入力を仮想的にコントローラ入力に変換した状態で動作確認ができる
今回は、各ProximityPromptInputTypeへの対応を行いました。
なかなかの物量で大変だったかと思いますが、これでさまざまな入力方式に汎用的に対応できるようになりました。
次回以降にご紹介する機能についても同様なのですが、実際に制作する際は、そのUIで利用したい機能さえあればよいので、ProximityPromptInputTypeの三種類にだけ対応して、表示するキーはProximityPromptに設定しているもののみを用意するなど、取捨選択して必要最低限の機能のものを作るのが良いかと思います。
この記事を参考に、ゲームに合わせたUI制作を行ってみてください!
そして次回は、ObjectTextとActionTextの表示を実装します。
そちらもぜひご覧ください!
最後までお読みいただき、ありがとうございました!
6. 参考

当社ではRobloxを活用したゲームの開発、 また企業の商品やサービスの認知度拡大に寄与する3Dワールドの制作など、 Robloxにおける様々な活用支援を行っております。 Robloxのコンテンツ開発をご検討されている企業様は、お気軽にご相談ください。 landho.co.jp/
Discussion