添加脚本

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

是时候把这一切工作聚在一起了!现在你已经创建了光束和粒子组件,你将添加三个预制脚本。这些脚本管理教程,告诉组件何时做什么。例如,脚本会为新玩家创建光束并在他们与目标互动时发射粒子。

存储光束和粒子

在添加脚本之前,光束和粒子需要移动到脚本需要复制它们的地方。

  1. 复制存储 中,创建一个名为 PlayerTutorial 的新文件夹。将教程光束从测试玩家移出,并移至新文件夹。

  2. 服务器存储 中,创建一个名为 TutorialParticles 的文件夹。将 爆破 粒子从 TestPlayer 移出到该文件夹。

  3. 一旦光束和粒子发射器移动,你就不再需要测试玩家。 删除 测试玩家,因为脚本完成后将与真实玩家一起工作。

创建事件

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

  1. 在 ReplicatedStorage > PlayerTutorial 中,创建两个 远程事件 对象。命名为 下一个目标教程结束

添加脚本

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

  1. 在 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 >= #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. 服务器脚本服务 中,创建一个名为 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.Enabled = true
    playerBeam.Parent = humanoidRootPart
    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. 播放项目以测试脚本。使用互动功能从一个展位移动到另一个展位,看看代码是否运行。

排除问题的提示

问题 : 游戏开始时发生粒子。

  • 进入服务器存储 > 教程粒子 > 爆炸。检查启用关闭。 问题 : 编译器中的警告,例如无限产出。

  • 因为脚本正在寻找特定位置的特定对象,所以有可能是部分名称不正确。双方检查游戏中每个部分的名称和位置是否匹配教程。

脚本优缺点和限制

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

  • 例如,教程结束等事件可以用来触发其他脚本。例实例,当这个事件发生时,你可以奖励玩家一件特殊物品。
  • 教程参与者脚本可以一次播放多个粒子。您可以在 ServerStorage/TutorialParticles 中添加更多粒子以获得更复杂的效果。 限制
  • 教程中玩家的进度不是持久的,这意味着你必须编写一种方法来保存那些进度。如需指导,请参阅文章:保存数据。