🅰️

【Roblox】ProximityPromptのカスタムUI(1)~表示切り替えとFadeIn, FadeOut~

に公開

1. はじめに

みなさんはProximityPromptを利用されていますでしょうか?

いわゆる「インタラクトボタン」などと呼ばれる、UIでユーザーにボタンなどの入力を促して、その入力があったら処理を行う仕組みを持つオブジェクトです。
色んな所で使われているので、Robloxのゲームをプレイしていたら、どこかしらで見たことはあるかと思います。
このProximityPromptで表示されるUIは、デフォルトのままでもいいのですが、自分で作成したUIを表示することもできます。
今回から全4回にわたって、このProximityPromptのカスタムUIについてご紹介していこうと思います。

バージョン:0.672.0.6720706

2. ProximityPromptの基本

本題に入る前に、ProximityPromptをまだ触ったことのない方のために基本をざっと説明しておこうかと思います。
既にProximityPromptを利用されている方は、この項目は読み飛ばしていただいて構いません。

使用方法


ProximityPrompt | Documentation - Roblox Creator Hubより引用
ProximityPromptは、BasePart、Attachment、PrimaryPartの設定されているModelのいずれかのオブジェクトの子に置いた時のみ動作します。
これらの子に置いた状態で、PlayerCharacterが一定距離以内に近づくと、親の座標を元にUIが表示され、特定のボタンやUIのタップなどの入力を受け付けるようになります。
UIが表示されるようになる距離は、MaxActivationDistanceで設定します。

右側に表示されているテキストは、ObjectTextActionTextで設定します。

受け付けるボタン入力は、KeyboardKeyCodeGamepadKeyCodeで設定します。
また、ClickablePromptをtrueにすると、UIをクリックやタップする事でも動作します。ただし、モバイル端末の場合はfalseでもタップで動作するようになります。

入力を一定時間押し続けにしたい場合は、HoldDurationでその時間を設定します。

入力の検出

ユーザーの入力を検出する方法は二種類あり、そのProximityPrompt自体のイベント発火を見る方法と、ProximityPromptServiceのイベント発火を見る方法があります。

ProximityPromptの場合、Triggeredで入力完了を検知し、TriggerEndedでTriggered後に入力が離された事を検知します。
HoldDurationが0以外に設定されている場合、PromptButtonHoldBeganで押し続けの開始を、PromptButtonHoldEndで終了を検出し、HoldDurationの時間分まで押し続けが完了した時には、PromptButtonHoldEndとTriggeredが両方発火します。
また、ProximityPromptが表示される時にPromptShown、消える時にPromptHiddenが発火するのですが、こちらはクライアント上でしか検出できない点に注意してください。

ProximityPromptServiceの場合もほぼ同じですが、TriggeredはPromptTriggered、TriggerEndedはPromptTriggerEndedという名前になっています。
そして大事なポイントとして、ProximityPromptServiceの場合は全てのPromptの発火を見る事ができます。
引数から発火したProximityPromptや発火させたPlayerが取得できるので、ProximityPromptにTagなどを設定しておき処理を判断するのが良いでしょう。
ProximityPromptServiceであれば、ProximityPromptごとにScriptが必要無いため、同じ処理を行う複数のProximityPromptのソースコードを一か所に纏めることができます。

3. UIのカスタマイズ

さて、ここからが本題です。
UIを変更するには、ProximityPrompt.StyleというプロパティをDefaultからCustomに変更した上で、表示したいUIを作成し、クライアント上でUIの表示、非表示を行う処理を書くことで行えます。
決まったフォーマットなどは無いので、自由なUIを表示することができます。


ポップな色にしてみたり…


ロックオンマーカーっぽくしてみたり…

公式のリファレンスにサンプルコードが載っており、それを改変して作ることもできます。
ただし、このサンプルコード、長い上にコメントが全然ありません!
ここで尻込みしてしまう方もいるかもしれませんが、このサンプルコードの大半は、UIのオブジェクトを生成してUI構築を行っている部分で、実際にカスタムUIを表示する際に行う処理の部分は単純です。
今回は、このサンプルコードを元に、ProximityPromptのカスタムUIの表示切り替えの仕組みの部分を実装してみようと思います。

4. UIのベースを作る

まずはUIのベースを構築していきます。
DefaultのUIに近いものを作っていく予定ですが、今回はその準備に留めます。

それではまず、WorkspaceにPartを置き、その子にBillboardGuiを、そのさらに子にFrameを追加してください。
名前は、BillboardGuiを「PromptUI」、Frameを「BaseFrame」としておきます。

追加できたら、PromptUI設定から行います。
まずは、AlwaysOnToptrueに設定してください。
こうすると、このUIは常に画面上の最前に表示されるようになります。
そして、Size.Y.Offset72にしてください。
XについてはScriptで動的に変更する予定なので、一旦200のままで大丈夫です。
最後に、Activefalseに設定しておいてください。
Activeはクリックやタップ等で操作できるUIかどうかを決めるプロパティなのですが、クリックできるかどうかはデバイスやProximityPromptの設定によって変動する部分なので、後でScriptから動的に設定する予定です。

これで、PromptUIの準備はOKです。

次に、BaseFrameを作っていきます。
左右の真ん中に来るよう、AnchorPointは(0.5, 0)に、PositionScaleで(0.5, 0)にしてください。
Colorは、(17, 17, 17)、BackgroundTransparency0.2です。
そして、SizeScaleで(0, 1)にしてください。
Scaleで0にしてしまうと表示されなくなってしまうのでは? と思うかもしれませんが、AutomaticSizeというプロパティを使用するための準備です。

AutomaticSize

AutomaticSizeとは、子オブジェクトやTextの長さなど、そのGuiObjectに含まれる要素に応じて自動的にSizeを調整する機能です。
AutomaticSizeにはNone, X, Y, XYの四つの選択肢があります。
名前のまんまなのでわかりやすいと思いますが、Noneは調整しない、XはXのみ、YはYのみ、XYは両方を調整するようになります。
今回はXに設定してください。これは、ActionTextやObjectTextの内容や有無によるX方向の長さの変化に対応するためです。

AutomaticSizeが有効になっている場合、Sizeプロパティは最低サイズとして扱われ、それより大きくなる場合のみAutomaticSizeによる調整が働くようになります。
今はSize.XをOffsetもScaleも0に設定しているので、常にAutomaticSizeによって調整された値になります。
ただし、現状はBaseFrame下に何もGuiObjectが無く、このままだとXが0になってしまい作業し辛いので、一旦Offsetで適当な値を設定しておきます。
Size.X.Offset72にすれば、正方形になるはずです。

最後に、BaseFrameの子にUICornerを追加してください。
UICornerは、名前の通りGuiObjectにコーナー(角丸)を付けるオブジェクトです。
設定はデフォルトのままで構いません。

最終的に、以下の画像のようになっていればOKです。

これでひとまずUIのベースができました。

5. UIの表示、非表示

一旦これをPromptのUIとして表示してみましょう。
ReplicatedStorageの子にFolderを一つ追加してください。
名前は「PromptUIFolder」にしておきます。
そして、PromptUI以下をPromptUIFolderに移動してください。

次に、PromptUI確認用に置いていたPartの子にProximityPromptを追加し、StyleをCustomに変更してください。

その後、StarterPlayerScriptsにLocalScriptを追加してください。
名前は、「PromptUIDispatcher」としておきます。

そして、以下のコードを追加してください。

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

	-- 破棄関数を定義.
	local function cleanup()
		-- 破棄.
		promptUI:Destroy()
	end

	-- 破棄関数を返す.
	return cleanup
end

-- ProximityPromptService.PromptShownに、カスタムUIの表示を接続します.
local function onLoad()
	-- ProximityPromptService.PromptShownに接続.
	ProximityPromptService.PromptShown:Connect(function(prompt, inputType)
		-- デフォルトだったら(カスタムじゃなかったら)処理しない.
		if prompt.Style == Enum.ProximityPromptStyle.Default then
			return
		end

		-- プロンプト用のScreenGuiを取得.
		local gui = getScreenGui()

		-- カスタムUI作成、戻り値で破棄関数が渡される.
		local cleanupFunction = createPrompt(prompt, inputType, gui)

		-- PromptHidden待ち.
		prompt.PromptHidden:Wait()

		-- 破棄関数を実行.
		cleanupFunction()
	end)
end

-- 実行.
onLoad()

この状態で実行すると、こんな感じになります。

ひとまず、表示と非表示を切り替えることができました!

ソースコードの構造はなるべく公式のサンプルコードと同じにしてあります。
基本的な流れは最後のonLoad関数を見てもらえればよいのですが、この関数自体はProximityPromptServiceのPromptShownにコールバック関数を接続しているのみです。
そしてそのコールバック関数は、StyleがDefaultかCustomかのチェックの後、ProximityPrompt用の配置場所を取得し、UIが複製されて表示され、ユーザーが離れるなどしてPromptHiddenが発火したらUIが破棄されて表示が消える、という単純な仕組みです。
表示と非表示の基本はこれだけです。

UIの複製はcreatePrompt関数の中で行っており、その際UIのBillboardGui.AdorneeにProximityPromptの親を設定しています。
BillboardGuiは通常、親のBasePartやAttachmentの位置を基準にして表示されるのですが、BillboardGui.Adorneeが設定されている場合、親ではなくAdorneeのオブジェクトの位置を基準にします。
GuiObjectはPlayerGuiの子孫に置かなければボタンに対してのタップやクリックの入力を取ることができないため、AdorneeにProximityPromptの親を設定した上で、BillboardGui自体はDefault時に置かれる場所と同じProximityPrompt用のScreenGui下に置くことで、特定オブジェクトを基準に表示しつつ入力できるようにしています。
動作上はPlayerGuiの子孫であればよいので、ScreenGui下に置く必要はないのですが、Defaultの配置に合わせています。

UIを破棄する際に直接Destroyせず、わざわざcreatePrompt内で破棄関数を定義して返しているのは、この後Destroy以外にもやるべき処理が増えるためです。

FadeIn, FadeOut

さて、このままぱっと出たり消えたりするだけだと寂しいので、FadeInとFadeOutを実装します。
公式のサンプルコードだとこういった動作も含め一つのScriptで全部構成していたのですが、今回はカスタムUI自体の動作などはModuleScriptとして分けて実装します。

それでは、PromptUIFolderにModuleScriptを追加してください。
名前は「PromptUIController」としておきます。

そして以下のソースコードを追加してください。

PromptUIController
--!strict
-- PromptUIの動作を設定するModule

local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local Folder = script.Parent

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


	-- イベントを接続.
	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

これは、渡されたカスタムUIに対して、動作を設定するメソッドを持つModuleです。
現状はBaseFrameのFadeIn, FadeOutだけですが、後々他のオブジェクトの動作の設定も追記していく予定なので、そのために配列にしている変数などもあります。

次に、PromptUIDispatcherのcreatePrompt関数に以下の修正を行ってください。

PromptUIDispatcher
 -- 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)
-	-- 破棄関数を定義.
-	local function cleanup()
-		-- 破棄.
-		promptUI:Destroy()
-	end
-
-	-- 破棄関数を返す.
-	return cleanup
end

破棄関数の定義はPromptUIControllerで行われて返ってくるので、それをそのまま返すようにしました。

この状態で実行するとこのようになります。

これで、FadeInとFadeOutができました!
距離での表示切り替えの際のFadeのほか、ボタン入力があった際もFadeOutしながら表示が消えるようになっています。

UIの動作はUI自体にLocalScriptを付ける形のほうがわかりやすく実装できるのですが、Scriptは破棄の際(特に初回)に大きくパフォーマンスに影響が出てしまうので、後で破棄する予定のUIの中には入れたくありません。
そこで、動作を設定する仕組みを外に用意しているわけです。
また、今回はカスタムUIが一種類なので省略しますが、複数種類のカスタムUIを作りたい場合、同様の仕組みのModuleをカスタムUIの種類毎に作成、対象のUIとセットにして置いておき、PromptUIDispatcherで呼び分けることで対応することができます。
その場合、よりきちんと作るなら、PromptUIControllerのBaseClassにあたるものを用意して、PromptUIDispatcher側ではModuleをその型で扱うとよいでしょう。

6. サンプルコード

今回作成した最終的なサンプルコードを掲載しておきます。

PromptUIDispatcher
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, inputType)
		-- デフォルトだったら(カスタムじゃなかったら)処理しない.
		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
PromptUIController
--!strict
-- PromptUIの動作を設定するModule

local TweenService = game:GetService("TweenService")

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

	-- 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


	-- イベントを接続.
	local connections = {}

	table.insert(connections, prompt.PromptButtonHoldBegan:Connect(function(playerWhoTriggered: Player)
		tweenPlayAll(tweensForButtonHoldBegin)
	end))
	table.insert(connections, prompt.PromptButtonHoldEnded:Connect(function(playerWhoTriggered: Player)
		tweenPlayAll(tweensForButtonHoldEnd)
	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()
		-- 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

7. まとめ

  • ProximityPrompt.StyleCustomに設定し、クライアント上でUIの表示、非表示を行う処理を書くことで、カスタムUIに変更できる
  • AutomaticSizeは、子オブジェクトやTextの長さなど、そのGuiObjectに含まれる要素に応じて自動的にSizeを調整する機能
  • AutomaticSizeが有効になっている場合、Sizeプロパティは最低サイズとして扱われ、それより大きくなる場合のみ自動調整される
  • カスタムUIの表示は、ProximityPromptService.PromptShownイベントの発火を見て行う
  • 逆に、表示の終了はProximityPromptService.PromptHiddenで行う
  • BillboardGui.Adorneeを設定すると、BillboardGuiの親に関わらず、Adorneeのオブジェクトの位置を基準にUIを表示する
  • Scriptは、特に初回の破棄の際に大きくパフォーマンスに影響が出てしまうため、UIの動作は複製されるUIの外のScriptで行う
  • ProximityPromptの各種イベントに接続することで、UIの動作を実装できる

今回は、ProximityPromptのカスタムUIの表示の仕組みについてご紹介しました。
しかし、このままだとただの四角なので、当然ProximityPromptのUIとしては使えませんよね。
というわけで次回は、タッチ入力への対応や、ボタンアイコンの表示を実装していきますので、そちらもぜひご覧ください!
最後までお読みいただき、ありがとうございました!

8. 参考

https://create.roblox.com/docs/reference/engine/classes/ProximityPrompt
https://create.roblox.com/docs/reference/engine/classes/ProximityPromptService
https://create.roblox.com/docs/reference/engine/enums/ProximityPromptStyle
https://create.roblox.com/docs/ui/size-modifiers#automatic-sizing

ランド・ホー Roblox開発チーム

Discussion