Projectile System acting differently in-game to studio

Hello, I am making a projectile shooting system where a projectile is shot from the player. It works perfectly fine on studio but when I go in-game it acts differently and is very jittery. Here is a video to showcase what’s happening:


I have really no idea why this is happening. I have the parts collisions turn off and even made the part massless but it still bugs out. I am using FastCast to achieve this here is my code:

Client

local Origin = HumanoidRootPart.Position + (HumanoidRootPart.CFrame.LookVector * 2)
local Direction = HumanoidRootPart.CFrame.LookVector
ReplicatedStorage.Events.Projectile:FireServer(Origin, Direction)

Server

Caster.LengthChanged:Connect(function(Cast, LastPoint, Direction, Length)
	Projectile.Position = LastPoint + Direction * Length
end)

Any help will be appreciated.

1 Like

Because when you play on the actual Roblox client you are playing on Roblox’s servers.

The roblox client uses a connection to a real server, meaning that projectiles can appear jittery or incorrect if they are modelled by the server, and was likely not appearing as the difference between the server and the client was much more minimal.

In order to circumvent ths, you can either use the Roblox physics engine which compensates for this (see BodyPosition) or do what some professional games do and have the server interpret the path of the projectile (for hit casting) and then the local client maps the projectile so it appears smooth.

I was thinking of doing that but wouldn’t the person who shot the projectile be the only one that sees it?

You’d have to manually replicate it to each client. Whenever a projectile is shot, have the server fire a remote to each client which then all create and move / animate that clientside projectile. It not only appears a lot smoother but also saves on network bandwidth.
Note that you would need to handle things like hit detection on the server which might be a bit difficult.

Here’s a quick demonstration of what this might look like:

-- Server projectile handler
local ProjectileRemote = ReplicatedStorage.ProjectileRemote
local TryFireProjectile = ReplicatedStorage.TryFireProjectileRemote

local function CreateProjectile(position: Vector3, direction: Vector3) 
    ProjectileRemote:FireAllClients(position, direction)
end

TryFireProjectile.OnServerEvent:Connect(function(player: Player, ...) 
    -- etc etc
    CreateProjectile(whatever, whatever)
end)
-- Client projectile handler
local RunService = game:GetService('RunService')
local ProjectileRemote = ReplicatedStorage.ProjectileRemote

local function CreateProjectile(position: Vector3)
    -- etc
    return projectile 
end

local projectiles = {}
ProjectileRemote.OnClientEvent:Connect(function(position, direction) 
    local t = {
        Direction = direction,
        Instance = CreateProjectile(position)
    }
    table.insert(projectiles, t)

    task.delay(4, function()
        local ind = table.find(projectiles, t)
        if ind ~= nil then
            table.remove(projectiles, ind)
        end
    end)
end)

RunService.Heartbeat:Connect(function(delta: number) 
    for _, projectile in projectiles do
        projectile.Instance.Position += projectile.Direction * delta -- Deltatime is important
    end
end)

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