当我使用 :Destroy() 时,未锚定部分的物理结构会被破坏

问题描述 投票:0回答:1

基本上,我的横向卷轴游戏中有一个射击机制,我让它与零件一起工作,让它们有生命值。

我希望这些部件是非锚定的,并且我已经在没有射击它们的情况下测试了它们,并且它们作为非锚定部件工作得很好。

问题是当我射击支撑顶部零件的一个零件时,当你完全摧毁我游戏中的一个零件时,我使用

part:Destroy()
移除零件,顶部的零件漂浮在半空中并像其滞后一样移动??看这个视频

我真的不知道如何尝试解决这个问题,这就是我将其发布在这里的原因。

有几点需要注意:

  1. 这是在一台新电脑上运行的东西,如真人快打1和埃尔登戒指等,所以我不认为它的性能。

  2. 我在这台电脑上的工作室由于某种原因有很多问题,尤其是动画。

  3. 我尝试在 roblox 播放器中加载实际游戏,但没有成功。

    这是我的射击代码(它位于 starterplayer.startercharacterscripts 中):

    local player = game.Players.LocalPlayer
    local mouse = player:GetMouse()
    local gui = player.PlayerGui:WaitForChild("GameGui") 
    local targetImage = gui:WaitForChild("Target") 
    local bulletSpeed = 70 
    local damageAmount = 25 
    local shootCooldown = 1 
    local lastShootTime = 0 
    
    
    targetImage.Visible = false
    
    
    local function unanchorBreakableParts()
     local breakableFolder = workspace:WaitForChild("Breakable")
     for _, part in pairs(breakableFolder:GetChildren()) do
         if part:IsA("Part") then
             part.Anchored = false 
         end
     end
    end
    
    
    local function fireBullet(startPosition, targetPosition)
     local bullet = Instance.new("Part")
     bullet.Size = Vector3.new(1, 0.5, 0.5) 
     bullet.Material = Enum.Material.Neon
     bullet.BrickColor = BrickColor.new("Bright yellow") 
     bullet.Position = startPosition
     bullet.Anchored = false
     bullet.CanCollide = false
     bullet.Parent = workspace
    
    
     local direction = (targetPosition - startPosition).unit
    
    
     bullet.CFrame = CFrame.lookAt(startPosition, startPosition + direction)
    
    
     local bodyVelocity = Instance.new("BodyVelocity")
     bodyVelocity.Velocity = direction * bulletSpeed
     bodyVelocity.MaxForce = Vector3.new(math.huge, math.huge, math.huge) 
     bodyVelocity.Parent = bullet
    
    
     local connection
     connection = bullet.Touched:Connect(function(hit)
         if hit and hit.Parent and hit.Parent:FindFirstChild("Humanoid") then
             local humanoid = hit.Parent:FindFirstChild("Humanoid")
             local character = player.Character
    
    
             if humanoid.Parent ~= character then
                 humanoid:TakeDamage(damageAmount)
                 bullet:Destroy() 
                 connection:Disconnect()
             end
         elseif hit and hit.Parent and hit:FindFirstChild("Health") then
    
             local health = hit:FindFirstChild("Health")
             if health then
                 health.Value = health.Value - damageAmount 
    
    
                 if health.Value <= 0 then
                     hit:Destroy() 
                 end
             end
    
             bullet:Destroy() 
             connection:Disconnect()
         else
    
             bullet:Destroy()
             connection:Disconnect()
         end
     end)
    
    
     game:GetService("Debris"):AddItem(bullet, 5)
    end
    
    
    mouse.Button1Down:Connect(function()
    
     unanchorBreakableParts()
    
    
     local currentTime = tick()
     if currentTime - lastShootTime < shootCooldown then
         return 
     end
    
    
     local mousePosition = Vector2.new(mouse.X, mouse.Y)
     targetImage.Position = UDim2.new(0, mousePosition.X - (targetImage.Size.X.Offset / 2), 0, mousePosition.Y - (targetImage.Size.Y.Offset / 2))
     targetImage.Visible = true
    
    
     task.delay(0.3, function()
         targetImage.Visible = false
     end)
    
    
     local ray = workspace.CurrentCamera:ScreenPointToRay(mouse.X, mouse.Y)
     local rayTarget = ray.Origin + ray.Direction * 500
    
    
     local raycastParams = RaycastParams.new()
     raycastParams.FilterDescendantsInstances = {player.Character} 
     raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
    
     local raycastResult = workspace:Raycast(ray.Origin, ray.Direction * 500, raycastParams)
     if raycastResult then
         rayTarget = raycastResult.Position 
     end
    
    
     local character = player.Character or player.CharacterAdded:Wait()
     local rightArm = character:FindFirstChild("ShootPart")
     local startPosition = rightArm.Position
    
    
     local humanoid = character:FindFirstChild("Humanoid")
     local shootAnim = character:FindFirstChild("Animations"):FindFirstChild("Shoot")
    
     if humanoid and shootAnim and shootAnim:IsA("Animation") then
    
         local loadedAnim = humanoid:LoadAnimation(shootAnim)
    
    
         loadedAnim.Priority = Enum.AnimationPriority.Action3
    
    
         loadedAnim:Play()
     else
         warn("Humanoid or Shoot animation not found!")
     end
    
    
     fireBullet(startPosition, rayTarget)
    
    
     lastShootTime = currentTime
    end)
    
    
lua roblox
1个回答
0
投票

通常,奇怪的物理错误往往是由网络所有权问题引起的。

服务器是所有对象、它们的位置、属性等一切的真实来源。但是,您正在删除客户端上的对象并尝试运行生成的物理模拟。客户端试图移动对象,但服务器(服务器不知道这些更改已经发生,因为客户端更改没有复制到服务器)坚持认为这些对象没有移动。

因此要解决此问题,您需要:

  • a) 创建您计划在 LocalScripts 中销毁的对象,或者
  • b) 使用 RemoteEvents 销毁服务器上的对象。

我将解释选项 B。所以你会...

  1. 在 ReplicatedStorage 中创建一个 RemoteEvent,并将其命名为
    ShootEvent
  2. 在ServerScriptService中创建脚本
  3. 将所有项目符号逻辑移至脚本中
  4. 让 LocalScript 触发 RemoteEvent
  5. 将您的脚本连接到 RemoteEvent 以生成客户端触发事件的子弹。

所以在你的 LocalScript 中...

local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local gui = player.PlayerGui:WaitForChild("GameGui") 
local shootEvent = game.ReplicatedStorage.ShootEvent
local targetImage = gui:WaitForChild("Target") 
local shootCooldown = 1 
local lastShootTime = 0


targetImage.Visible = false

-- listen for mouse clicks
mouse.Button1Down:Connect(function()
    -- escape if we're on cooldown
    local currentTime = tick()
    if currentTime - lastShootTime < shootCooldown then
        return 
    end

    -- update the ui
    targetImage.Visible = true
    task.delay(0.3, function()
        targetImage.Visible = false
    end)

    -- figure out what we're aiming at
    local mousePosition = Vector2.new(mouse.X, mouse.Y)
    targetImage.Position = UDim2.new(0, mousePosition.X - (targetImage.Size.X.Offset / 2), 0, mousePosition.Y - (targetImage.Size.Y.Offset / 2))
    

    local ray = workspace.CurrentCamera:ScreenPointToRay(mouse.X, mouse.Y)
    local rayTarget = ray.Origin + ray.Direction * 500
    local raycastParams = RaycastParams.new()
    raycastParams.FilterDescendantsInstances = {player.Character} 
    raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
    local raycastResult = workspace:Raycast(ray.Origin, ray.Direction * 500, raycastParams)
    if raycastResult then
        rayTarget = raycastResult.Position 
    end

    -- play an animation
    local humanoid = character:FindFirstChild("Humanoid")
    local shootAnim = character:FindFirstChild("Animations"):FindFirstChild("Shoot")

    if humanoid and shootAnim and shootAnim:IsA("Animation") then
        local loadedAnim = humanoid:LoadAnimation(shootAnim)
        loadedAnim.Priority = Enum.AnimationPriority.Action3
        loadedAnim:Play()
    else
        warn("Humanoid or Shoot animation not found!")
    end

    -- tell the server to fire the bullet
    shootEvent:FireServer(rayTarget)

    -- reset the debounce/cooldown
    lastShootTime = currentTime
end)

然后在你的服务器脚本中...

local bulletSpeed = 70 
local damageAmount = 25 

local function unanchorBreakableParts()
    local breakableFolder = workspace:WaitForChild("Breakable")
    for _, part in pairs(breakableFolder:GetChildren()) do
        if part:IsA("Part") then
           part.Anchored = false 
        end
    end
end


local function fireBullet(startPosition, targetPosition)
    -- create the bullet
    local bullet = Instance.new("Part")
    bullet.Size = Vector3.new(1, 0.5, 0.5) 
    bullet.Material = Enum.Material.Neon
    bullet.BrickColor = BrickColor.new("Bright yellow") 
    bullet.Position = startPosition
    bullet.Anchored = false
    bullet.CanCollide = false
    bullet.Parent = workspace

    local direction = (targetPosition - startPosition).unit
    bullet.CFrame = CFrame.lookAt(startPosition, startPosition + direction)

    -- make the bullet move
    local bodyVelocity = Instance.new("BodyVelocity")
    bodyVelocity.Velocity = direction * bulletSpeed
    bodyVelocity.MaxForce = Vector3.new(math.huge, math.huge, math.huge) 
    bodyVelocity.Parent = bullet

    -- listen for when the bullet hits things
    local connection
    connection = bullet.Touched:Connect(function(hit)
        if hit and hit.Parent and hit.Parent:FindFirstChild("Humanoid") then
            local humanoid = hit.Parent:FindFirstChild("Humanoid")
            local character = player.Character
            if humanoid.Parent ~= character then
                humanoid:TakeDamage(damageAmount)
            end

        elseif hit and hit.Parent and hit:FindFirstChild("Health") then
            local health = hit:FindFirstChild("Health")
            if health then
                health.Value = health.Value - damageAmount 
                if health.Value <= 0 then
                    hit:Destroy() 
                end
            end
        end

        bullet:Destroy()
        connection:Disconnect()
    end)

    -- mark the bullet for cleanup
    game:GetService("Debris"):AddItem(bullet, 5)
end


 
-- listen for when the client says they've fired a bullet
game.ReplicatedStorage.ShootEvent.OnServerEvent:Connect(function(player : Player, rayTarget : Vector3)
    local character = player.Character or player.CharacterAdded:Wait()
    local rightArm = character:FindFirstChild("ShootPart")
    local startPosition = rightArm.Position

    fireBullet(startPosition, rayTarget)
end)

希望这有帮助!

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.