Basically I have a shooting mechanic in my side scroller game and I made it work with parts, having them have health.
I wanted these parts to be unanchored and I have tested them without shooting them, and they work fine as unanchored parts.
The issue is when I shoot one of the parts holding up a part on the top, when you fully destroy a part in my game i use part:Destroy()
to remove the parts, the part on the top floats midair and moves like its laggy?? see this video.
I don't really know what to try to fix this problem, which is why I'm posting it on here.
A few things to note:
This is on a new pc which runs stuff like mortal kombat 1 and elden ring etc so i don't think its performance.
My studio on this pc is quite buggy for some reason, especially with animations.
I tried loading the ACTUAL game up in the roblox player to no avail.
here is my code for shooting (it goes in 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)
Basically I have a shooting mechanic in my side scroller game and I made it work with parts, having them have health.
I wanted these parts to be unanchored and I have tested them without shooting them, and they work fine as unanchored parts.
The issue is when I shoot one of the parts holding up a part on the top, when you fully destroy a part in my game i use part:Destroy()
to remove the parts, the part on the top floats midair and moves like its laggy?? see this video.
I don't really know what to try to fix this problem, which is why I'm posting it on here.
A few things to note:
This is on a new pc which runs stuff like mortal kombat 1 and elden ring etc so i don't think its performance.
My studio on this pc is quite buggy for some reason, especially with animations.
I tried loading the ACTUAL game up in the roblox player to no avail.
here is my code for shooting (it goes in 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)
1 Answer
Reset to default 0Usually, weird physics bugs tend to be caused by network ownership issues.
The server is source of truth for all objects, their positions, properties, everything. However, you are deleting objects on the client and trying to run the resulting physics sim. The client is trying to move objects around but the server (which has no idea that these changes have happened because client changes are not replicated to the server) is insisting that these objects haven't moved.
So to fix this issue, you need to either :
- a) Create the objects you plan to destroy in LocalScripts, or
- b) Use RemoteEvents to destroy the objects on the server.
I'll explain Option B. So you'll to...
- Create a RemoteEvent in ReplicatedStorage, and name it something like
ShootEvent
- Create a Script in ServerScriptService
- Move all of your bullet logic into the Script
- Have your LocalScript fire the RemoteEvent instead
- Connect your Script to the RemoteEvent to spawn the bullet the client fires the event.
So in your 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)
Then in your server Script...
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)
Hope this helps!