Projectile behavior differs in Play mode and Studio

  1. Hey everyone, I recently ran into an issue that seems to be caused by a roblox update that has been causing my projectiles to randomly strike below their target when playing the game on a live server. This behavior does not occur within roblox studio.

2… This is an issue for my game due to the fact that missing an attack means the difference between success and failure in my game.

Here is a video on how the projectiles perform within studio (All Projectiles hit the top of the pillar correctly)
Projectile Correct

Here is a video on how they perform on a live server (I’m aiming at the top of the pillar like in the first GIF, but occassionally the projectiles randomly veer downwards)
Incorrect2

  1. I’ve tried browsing the forums for similar topics but every post I’ve ran across only has this problem in studio and are just offset issues.

Below is a snippet of my code that handles spawning the projectile and ensuring it hits its target. Any help would be appreciated, thanks!

["Orb"] = function()
		if not Spell1 then return end
		Spell1 = false

		Handle:WaitForChild("LightningBolt"):Play()

		local Anim = MyHumanoid:LoadAnimation(Tool:FindFirstChild("Cast"))
		if Anim then Anim:Play() end

		local Icon = SpellGui:WaitForChild("SpellGuiFrame"):WaitForChild(ChosenSpellTag)
		local Overlay = Icon:WaitForChild("Overlay")
		local LastText = Overlay.Text
		Icon.Image = BaseUrl.."7560818616"
		spawn(function()
			local MousePos = MouseLoc:InvokeClient(MyPlayer)

			local Orb = Instance.new("Part")
			Orb.TopSurface = Enum.SurfaceType.Smooth
			Orb.BottomSurface = Enum.SurfaceType.Smooth
			Orb.Color = Color3.fromRGB(110, 153, 202)
			Orb.Material = Enum.Material.Neon
			Orb.Transparency = 0
			Orb.Shape = Enum.PartType.Ball
			Orb.Size = Vector3.new(1,1,1)
			Orb.Anchored = false
			Orb.CanCollide = false
			Orb.Velocity = (MousePos-Handle.CFrame.p).unit*100
			Orb.CFrame = CFrame.new(Handle.CFrame.Position, Handle.CFrame.Position + Orb.Velocity)

			local parti = script.Particles:Clone()
			parti.Enabled = true
			parti.Parent = Orb

			local Light = Instance.new("PointLight")
			Light.Color = Color3.fromRGB(0, 85, 255)
			Light.Range = 2
			Light.Brightness = 10
			Light.Parent = Orb
			Light.Enabled = true

			Aura7.Parent = Orb

			local Force = Instance.new("BodyForce")
			Force.Force = Vector3.new(0,Orb:GetMass()*workspace.Gravity,0)
			Force.Parent = Orb

			Orb.Parent = workspace

			Orb:SetNetworkOwner(MyPlayer) -- no lagging visuals

			Services.Debris:AddItem(Orb,4)

			Orb.Touched:Connect(function(hit) Blow(Orb, hit, Properties.OrbDamage) end)
		end)
1 Like

I would use a linear velocity instead of a body force that counters gravity and a velocity, especially since can collide is false anyways, so it should follow the behavior of a linear velocity.

The main difference between studio and live servers (besides bugs) is the lag. There seems to be a lot of back and force to launch a spell (spell input from the client to the server > server asks the client what the mouse position is > client sends back the mouse position > server creates the ball and that replicates back to the client, which is like 5 transmissions).

I don’t see where extra lag would cause the issue you’re seeing though. It’s possible that there is some sort of physics problem when the ball gets its ownership changed, but I’ve never seen this specific problem.

Perhaps try using a LinearVelocity and seeing if that fixes it. (Maybe gravity accelerates the velocity downwards for just a second because of some replication of ownership problem, so constantly controlling the velocity to the desired value (which a linear velocity would do) might fix it.)

At the very least a linear velocity would make the issue better, even if it can’t fully solve it.

1 Like

Did some additional testing while on higher than average ping (90+) , and now I’m absolutely convinced its some sort of bug. If i open up the dev console while playing in a live server and then aim and fire a projectile it will never go off course.
Untitled video - Made with Clipchamp

Did some more testing and one of my other projectile launching spells is functioning just fine as well and is coded almost identically.

Untitled video - Made with Clipchamp (1)

The Code for the fire projectiles

["Orb"] = function()
		if not Spell1 then return end
		Spell1 = false

		Handle:WaitForChild("Fireball"):Play()

		local Anim = MyHumanoid:LoadAnimation(Tool:FindFirstChild("Cast"))
		if Anim then Anim:Play() end

		local Icon = SpellGui:WaitForChild("SpellGuiFrame"):WaitForChild(ChosenSpellTag)
		local Overlay = Icon:WaitForChild("Overlay")
		local LastText = Overlay.Text
		Icon.Image = BaseUrl.."7524344295"
		spawn(function()
			local MousePos = MouseLoc:InvokeClient(MyPlayer)

			local Orb = Instance.new("Part")
			Orb.TopSurface = Enum.SurfaceType.Smooth
			Orb.BottomSurface = Enum.SurfaceType.Smooth
			Orb.Color = Color3.fromRGB(253, 128, 47)
			Orb.Material = Enum.Material.Neon
			Orb.Transparency = 0
			Orb.Shape = Enum.PartType.Ball
			Orb.Size = Vector3.new(1,1,1)
			Orb.Anchored = false
			Orb.CanCollide = false
			Orb.Velocity = (MousePos-Handle.CFrame.p).unit*120
			Orb.CFrame = CFrame.new(Handle.CFrame.Position, Handle.CFrame.Position + Orb.Velocity)

			local OrbMesh = Instance.new("SpecialMesh")
			OrbMesh.MeshId = "http://www.roblox.com/asset/?id=1290033"
			OrbMesh.TextureId = "http://www.roblox.com/asset/?id=3197743"
			OrbMesh.Scale = Vector3.new(.5,.5,.5)
			OrbMesh.Offset = Vector3.new(0,0,0)
			OrbMesh.Parent = Orb

			local Light = Instance.new("PointLight")
			Light.Color = Orb.Color
			Light.Range = 10
			Light.Brightness = 2
			Light.Parent = Orb
			Light.Enabled = true

			local Aura = EffectsFolder:FindFirstChild("FB1"):Clone()
			local Aura2 = EffectsFolder:FindFirstChild("FB2"):Clone()
			local Aura3 = EffectsFolder:FindFirstChild("FB3"):Clone()
			local Aura4 = EffectsFolder:FindFirstChild("FB4"):Clone()
			local Aura5 = EffectsFolder:FindFirstChild("FB5"):Clone()
			Aura.Parent = Orb
			Aura2.Parent = Orb
			Aura3.Parent = Orb
			Aura4.Parent = Orb
			Aura5.Parent = Orb
			Aura.Enabled = true
			Aura2.Enabled = true
			Aura3.Enabled = true
			Aura4.Enabled = true
			Aura5.Enabled = true

			local Force = Instance.new("BodyForce")
			Force.Force = Vector3.new(0,Orb:GetMass()*workspace.Gravity,0)
			Force.Parent = Orb

			local gg = script.Splatterpoison:clone()
			gg.Enabled = true
			gg.Parent = Orb

			Orb.Parent = workspace

			Orb:SetNetworkOwner(MyPlayer) -- no lagging visuals

			Services.Debris:AddItem(Orb,4)

			Orb.Touched:Connect(function(hit) Blow(Orb, hit, Properties.OrbDamage) end)
		end)
			
		for timer=4,Reduction,-Reduction do
			Overlay.Text = timer
			wait(1)
		end
		Overlay.Text = "Q"
		Icon.Image = BaseUrl.."10646579428"
		Spell1 = true
	end,

I also did give LinearVelocity a shot but this would cause the projectile to arc straight through the floor

local Force = Instance.new("LinearVelocity")
			Force.VectorVelocity = (MousePos - Handle.CFrame.p).unit * 100
			Force.Parent = Orb

I then tried constantly adjusting the LinearVelocity and it would then arc to ground level and bounce toward the target (which it would hit if I aimed high enough) but it just looks goofy.

local direction = (MousePos - Handle.CFrame.p).unit
local speed = 100
Orb.AssemblyLinearVelocity = direction * speed

game:GetService("RunService").Heartbeat:Connect(function()
	if Orb and Orb.Parent then
		Orb.AssemblyLinearVelocity = direction * speed
	end
end)
2 Likes

Yeah LinearVelocities have a bit more setup than would be ideal in my opinion.

You need to parent the linearvelocity to an attachment in the part for it to work I believe. Then, you’d want to set it to world relative instead of attachment relative by setting LinearVelocity.RelativeTo = Enum.ActuatorRelativeTo.World. Also make sure to set the .MaxForce to something big.

For the second one, the problem might be that the client has network ownership, so the adjustment code would need to be run on the client for that to work properly (a linearvelocity works on the client because it replicates, then the client knows to use the linearvelocity). The problem also could be that the second one would still need a force against gravity if that wasn’t added. (With a linear velocity a force against gravity wouldn’t neccisarially be needed, but couldn’t hurt.)


That is seriously weird it only seems to happen for the orb, despite the fireball code being virtually identical from a physics standpoint.

2 Likes

Worked like a charm! For anyone interested this is how the final script turned out.

["Orb"] = function()
		if not Spell1 then return end
		Spell1 = false

		Handle:WaitForChild("LightningBolt"):Play()

		local Anim = MyHumanoid:LoadAnimation(Tool:FindFirstChild("Cast"))
		if Anim then Anim:Play() end

		local Icon = SpellGui:WaitForChild("SpellGuiFrame"):WaitForChild(ChosenSpellTag)
		local Overlay = Icon:WaitForChild("Overlay")
		local LastText = Overlay.Text
		Icon.Image = BaseUrl.."7560818616"
		spawn(function()
			local MousePos = MouseLoc:InvokeClient(MyPlayer)

			local Orb = Instance.new("Part")
			Orb.TopSurface = Enum.SurfaceType.Smooth
			Orb.BottomSurface = Enum.SurfaceType.Smooth
			Orb.Color = Color3.fromRGB(110, 153, 202)
			Orb.Material = Enum.Material.Neon
			Orb.Transparency = 0
			Orb.Shape = Enum.PartType.Ball
			Orb.Size = Vector3.new(1,1,1)
			Orb.Anchored = false
			Orb.CanCollide = false
			Orb.Velocity = (MousePos-Handle.CFrame.p).unit*100
			Orb.CFrame = CFrame.new(Handle.CFrame.Position, Handle.CFrame.Position + Orb.Velocity)

			local parti = script.Particles:Clone()
			parti.Enabled = true
			parti.Parent = Orb

			local Light = Instance.new("PointLight")
			Light.Color = Color3.fromRGB(0, 85, 255)
			Light.Range = 2
			Light.Brightness = 10
			Light.Parent = Orb
			Light.Enabled = true

			local Aura = EffectsFolder:WaitForChild("Bolt1"):Clone()
			local Aura2 = EffectsFolder:WaitForChild("Bolt2"):Clone()
			local Aura3 = EffectsFolder:WaitForChild("Bolt3"):Clone()
			local Aura4 = EffectsFolder:WaitForChild("Bolt4"):Clone()
			local Aura5 = EffectsFolder:WaitForChild("Bolt5"):Clone()
			local Aura6 = EffectsFolder:WaitForChild("Bolt6"):Clone()
			local Aura7 = EffectsFolder:WaitForChild("Bolt7"):Clone()
			local Aura7 = EffectsFolder:WaitForChild("Smoke"):Clone()
			local hi = Handle.Hit:Clone()
			hi.Parent = Orb
			Aura.Parent = Orb
			Aura2.Parent = Orb
			Aura3.Parent = Orb
			Aura4.Parent = Orb
			Aura5.Parent = Orb
			Aura6.Parent = Orb
			Aura7.Parent = Orb

			local LinearVelocity = Instance.new("LinearVelocity")
			LinearVelocity.Attachment0 = hi
			LinearVelocity.MaxForce = math.huge
			LinearVelocity.VectorVelocity = (MousePos - Handle.CFrame.p).unit * 100
			LinearVelocity.RelativeTo = Enum.ActuatorRelativeTo.World
			LinearVelocity.Parent = Orb

			Orb.Parent = workspace

			Orb:SetNetworkOwner(MyPlayer) -- no lagging visuals

			Services.Debris:AddItem(Orb,4)

			Orb.Touched:Connect(function(hit) Blow(Orb, hit, Properties.OrbDamage) end)
		end)
1 Like