Making projectiles more fluid?

(Local script)
tool.Activated:Connect(function()
	for count = 1, 5 do
		wait(.05)	
		local bullet = p1:Clone()
		bullet.CanCollide = false
		bullet.CFrame = hole.CFrame * CFrame.Angles(0,math.rad(180),0)
		bullet.Parent = workspace	
		
		local BV = Instance.new("BodyVelocity")
		BV.MaxForce = Vector3.new(1,1,1) * 10000
		BV.Velocity = humrp.CFrame.lookVector * 100
		BV.Parent = bullet
		Debris:AddItem(bullet,.5)
	end	
end)

(Module script)
function Zero.q(player,tool)
	local humrp = player.Character.HumanoidRootPart
	local hole = tool.Hole
	
	spawn(function()
		for count = 1, 5 do
			wait(.15)	
			
			local bullet = p1:Clone()
			bullet.CanCollide = false
			bullet.CFrame = hole.CFrame * CFrame.Angles(0,math.rad(180),0)
			bullet.Parent = workspace
			bullet:SetNetworkOwner(player)
		
			local BV = Instance.new("BodyVelocity")
			BV.MaxForce = Vector3.new(1,1,1) * 10000
			BV.Velocity = humrp.CFrame.lookVector * 100
			BV.Parent = bullet
			
			Debris:AddItem(bullet,.5)	
		end		
	end)	
end

So far on my scripting journey, I’ve recently noticed that creating parts and moving them with BodyMovers are delayed when created on the server compared to on client.

Above I posted my local script which creates bullets on the client and after is my module script which is required in my server script when the player press a keycode.

How should I go about shooting projectiles so that the client sees it smoothly and the server sees the bullets as well?

1 Like

Hey Zadits!

I’ve found that to have neat and smooth projectiles that don’t need to change direction mid flight you can use TweenService!

When creating the tween you’ll want to divide the speed you want it to go by the distance it has to travel because the formula for time is speed divided by distance, you can get that distance by casting a ray. You’ll also want to play with these number and try multiplying them by positive numbers less than 1 so that they’re scaled properly.

local Speed = 100 -- Your speed variable, the thing you would multiply your LookVector by
local EndPosition = Vector3.new(0, 0, 0) -- Vector that was calculated from ray cast
local Distance = (bullet.Position - EndPosition).Magnitude
local SpeedScaling = 1 -- The scale number, to make sure 100 speed isn't too slow or too fast

local Tween = TweenService:Create(bullet, TweenInfo.new((Speed / Distance) * SpeedScaling), {CFrame = CFrame.new(EndPosition)})
Tween:Play()

In the example above, 100 speed is in terms of studs per second, so 100 means it will travel 100 studs in a single second, you might want to turn that speed down a notch.

Hope this helps!

2 Likes

I mean i guess you could lerp and make its duration based on the distance.

Thanks for replying, I’ll definitely check this out but I’m not really familiar with raycasting. I tried reading the developer page on raycasting but I’m still confused how would I set the ray. Would I put the script above in the module script or would that go into local?

Thanks!

The code I wrote was more of a guide, and that would certainly go in the server if you wanted everyone to see it.

Ray casting has been made super simple lately, here’s the basic code for that:

local rayOrigin = bullet.Position
local rayDirection = humrp.CFrame.LookVector

-- Build a "RaycastParams" object and cast the ray
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {Shooter} -- This will want to be the player shooting the projectile so it doesn't hit them
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

Then once you have your raycastResult, it has a vew handy properties such as:

raycastResult.Position -- Set to the position where the ray hit, this is the position I mentioned earlier.
1 Like

Another way to make projectiles is to use the fast cast resource which makes projectiles using ray-casting, I suggest checking it out:

2 Likes