これらすべての作業を一緒にもたらす時が来ました!ビームとパーティクルコンポーネントを作成したので、プリメイドのスクリプトを 3つ追加します。これらのスクリプトは、コンポーネントに何をすべきかを告知して、チュートリアルを管理します。たとえば、スクリプトは新しいプレイヤーにビームを作成し、ゴールと対話するたびに粒子を放出します。
ビームと粒子を保存する
スクリプトを追加する前に、ビームとパーティクルは、スクリプトが必要に応じてコピーを作成できる場所に移動する必要があります。
In ReplicatedStorage で、 PlayerTutorial という新しいフォルダを作成します。TutorialBeamをテストプレイヤーから新しいフォルダに移動し、新しいフォルダに移動します。
In ServerStorage で、 TutorialParticles という名前のフォルダを作成します。 バースト パーティクルを TestPlayer からそのフォルダに移動します。
ビームとパーティクルエミッタが移動したら、テストプレイヤーはもう必要ありません。 テストプレイヤーを削除する スクリプトが完了すると、実際のプレイヤーと一緒に動作するため。
イベントを作成
プレイヤーがゴールと対話するたびに、チュートリアルスクリプトはそのプレイヤーの進捗状況を更新し、粒子効果を放つことができるように知る必要があります。スクリプトを通知するには、 イベント を使用してシグナルを送信できます。
ReplicatedStorage > PlayerTutorial で、2つの リモートイベント オブジェクトを作成し、名前を 次のゴール と チュートリアル終了 に設定します。
スクリプトを追加する
以下の 3つのスクリプトは、以前に作成されたパーティクルエミッターとビームオブジェクトを検索し、チュートリアルシステムを管理します。
ReplicatedStorage > PlayerTutorial > で、新しい モジュールスクリプト を名前付きの TutorialManager を作成します。
デフォルトコードを置き換えるには、以下のコード全体をコピーして貼り付けます。
local TutorialManager = {}local ReplicatedStorage = game:GetService("ReplicatedStorage")local tutorialFolder = ReplicatedStorage:WaitForChild("PlayerTutorial")local TutorialEndEvent = tutorialFolder:WaitForChild("TutorialEnd")local NextGoalEvent = tutorialFolder:WaitForChild("NextGoal")-- ノートゴールパーツはテーブルで注文する必要があり、そうでなければゲーム内のゴール注文が異なる可能性がありますlocal goalParts = {workspace.TutorialGoals.GoalPart1,workspace.TutorialGoals.GoalPart2}local function checkTutorialEnd(player, goalParts)local currentIndex = player:WaitForChild("GoalProgress")return currentIndex.Value >= #goalPartsendlocal function finishTutorial(player)local playerBeam = player.Character.HumanoidRootPart:FindFirstChildOfClass("Beam")playerBeam:Destroy()print(player.Name .. " finished the tutorial")-- 以降のコードのプレースホルダー。例えば、他のタスクを実行するためにサーバーにメッセージを送信したい場合endfunction TutorialManager.interactGoal(player)NextGoalEvent:FireServer()endfunction TutorialManager.getTutorialGoals()return goalPartsendfunction TutorialManager.nextGoal(player, goalParts)if checkTutorialEnd(player, goalParts) thenfinishTutorial(player)else-- プレイヤーのゴールトラッカーを増加local currentGoalIndex = player:WaitForChild("GoalProgress")currentGoalIndex.Value += 1endend-- チュートリアルゴールを通じてプレイヤーの進捗状況をローカルで追跡するための int 値を作成するfunction TutorialManager.setupPlayerProgress(player)local currentGoalProgress = Instance.new("IntValue")currentGoalProgress.Name = "GoalProgress"currentGoalProgress.Value = 1currentGoalProgress.Parent = playerendreturn TutorialManagerこのスクリプトは、チュートリアルでプレイヤーの進捗を管理するコードを実行します。これには、ゴールと対話するためのコードの実行や、チュートリアルが終了したときに起こることなどが含まれます。
In サーバースクリプトサービス , create a new スクリプト named TutorialParticles .
以下のコードを貼り付けます。
local Players = game:GetService("Players")local ReplicatedStorage = game:GetService("ReplicatedStorage")local ServerStorage = game:GetService("ServerStorage")local tutorialFolder = ReplicatedStorage:WaitForChild("PlayerTutorial")local NextGoalEvent = tutorialFolder:WaitForChild("NextGoal")local EMIT_RATE = 50local function playParticleBurst(player)local character = player.Character or player.CharacterAdded:Wait()local humanoidRootPart = character:WaitForChild("HumanoidRootPart")local particleAttachment = humanoidRootPart:WaitForChild("ParticleAttachment")-- 添付ファイル上のパーティクルを通過し、パーティクルの種類に従って再生するfor _, particle in particleAttachment:GetChildren() doif particle:IsA("ParticleEmitter") thenparticle:Emit(EMIT_RATE)endendendlocal function setupPlayerParticles(player)player.CharacterAdded:Connect(function(character)local humanoidRootPart = character:WaitForChild("HumanoidRootPart")local playerParticleAttachment = Instance.new("Attachment")playerParticleAttachment.Name = "ParticleAttachment"playerParticleAttachment.Parent = humanoidRootPart-- フォルダ内のパーティクルをクローンし、1つ以上あってもプレイヤーに付属するfor _, emitter in ServerStorage.TutorialParticles:GetChildren() doemitter:Clone().Parent = playerParticleAttachmentendend)endPlayers.PlayerAdded:Connect(setupPlayerParticles)NextGoalEvent.OnServerEvent:Connect(playParticleBurst)このスクリプトは、プレイヤーがゴールと対話するたびにバーストパーティクルを再生します。また、インタラクション中に生成されるパーティクルの数を決定する変数 EMIT_RATE があります。
In StarterPlayer > StarterPlayerScripts, create a new ローカルスクリプト named チュートリアルスクリプト .
次に、以下のスクリプトを貼り付けます。このスクリプトは、プレイヤーを誘導するビームを作成し、管理します。
local Players = game:GetService("Players")local ReplicatedStorage = game:GetService("ReplicatedStorage")local tutorialFolder = ReplicatedStorage:WaitForChild("PlayerTutorial")local TutorialManager = require(tutorialFolder:WaitForChild("TutorialManager"))local TutorialEndEvent = tutorialFolder:WaitForChild("TutorialEnd")local player = Players.LocalPlayerlocal goalParts = TutorialManager.getTutorialGoals()local playerBeam = nillocal goalIndex = nillocal function getTargetAttachment()local currentTarget = goalParts[goalIndex.Value]local interactionPart = currentTarget:FindFirstChild("InteractionPart")local attachment = interactionPart and interactionPart:FindFirstChildOfClass("Attachment")if not attachment thenattachment = Instance.new("Attachment")attachment.Name = "BeamAttachment"attachment.Parent = currentTargetendreturn attachmentendlocal function updateBeamTarget()playerBeam = player.Character.HumanoidRootPart:FindFirstChildOfClass("Beam")local targetBeamAttachment = getTargetAttachment()if targetBeamAttachment thenplayerBeam.Attachment1 = targetBeamAttachmentelsewarn("Attachment not found in a goal. Check that goals have attachments or they're included under the InteractionPart")endendlocal function setupGoals()for _, part in goalParts dolocal interactionPart = part:FindFirstChild("InteractionPart")local proximityPrompt = interactionPart and interactionPart:FindFirstChild("ProximityPrompt")if proximityPrompt thenproximityPrompt.Triggered:Connect(function(player)proximityPrompt.Enabled = falseTutorialManager.nextGoal(player, goalParts)TutorialManager.interactGoal(player)end)elsewarn("Proximity prompt not included in goal. Add one to each goal part under the InteractionPart")endendendlocal function createBeamForCharacter(character)local humanoidRootPart = character:WaitForChild("HumanoidRootPart")local playerBeamAttachment = Instance.new("Attachment")local beamTemplate = tutorialFolder:WaitForChild("TutorialBeam")if not beamTemplate thenwarn("Tutorial Beam not found in ReplicatedStorage")endplayerBeamAttachment.Name = "BeamAttachment"playerBeamAttachment.Parent = humanoidRootPartlocal targetBeamAttachment = getTargetAttachment()playerBeam = beamTemplate:Clone()playerBeam.Attachment0 = playerBeamAttachmentplayerBeam.Attachment1 = targetBeamAttachmentplayerBeam.Enabled = trueplayerBeam.Parent = humanoidRootPartendlocal function setupPlayer()setupGoals()TutorialManager.setupPlayerProgress(player)goalIndex = player:WaitForChild("GoalProgress")player.CharacterAdded:Connect(createBeamForCharacter)if player.Character thencreateBeamForCharacter(player.Character)endendsetupPlayer()goalIndex.Changed:Connect(updateBeamTarget)プロジェクトを再生して、スクリプトをテストします。インタラクション機能を使用して、コードが機能するかどうかを確認します。
トラブルシュートのヒント
問題 : ゲームが開始すると、パーティクルが再生します。
サーバーストレージ > チュートリアルパーティクル > バーストに移動します。[オフにする] が有効になっていることを確認します。 問題 : コンパイラーでの「無限の生産」などの警告
スクリプトが特定の場所で特定のオブジェクトを検索しているため、パーツの名前が間違っている可能性があります。ゲーム内の各パーツの名前と場所がチュートリアルと一致しているかどうかを二度確認します。
スクリプトの利点と制限
このチュートリアルシステムをエクスペリエンスで使用している場合は、フォロー中のことを覚えておいてください: 利点
- チュートリアル終了などのイベントは、他のスクリプトをトリガーするのに使用できます。たとえば、このイベントが発動すると、プレイヤーに特別なアイテムを授与できます。
- チュートリアルパーティクルスクリプトは、一度に複数のパーティクルを再生できます。より複雑な効果のために、ServerStorage/TutorialParticles により多くのパーティクルを追加できます。 制限
- チュートリアル中のプレイヤーの進行状況は永続しません、つまりその進行状況を保存する方法をコード化する必要があります。ガイドについては、「データの保存」を参照してください。