🤖

[Roblox] ゲーム内でカットシーンを入れる方法

2024/12/03に公開

こんにちは! Asterです!
これはIwaken Lab. Advent Calendar 2024の3日目の記事です。

本日は、ゲームをよりワクワクしてもらうための工夫「カットシーン」をどうやって入れるのかを記事にしていこうかなと思います。

カットシーンの例

今回はシンプルにPartを触ったらキャラクターの前にカメラが前に来るカットを作成します。

Partに触ってカットシーンまでの流れ

カットシーンの前のPartに触る処理を書いていきます。今回は、分かりやすいように「ProximityPrompt」という触る処理などによく使われるものを使っていきます。
Partの子にProximityPromptをいれてください。

ProximityPromptを入れた状態でPlayをして、そのPartに近づくと以下のようにPartにGuiが表示されるようになります。

Defaultでは、「E Button」を押すとイベント発火されるようになります。
また、InteractというAction Textとなっています。
これらを変更するのは、Propertiesから変更できます。

それでは、E Buttonを押したら、カットシーンに流すためのスクリプトを書いていきましょう。
以下のようにScriptを追加してください。

まずは、ProximityPromptが動くかどうかの確認です。以下のようにコードを書いてください。
追加した状態で、Partに近づき、E Buttonを押すと「Action cut scene」と出力されると思います。
ActionCutSceneにカットシーンへのつなぎを書いていきます。

local ProximityPrompt = script.Parent

local function ActionCutScene()
	print("Action cut scene")
end

ProximityPrompt.Triggered:Connect(function(Player)
	ActionCutScene()
end)

では、早速 ActionCutSceneにカットシーンへのつなぎを書いていきましょう。
「カットシーンということだから、カメラを移動させればいいよね?」ということで、Workspace上のカメラを呼び出して、ActionCutSceneにカメラ移動のコードを書いても動きません。

基本 Robloxでは、個々のキャラクターを動かした際にキャラクターにカメラが追従するようになっています。このカメラはClient側で追従されており、Server側からでは動きません。
先ほどのProximityPromptの処理は、Server側で行っているため、動かないということです。
そのため、Server側ではなく、Client側で処理を実行する必要があります。
ここで使うのが、「Remote Event」です。
この「Remote Event」は、Server-Client間をつなげてくれるものとなります。
ついでに話すと「Bindable Event」というものもありこれは、Server-Server間、Client-Client間をつなげてくれるものがあります。

この「Remote Event」を使って、ServerからClient側に処理を渡していきましょう。]
まず、ReplicatedStorageの中にEventsフォルダーを用意して(見やすくするため)、その下にRemoteEventを追加してください。名前は、ActionCutSceneEvent(何か分かりやすくするため)にしましょう。

次に、先ほどのコードを以下のように書き換えてください。

local ProximityPrompt = script.Parent
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Events = ReplicatedStorage.Events
local ActionCutSceneEvent = Events.ActionCutSceneEvent

local function ActionCutScene(Player)
	print("Action cut scene")
	ActionCutSceneEvent:FireClient(Player)
end

ProximityPrompt.Triggered:Connect(function(Player)
	ActionCutScene(Player)
end)

追加した部分としては、ActionCutSceneEventを宣言する点と、そのActionCutSceneEventをProximityPromptのEventを発火させたPlayerにEventを発火させる部分を追加しました。

これで、Client側に処理を渡すことが出来ました。

次にClient側での処理を書いていきましょう。
StarterPlayer下のStarterPlayerScripts下に「local script」を追加しましょう。
名前は、ActionCutSceneとしています。

実際Client側に処理が流れているか以下のコードで確認しましょう。
追加した状態で、Partに近づき、E Buttonを押すと「Action cut scene (Client)」と出力されると思います。

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Events = ReplicatedStorage.Events
local ActionCutSceneEvent = Events.ActionCutSceneEvent

ActionCutSceneEvent.OnClientEvent:Connect(function()
	print("Action cut Scene (Client)")
end)

次に実際にカメラ移動をしていきましょう。
流れとしては、カメラの追従をやめて、カメラを思い通りに動かすようにしなければならないです。

カメラはDefautだと、CameraTypeが「Custom」となっているため、それがキャラクターに対して追従させています。そのため、このCameraTypeを「Fixed」に変更して上げるとカメラがその場で止まります。
この状態で、CameraのCFrameを変更することで、Characterの前にカメラが移動します。

では、実際にCameraを動かして行きましょう。
Cameraを動かすときに、ScriptからPositionを決めて、それで移動させるのもいいですが、それだと細かい調整がめんどくさいので、別Partを作って、そのPositionを使う形で行います。
このように別Partを白いPartの前に持ってきてください。(このとき黄色PartのAnchorをTrueにしておいてください。)

白いPartはTargetPart,黄色のPartは、CutCameraという名前に変更します。

実際にカメラを動かしていきます。
以下のコードに修正してください。このようにすることで、Partの前にカメラが移動するようになりました。

--Server Script
local ProximityPrompt = script.Parent
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Events = ReplicatedStorage.Events
local ActionCutSceneEvent = Events.ActionCutSceneEvent

local CutCamera = workspace.CutCamera
local TargetPart = workspace.TargetPart

local function ActionCutScene(Player)
	print("Action cut scene")
	ActionCutSceneEvent:FireClient(Player,CutCamera,TargetPart)
end

ProximityPrompt.Triggered:Connect(function(Player)
	ActionCutScene(Player)
end)
--Client Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Events = ReplicatedStorage.Events
local ActionCutSceneEvent = Events.ActionCutSceneEvent

local camera = workspace.CurrentCamera

local function MoveCamera(CutCamera,TargetPart)
	camera.CameraType = Enum.CameraType.Fixed
	camera.CFrame = CFrame.new(CutCamera.Position,TargetPart.Position)
end

ActionCutSceneEvent.OnClientEvent:Connect(function(CutCamera,TargetPart)
	MoveCamera(CutCamera,TargetPart)
	print("Action cut Scene (Client)")
end)

このままでは、カットシーンを入れた後にカメラがその場に残ってしまい、ゲームの続きを行うことが出来ません。そのため、CameraのTypeを戻す必要があります。また、CameraのCFrameもカットシーン前に戻しておくのがいいでしょう。
以下のコードにすると、5秒経ったら、カメラが戻るようになります。

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Events = ReplicatedStorage.Events
local ActionCutSceneEvent = Events.ActionCutSceneEvent

local camera = workspace.CurrentCamera

local function MoveCamera(CutCamera,TargetPart)
	local CurrentCameraCFrame = camera.CFrame
	camera.CameraType = Enum.CameraType.Fixed
	camera.CFrame = CFrame.new(CutCamera.Position,TargetPart.Position)
	
	wait(5)
	camera.CameraType = Enum.CameraType.Custom
	camera.CFrame = CurrentCameraCFrame
end

ActionCutSceneEvent.OnClientEvent:Connect(function(CutCamera,TargetPart)
	MoveCamera(CutCamera,TargetPart)
	print("Action cut Scene (Client)")
end)

これにより、ゲーム中にカットシーンを入れるための基盤が出来ました。
このMoveCameraに対して、TweenServiceを使って、カメラワークを追加するもよし、キャラクターのアニメーションを追加するもよしです。
自身にあったカットシーンを作っていただけたらと思います。

これにて、「ゲーム内でカットシーンを入れる方法」は終わりになります。

現在Asterが開発をしている「Arcadia : Rise of the Champion」にも是非遊びに来ていただけたらと思います!

https://www.roblox.com/ja/games/114994148606477/Beta-Arcadia-Rise-of-the-Champion

Xの方でもRobloxに関して発信していますので、フォローしていただけたらと思います!

https://x.com/Aster_NeRF

Iwaken Lab. Advent Calendar 2024の4日目は、ヘリンさん!お楽しみに!!

Discussion