Understanding Projectiles?

((Please don’t link Fastcast as I’m attempting to find a solution without.)

I’m looking into projectile management on a large scale - I’ve watched a fair few tutorials on both YouTube and DevForum but all seem to be using .Heartbeat() on the Server and others are using BodyConstraints for the physics.

To summarise, I’m working on SpellCasting & want the Projectiles to be Moved from PointA to PointB whilst checking for obstructions Infront of them. I’ve got a basic method of doing this utilities :FireAllClients and loading the Projectile & Movement ClientSide by utilising CollectionService to see when a new SpellPart is added.

However I’m seeing an increase in Pings whenever this occurs and don’t want to create immense lag from Projectiles. (Roughly about 15-20 being fired every 2-3 seconds by the Players ingame.)

Does anyone have any suggestions or concepts that I could build on? This is a method that has baffled me for years now and I’m looking for finally solve it efficiently.

2 Likes

Ping is related to the amount of data being sent, how does your remote structure look like? Have you tried minimizing it?

Are you creating instances on the server as well? That will also need to bre replicated and increase ping.

1 Like

Projectiles are created and managed on the Client.

I handle the remotes by:
Wand tool > RemoteEvent in replicatedStorage > Confirms data > FiresAllClients on another remote event. Then from there it’s handled on the client.

Yep that structure sounds good.

How much data are you sending? Is it just position, direction, and id of was shot? I remember FE gunkit was sending a whole table of effects and settings which easy reached the 50 kbps data limit. Speaking of which what is the maximum kbps you get while shooting the spell?

1 Like

I’m also sending the wand Tools data, i.e. the tool itself and the caster?
And not too sure on the Kbps however the pings gradually increase from 30 to 50 and fluctuate between 50-60

I like doing it with physics.

Hit detection if high speeds:

local RunService = game:GetService("RunService")

local bullet = script.Parent
local previousPosition = bullet.Position

local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {bullet}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude

RunService.Stepped:Connect(function()
    local origin = bullet.Position
    local direction = (origin - previousPosition) * (origin - previousPosition).Magnitude
    local raycast = workspace:Raycast(origin, direction, raycastParams)

    if raycast then
        print("hit")
    end

    previousPosition = origin
end)
1 Like

Would this then moving using BodyConstraints? Ideally looking to avoid that as I feel it won’t be as smooth as CFraming?

No, you just launch the part using :ApplyImpulse or part.AssemblyLinearVelocity.

On the server, you create the projectile and set the network owner to the player and launch it using AssemblyLinearVelocity.

You can use the server or the client to detect hit detection with my script above.

Would this be more performant than CFrame? Or would there be a noticeable stutter when first creating to projectile and setting the NetworkOwner to the Player?

CFraming every frame is laggier than using Physics.

I don’t think there would be any stutter as you only need to set the network owner to the main part.

1 Like

I’ll give that a go when I’m home :slight_smile:
Do you possibly have any snippets of code I can use as reference and build on as an example, please?
It’s fine if not!

1 Like

place file:
Fast Bullet.rbxl (56.1 KB)

1 Like

Thank you! I’ve looked into it however due to the physics I can’t really work with it - I’m looking for my spells to be linear in direction as opposed to gravity induced. :confused:

I’m continuing to work on this ~ I’ve attached below code that I’m currently working on - This is just an example of producing projectiles & movement.

Issue it that the only way I can get an accurate detection is by having the Speed and the RaycastDistance both match - The issue with this is that if the Speed is ‘20’ then that Raycast is capable of hitting targets from 20 studs away - Whereas those 20 studs could be crucial for a defence.


	local Core = { ... }
	local Server, Script = game, script
	
	local Folder = Instance.new('Folder')
	Folder.Parent = workspace
	
	local RaycastParam = RaycastParams.new()
	RaycastParam.FilterType = Enum.RaycastFilterType.Exclude
	RaycastParam.FilterDescendantsInstances = {Folder}
	
	local Speed = 5
	
	Server:GetService('RunService').PreSimulation:Connect(function(dt, ...)
		for __,Part in (Server:GetService('CollectionService'):GetTagged('Projectile')) do
			local LastPos = Part.Position
			local result = Server:GetService('Workspace'):Raycast(LastPos, Part.CFrame.LookVector * Speed, RaycastParam)
			if not result then
				Part.CFrame *= CFrame.new(-Vector3.zAxis * Speed)
			else
				Part.Position = result.Position
				Part.Transparency = 1
				Part:FindFirstChild('ParticleEmitter', true):Emit(1)
				Part:RemoveTag('Projectile')
			end
		end
	end)
	
	while Core do 
		task.wait(0.25)
		
		local Part = Script.Part:Clone()
		Part.Size = Vector3.new(1, 1, 1)
		Part.Anchored = true
		Part.CanCollide = false
		Part.CanTouch = false
		Part.CanQuery = false
		Part.CastShadow = false
		Part.Position = Vector3.new(0, 18.5, 227) + Vector3.new(math.random(-45, 45), math.random(-16, 16), 0)
		Part.BrickColor = BrickColor.random()
		Part.Parent = Folder
		
		Server:GetService('Debris'):AddItem(Part, 5)
		
		Part:AddTag('Projectile')
	end
	
	return Core

Why this?

Part.CFrame.LookVector * Speed

cant you do this?

local distance = (currentPosition - lastPosition).Magnitude
local direction = (currentPosition - lastPosition).Unit * distance
1 Like

Yep & that’s solved the speed issue I’d been having for quite some time! ._.
Thank you so much for that one!

1 Like

Sorry to bump this again - Just one final question.
In terms of using the .Stepped - Is it best to filter through a table of the projectiles within CollectionService i.e. for __,Part in (Service) do or to simply allow each projectile to generate their own .Stepped function?

I think having individual Stepped for each projectile is better because looping through a table uses more data.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.