How can i properly make projectile hitboxes?

Your right about the strain on the server but the server doesnt need to see the bullet itself thats why you i use a remote event with :FireAllClients so each client has a replicated copy with smooth movement. Only thing important on the server is the hitbox.

This could be inefficient. Too many requests on the server and the bullet will only be seen on the client. I see what you mean though.

3 Likes

You could create your own raycast module and add all the features you need by defining the volume / hitbox of the projectile using a Region3, then, use custom logic to move the region and and add features like projectile drop. For collision detection, you can use GetPartBoundsInBox and specify collision behavior with the default RaycastParams data type. If you encounter performance issues, consider using some form of batch processing or lower the frequency of collision checks to reduce lag.

1 Like

This is what im trying to find out.

Example:

Bullet Force = 100

I want to find out how much i should move the hitbox per heartbeat so it matches the force of the bullet

1 Like

You’ll need to move the hitbox forward the same length as the projectile to avoid skipping collisions. You can use the force to determine the length of the projectile, allowing it to move faster without missing collisions. For projectile drop, store the creation time of the projectile using Tick() and use the time difference as a parameter in an interpolation formula (Something like this).

1 Like

My projectile is only replicated to the clients. The server doesn’t keep track of it, it only has the force which it passes to the clients.

And im a little lost on this:

2 Likes

Move the collision detection to the server and send the necessary information to the client for rendering. Relying on clients for collision detection can make your game vulnerable to exploiters and affect performance.

If your projectile is 2 studs long, you should move it forward by 2 studs per heartbeat. Moving it more than that could cause it to skip collisions, while moving it less could cause inefficiencies due to overlapping positions. Increasing the size of the projectile can make it move forwards faster, while not skipping any collisions.

2 Likes

I never rely on the client? My hitbox with the collision detection IS on the server but the projectile which is affected by velocity is on the client.

Hitbox and projectile’s are 2 different thing’s in my game

This is where we got it confused because my projectile’s use assembly linear velocity and linear velocity. I dont use heartbeat events to move them I use instances

If i were to use your logic, count the hitbox as the projectile to move with the heartbeat event. the actual projectile model, example: a baseball would be unimportant and just a model with effects.

1 Like

I didn’t know your projectiles were actual parts. I don’t recommend using unanchored client side parts to represent the projectiles, as it could affect performance, require manual garbage collection, and Roblox physics are generally unreliable on the client.

1 Like

How does it affect performance? If I manually anchor and use heartbeat its not gonna create the physic’s effects a regular projectile has. But this is for alv, for a regular linear projectile ill probably use your method, but it can also cause lag on the server cant it? And especially if i have many projectiles at the same time. Its better to put some of this work on all client since it doesn’t have the job of replicating everything to every player

1 Like

As I mentioned here, you can simulate the physics to ensure you know exactly where the projectile will be at any time, allowing you to replicate the positions accurately.

I tested it with 2600 projectiles, and it ran fine even without optimizations like streaming. However, performance can vary depending on the player’s computer.

Can you show me some code of how it would look like?

I thought you said it was bad for performance?

Setup:

–Local Script:

UIS.InputBegan:Connect(function()
    --Client code for when a button is pressed to tell the server to replicate the projectiles
    Event:FireServer()
end)

–Server Script


local Force = 100

Event.OnServerEvent:Connect(function(Player)
    ReplicateProjectileEvent:FireAllClients(Force)
    --Code for the hitbox here, what im trying to figure out
end)

–Local Script 2


  ReplicateProjectileEvent.OnClientEvent:Connect(function(Force)

      --Creates the projectile with the linear velocity
    local Direction = --Mouse position from the sent player minus the sent players charcter
    LinearVelocity.VectorVelocity = Direction.Unit * Force
end)

This is what i roughly do to set it up but im willing to change it because idk what to even do atp

Boosting postttttt 31 characters

This is a proof of concept and should ideally be implemented on the client rather than the server. I’ve written it on the server for now as I currently do not have enough time to write the full thing.

Script Inside ServerScriptService
local RunService = game:GetService("RunService")

-- Testing projectile part
local Projectile = Instance.new("Part")
Projectile.Size = Vector3.new(1, 1, 3)
Projectile.Position = Vector3.new(0, 20, 0)
Projectile:SetAttribute("CreationTime", tick()) -- Track the creation time for the interpolation function
Projectile.Anchored = true
Projectile.Parent = workspace

local Force = 2 -- Horizontal movement speed of the projectile
local Gravity = 2 -- Fall speed of the projectile

--- Quadratic interpolation function to calculate the projectile's position
-- @param startPos The starting position of the projectile
-- @param force The force applied to the projectile (used for air resistance)
-- @param currentTime The current time
-- @return The new position of the projectile
local function interpolate(startPos, force, currentTime)
	-- Calculate the vertical drop this frame, clamped to a maximum of 5 (terminal velocity)
	local drop = math.clamp(currentTime^2 / Gravity / force, 0, 5)

	-- Calculate the new position by subtracting the drop from the starting position
	local newPos = startPos - Vector3.new(0, drop, 0)

	return newPos
end

--- Function called every frame to update the projectile's position
local function heartbeat()
	-- Get the creation time of the projectile
	local creationTime = Projectile:GetAttribute("CreationTime")

	-- Calculate how long the projectile has existed
	local timeDifference = tick() - creationTime

	-- Set the new position for the projectile
	-- interpolate(Projectile.Position, Force, timeDifference) to get the new height
	-- Projectile.CFrame.LookVector to get the horizontal movement
	-- Projectile.Size.Z to avoid overlapping and skipping positions
	-- Increase the part's Z size to make it move faster
	Projectile.Position = interpolate(Projectile.Position, Force, timeDifference) + Projectile.CFrame.LookVector * Projectile.Size.Z
end

-- Connect the heartbeat function to the RunService.Heartbeat event
RunService.Heartbeat:Connect(heartbeat)

ProjectileExample.rbxl (52.8 KB)

Unanchored parts would be bad for performance and have unreliable physics when used on the client. I used anchored parts and moved them with a RunService.Heartbeat connection.

Create a Region3 to represent the projectile on the server, then use the interpolation function I provided to move that region forwards. Use Workspace:GetPartBoundsInBox to check for collisions.

You could use the interpolation function to visualize the movement of the part by updating its position, or have the server send the Region3 location to the client, and use that to visualize the part.

Additionally, optimize the collision detection logic and part movement using something like batch processing before using it in production.

1 Like

I went into the project and it works but I have some questions.

Im guessing by remote events?

Also what is this?

Yes

Instead of creating separate RunService.Heartbeat connections for each part’s collision detection, create a single connection that loops through a table of all the projectiles and processes them simultaneously. However, consider using BasePart.Touched first, as it may be more performant if it works correctly.

1 Like

Yeah it would be my last resort using touched events for heavy physics based projectiles

1 Like

I didnt really find a answer to this question but i found some helpful topics like:

This works for linear projectiles with a predictable path but not really what im looking for

If you do not want it to be linear you can modify the equation.

Currently the equation is this on the Z axis

local projectileTime =  (respondedTick - startTickVal)
local positionCFrame = spawnPoint * CFrame.new(0, 0, -45 * projectileTime )

If you want it to randomly start moving diagonally at 5 seconds in linearly you can use an if statement.

local projectileTime =  (respondedTick - startTickVal)

if projectileTime > 10 then
--Start moving in X axis instead
local positionCFrame = spawnPoint * CFrame.new( -45 * (projectileTime-10), 0, -45 * projectileTime )

else
local positionCFrame = spawnPoint * CFrame.new(0, 0, -45 * projectileTime )
end

You can even instead of just making it swerve 10 seconds in you can use math.random instead to make it even more unpredictable yet predictable.

You can also even add a quadratic equation instead to make a curved behavior.

local positionCFrame = spawnPoint * CFrame.new(0, 0, -45 * projectileTime^2 -5*projectileTime )

The concept I did above was actually similar but not the same as fastcast using piecewise functions to seperate the projectile motions into sections.

2 Likes

I know how do to everything you said except the equation.

This was what i was looking for but i dont know how to implement it i know the rest of what you said but i usually use roblox physics to move my projectile.

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