You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Roblox开发问题:Object触碰Orb后调用destroy()无法销毁

问题:Roblox中Object与Orb碰撞后无法销毁

我正在开发一款Roblox游戏,核心需求如下:

  • 点击「AttractButton」时,Object会向玩家位置移动并停在距离玩家4 studs的位置;
  • 点击「RepelButton」时,Object会被推开一段距离。

上述移动功能运行正常,但当Object与名为Orb的部件碰撞后,调用destroy()函数始终无法让Object消失,多次调试无果,寻求解决帮助。


StarterGui中的脚本

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local CollectionService = game:GetService("CollectionService")
local RunService = game:GetService("RunService")

local player = Players.LocalPlayer
local mouse = player:GetMouse()

local controlGui = player:WaitForChild("PlayerGui"):WaitForChild("ControlGui")
local attractButton = controlGui:WaitForChild("AttractButton")
local repelButton = controlGui:WaitForChild("RepelButton")

local attractMode = false
local repelMode = false

local cooldownTime = 2
local lastInteractionTime = {}
local velocity = 10 -- studs per second

-- Function to handle the attract button click
local function onAttractButtonClick()
attractMode = true
    repelMode = false
    print("Attract mode enabled")

-- Visual feedback for button click
    attractButton.BackgroundColor3 = Color3.fromRGB(200, 200, 200) -- Change to a different color
    wait(0.1) -- Wait for a short delay
    attractButton.BackgroundColor3 = Color3.fromRGB(255, 255, 255) -- Revert to original color
end

-- Function to handle the repel button click
local function onRepelButtonClick()
    attractMode = false
    repelMode = true
    print("Repel mode enabled")

    -- Visual feedback for button click
    repelButton.BackgroundColor3 = Color3.fromRGB(200, 200, 200) -- Change to a different color
    wait(0.1) -- Wait for a short delay
    repelButton.BackgroundColor3 = Color3.fromRGB(255, 255, 255) -- Revert to original color
end

attractButton.MouseButton1Click:Connect(onAttractButtonClick)
repelButton.MouseButton1Click:Connect(onRepelButtonClick)

-- Function to perform raycast check
local function raycastCheck(startPos, endPos)
    local direction = (endPos - startPos).Unit * (endPos - startPos).Magnitude
    local raycastParams = RaycastParams.new()
    raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
    raycastParams.FilterDescendantsInstances = {player.Character}

    local result = workspace:Raycast(startPos, direction, raycastParams)
    return result
end

-- Function to move object to final position with collision checking
local function moveObject(target, finalPosition)
    local connection
    local function onHeartbeat()
        local currentPosition = target.Position
        local direction = (finalPosition - currentPosition).Unit
        local deltaTime = RunService.Heartbeat:Wait()
        local newPosition = currentPosition + direction * velocity * deltaTime
        local result = raycastCheck(currentPosition, newPosition)

        if result then
            target.Position = result.Position - direction * 1 -- Stop just before the obstacle
            connection:Disconnect()
            return
        elseif (currentPosition - finalPosition).Magnitude < 1 then
            target.Position = finalPosition
            connection:Disconnect()
            return
        end

        target.Position = newPosition
    end

    connection = RunService.Heartbeat:Connect(onHeartbeat)
end

-- Function to handle mouse button click
mouse.Button1Down:Connect(function()
    local target = mouse.Target
    if target and target:IsA("BasePart") and CollectionService:HasTag(target, "attractable") then
        local currentTime = tick()
        local lastTime = lastInteractionTime[target]

        if lastTime and (currentTime - lastTime) < cooldownTime then
            print("Cooldown active. Please wait.")
            return
        end

        lastInteractionTime[target] = currentTime

        local character = player.Character or player.CharacterAdded:Wait()
        local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
        local targetPosition = humanoidRootPart.Position

        local offset, finalPosition
        if attractMode then
            offset = (target.Position - targetPosition).Unit * 4
            finalPosition = targetPosition + offset
        elseif repelMode then
            offset = (target.Position - targetPosition).Unit * 20
            finalPosition = target.Position + offset
        end

        finalPosition = Vector3.new(finalPosition.X, target.Position.Y, finalPosition.Z) -- Keep Y the same

        moveObject(target, finalPosition)
        print(attractMode and "Object attracted" or "Object repelled")
    end
end)

Object部件中的脚本

local object = script.Parent -- Assuming the script is directly inside the Object part
local orb = game.Workspace:WaitForChild("Orb") -- Assuming the orb is named "Orb" and is a separate part in the Workspace

local function onHit(otherPart)
    if otherPart == orb then
        object:Destroy()
    end
end

object.Touched:Connect(onHit)

排查与修复方案

1. 确保Touched事件正常触发

  • 检查Orb和Object的CanCollide属性是否为true,Touched事件依赖碰撞体开启碰撞才能触发;
  • 替换otherPart == orb为otherPart.Name == "Orb",避免因碰撞到Orb的子部件导致匹配失败;
  • 增加调试输出确认事件触发状态:
    local function onHit(otherPart)
        print("碰撞到的部件:", otherPart.Name)
        if otherPart.Name == "Orb" then
            print("执行销毁操作")
            object:Destroy()
        end
    end
    

2. 解决客户端脚本权限问题

如果Object中的脚本是本地脚本,仅在客户端销毁对象会导致服务器端Object依然存在,其他玩家无法看到销毁效果。需改为服务器脚本,或通过RemoteEvent通知服务器处理:

  • 将Object内的脚本改为ServerScript;
  • 若需客户端触发,创建RemoteEvent实现跨端通信:
    1. 在ReplicatedStorage中创建RemoteEvent,命名为DestroyObject;
    2. Object的本地脚本修改为:
      local object = script.Parent
      local orb = game.Workspace:WaitForChild("Orb")
      local ReplicatedStorage = game:GetService("ReplicatedStorage")
      local destroyEvent = ReplicatedStorage:WaitForChild("DestroyObject")
      
      local function onHit(otherPart)
          if otherPart.Name == "Orb" then
              destroyEvent:FireServer(object)
          end
      end
      
      object.Touched:Connect(onHit)
      
    3. 在ServerScriptService中添加服务器处理脚本:
      local ReplicatedStorage = game:GetService("ReplicatedStorage")
      local destroyEvent = ReplicatedStorage:WaitForChild("DestroyObject")
      
      destroyEvent.OnServerEvent:Connect(function(player, object)
          if object and object:IsDescendantOf(game.Workspace) then
              object:Destroy()
          end
      end)
      

3. 断开移动脚本的Heartbeat连接

Object销毁时,moveObject函数中的Heartbeat连接可能仍在运行,尝试修改已销毁对象的Position导致报错。需在Object销毁时自动断开连接:

local function moveObject(target, finalPosition)
    local connection = RunService.Heartbeat:Connect(function()
        local currentPosition = target.Position
        local direction = (finalPosition - currentPosition).Unit
        local deltaTime = RunService.Heartbeat:Wait()
        local newPosition = currentPosition + direction * velocity * deltaTime
        local result = raycastCheck(currentPosition, newPosition)

        if result then
            target.Position = result.Position - direction * 1
            connection:Disconnect()
            return
        elseif (currentPosition - finalPosition).Magnitude < 1 then
            target.Position = finalPosition
            connection:Disconnect()
            return
        end

        target.Position = newPosition
    end)
    -- 监听对象销毁事件,自动断开连接
    target.AncestryChanged:Connect(function(_, parent)
        if not parent then
            connection:Disconnect()
        end
    end)
end

内容的提问来源于stack exchange,提问作者vinny9592

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 19:13:09