添加脚本

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处

是时候把这些工作结合起来了!现在你已经创建了光束和粒子组件,你将添加三个预制脚本。这些脚本通过告诉组件何时做什么来管理教程。例如,当新玩家与目标交互时,它们会创建光束。

存储光束和粒子

在添加脚本之前,光束和粒子需要移动到可以根据需要制作复制的位置。

  1. ReplicatedStorage 中,创建一个名为 PlayerTutorial 的新文件夹。移动 TutorialBeam 出 TestPlayer,并且在新文件夹中。

  2. 在 ServerStorage 中,创建一个名为 TutorialParticles 的文件夹。将 Burst 粒子从 TestPlayer 移动到该文件夹。

  3. 当光束和粒子发射器移动时,您不再需要 TestPlayer。 删除 TestPlayer,因为脚本将在完成时与实际玩家工作。

创建事件

每次玩家与目标互动时,教程脚本需要知道, чтобы它可以更新该玩家的进度并发出粒子效果。要向脚本发送信息,信号可以使用 事件

  1. 在 ReplicatedStorage > PlayerTutorial 中,创建两个 RemoteEvent 对象。命名它们 下一个目标教程结束

添加脚本

以下三个脚本将寻找早先创建的粒子发射器和光束对象,并管理教程系统。

  1. 在 ReplicatedStorage > PlayerTutorial > 创建一个名为 TutorialManager 的新 ModuleScript

    将默认代码替换为复制并粘贴以下全部代码。


    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 >= #goalParts
    end
    local function finishTutorial(player)
    local playerBeam = player.Character.HumanoidRootPart:FindFirstChildOfClass("Beam")
    playerBeam:Destroy()
    print(player.Name .. " finished the tutorial")
    -- 用于存储更多验证码。例如,如果您想向服务器发送消息以执行其他任务
    end
    function TutorialManager.interactGoal(player)
    NextGoalEvent:FireServer()
    end
    function TutorialManager.getTutorialGoals()
    return goalParts
    end
    function TutorialManager.nextGoal(player, goalParts)
    if checkTutorialEnd(player, goalParts) then
    finishTutorial(player)
    else
    -- 增加玩家的目标追踪器
    local currentGoalIndex = player:WaitForChild("GoalProgress")
    currentGoalIndex.Value += 1
    end
    end
    -- 创建一个 int 值来本地跟踪玩家的进度通过教程目标
    function TutorialManager.setupPlayerProgress(player)
    local currentGoalProgress = Instance.new("IntValue")
    currentGoalProgress.Name = "GoalProgress"
    currentGoalProgress.Value = 1
    currentGoalProgress.Parent = player
    end
    return TutorialManager

    此脚本在教程中管理玩家的进度。这包括与目标交互的代码运行,或教程结束后发生的事件。

  2. ServerScriptService 中,创建一个名为 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 = 50
    local 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() do
    if particle:IsA("ParticleEmitter") then
    particle:Emit(EMIT_RATE)
    end
    end
    end
    local function setupPlayerParticles(player)
    player.CharacterAdded:Connect(function(character)
    local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
    local playerParticleAttachment = Instance.new("Attachment")
    playerParticleAttachment.Name = "ParticleAttachment"
    playerParticleAttachment.Parent = humanoidRootPart
    -- 在文件夹中克隆粒子,即使有多个粒子并且添加到玩家
    for _, emitter in ServerStorage.TutorialParticles:GetChildren() do
    emitter:Clone().Parent = playerParticleAttachment
    end
    end)
    end
    Players.PlayerAdded:Connect(setupPlayerParticles)
    NextGoalEvent.OnServerEvent:Connect(playParticleBurst)

    这个脚本在玩家与目标互动时播放爆炸粒子。还有一个名为 EMIT_RATE 的变量,它确定在交互中产生多少粒子。

  3. 在 StarterPlayer > StarterPlayerScripts 中,创建一个名为 TutorialScript 的新 本地脚本

    然后,复制下面的脚本。 此脚本创建并管理使用来引导玩家的光束。


    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.LocalPlayer
    local goalParts = TutorialManager.getTutorialGoals()
    local playerBeam = nil
    local goalIndex = nil
    local function getTargetAttachment()
    local currentTarget = goalParts[goalIndex.Value]
    local interactionPart = currentTarget:FindFirstChild("InteractionPart")
    local attachment = interactionPart and interactionPart:FindFirstChildOfClass("Attachment")
    if not attachment then
    attachment = Instance.new("Attachment")
    attachment.Name = "BeamAttachment"
    attachment.Parent = currentTarget
    end
    return attachment
    end
    local function updateBeamTarget()
    playerBeam = player.Character.HumanoidRootPart:FindFirstChildOfClass("Beam")
    local targetBeamAttachment = getTargetAttachment()
    if targetBeamAttachment then
    playerBeam.Attachment1 = targetBeamAttachment
    else
    warn("Attachment not found in a goal. Check that goals have attachments or they're included under the InteractionPart")
    end
    end
    local function setupGoals()
    for _, part in goalParts do
    local interactionPart = part:FindFirstChild("InteractionPart")
    local proximityPrompt = interactionPart and interactionPart:FindFirstChild("ProximityPrompt")
    if proximityPrompt then
    proximityPrompt.Triggered:Connect(function(player)
    proximityPrompt.Enabled = false
    TutorialManager.nextGoal(player, goalParts)
    TutorialManager.interactGoal(player)
    end)
    else
    warn("Proximity prompt not included in goal. Add one to each goal part under the InteractionPart")
    end
    end
    end
    local function createBeamForCharacter(character)
    local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
    local playerBeamAttachment = Instance.new("Attachment")
    local beamTemplate = tutorialFolder:WaitForChild("TutorialBeam")
    if not beamTemplate then
    warn("Tutorial Beam not found in ReplicatedStorage")
    end
    playerBeamAttachment.Name = "BeamAttachment"
    playerBeamAttachment.Parent = humanoidRootPart
    local targetBeamAttachment = getTargetAttachment()
    playerBeam = beamTemplate:Clone()
    playerBeam.Attachment0 = playerBeamAttachment
    playerBeam.Attachment1 = targetBeamAttachment
    playerBeam.Parent = humanoidRootPart
    playerBeam.Enabled = true
    end
    local function setupPlayer()
    setupGoals()
    TutorialManager.setupPlayerProgress(player)
    goalIndex = player:WaitForChild("GoalProgress")
    player.CharacterAdded:Connect(createBeamForCharacter)
    if player.Character then
    createBeamForCharacter(player.Character)
    end
    end
    setupPlayer()
    goalIndex.Changed:Connect(updateBeamTarget)
  4. 播放项目以测试脚本。从一个摊位移动到另一个摊位,使用交互功能来确定代码是否运行。

排查提示

发生问题 : 粒子会在游戏开始时播放。

  • 进入服务器存储 > 教程粒子 > 爆裂。检查启用以关闭。 发出 : 在编译器上发出警告,例如“无限产出”。

  • 因为脚本在某些位置寻找特定对象,因此有可能部分的名称会错误。请确认每个部分在游戏中的名称和位置与教程中的对象匹配。

脚本优势和限制

如果您在体验中使用此教程系统,请记住以下几点: 好处

  • TutorialEnd 等级的事件可以用来触发其他脚本。 例实例,你可以在此事件发生时奖励玩家一件特殊物品。
  • TutorialParticles 脚本可以同时播放多个粒子。 您可以在服务器存储/TutorialParticles 中添加更多粒子以获得更复杂的效果。 限制
  • 玩家在教程中的进度不是持久的,这意味着您需要编写一些方法来保存该进度。 有关指导,请参阅文章:保存数据。