Hello
So right now I am working on projectiles. What I am trying to do is make the server do the actual collision detection, and the client will render the projectile in sync with the server. Right now, I have the exact effect I want, but it only renders to the client that shot the projectile and nobody else. The server calculates it all, and the client has a part move perfectly every frame to match the server simulation. I am kind of stumped and I dont know how Im gonna render it to the other clients without some sort of delay or making the projectile not move perfectly. I will provide the scripts, hopefully you guys have ideas.
Localscript:
local replicatedStorage = game:GetService("ReplicatedStorage")
local weaponModules = replicatedStorage.WeaponModules
local projectileModule = require(weaponModules.ProjectileModule)
local projectile = replicatedStorage.Projectiles.Paintball
local player = game:GetService("Players").LocalPlayer
local mouse = player:GetMouse()
local tool = script.Parent
local fire = tool.Fire
local attachment = tool.Handle.Attachment
local weaponType = tool.Name
local function activated()
fire:FireServer(mouse.Hit.Position,weaponType)
local blacklist = tool.Parent:GetDescendants()
local projectileProperties = {1,blacklist,Vector3.new(0,0,0),8,0,0,projectile,projectile.Size.Z/2}
local projectile = projectileModule.new(table.unpack(projectileProperties))
projectile:CastOnClient(attachment.WorldPosition,mouse.Hit.Position,7)
end
tool.Activated:Connect(activated)
Script:
local replicatedStorage = game:GetService("ReplicatedStorage")
local weaponModules = replicatedStorage.WeaponModules
local projectileModule = require(weaponModules.ProjectileModule)
local projectile = replicatedStorage.Projectiles.Paintball
local tool = script.Parent
local attachment = tool.Handle.Attachment
colors = {45, 119, 21, 24, 23, 105, 104}
tool.Fire.OnServerEvent:Connect(function(player,hit,weaponType)
if weaponType == tool.Name then
tool.Handle.Fire:play()
local spawnCFrame = attachment.WorldPosition
local blacklist = tool.Parent:GetDescendants()
local projectileProperties = {1,blacklist,Vector3.new(0,0,0),8,0,0,projectile,projectile.Size.Z/2}
local projectile = projectileModule.new(table.unpack(projectileProperties))
projectile:CastOnServer(spawnCFrame,hit,7)
end
end)
Module:
local replicatedStorage = game:GetService("ReplicatedStorage")
local debrisService = game:GetService("Debris")
local runService = game:GetService("RunService")
local projectile = {}
function projectile.new(gravity,blacklist,alternateForce,despawnTime,maxBounces,decay,projectileType,radius)
local newProjectile = {}
newProjectile.Gravity = gravity
newProjectile.AlternateForce = alternateForce
newProjectile.DespawnTime = despawnTime
newProjectile.MaxBounces = maxBounces
newProjectile.Decay = decay
newProjectile.Radius = radius
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = blacklist
newProjectile.Params = params
function newProjectile:CastOnClient(start,destination,force)
local conversion = 196.2/9.8
local velocity = (destination - start).Unit * force * conversion
local a = Vector3.new(self.AlternateForce.X,self.AlternateForce.Y -self.Gravity * 9.8,self.AlternateForce.Z) * conversion
local t = 0
local totalTime = 0
local bounces = 0
local currentVelocity = velocity
local currentPosition = start
local raycastResult = nil
local found = false
local currentVelocity
local projectiles = {}
local projectile = projectileType:Clone()
projectile.Parent = workspace.Projectiles
local connection = runService.RenderStepped:Connect(function(dt)
if not found then
t += dt
totalTime += dt
currentVelocity = velocity + a * t
local projectilePosition = Vector3.new(
start.X + velocity.X * t + 0.5 * a.X * t * t,
start.Y + velocity.Y * t + 0.5 * a.Y * t * t,
start.Z + velocity.Z * t + 0.5 * a.Z * t * t
)
raycastResult = workspace:Raycast(currentPosition,projectilePosition - currentPosition,self.Params)
if projectile then
projectile.Position = currentPosition
end
currentPosition = projectilePosition
if raycastResult then
print("ok")
if bounces >= self.MaxBounces then
found = true
else
local normal = raycastResult.Normal
velocity = currentVelocity - 2 * currentVelocity:Dot(normal) * normal
start = raycastResult.Position
currentPosition = raycastResult.Position
t = 0
bounces += 1
end
end
if totalTime > self.DespawnTime then
found = true
end
end
end)
while not found do
wait()
end
connection:Disconnect()
projectile:Destroy()
end
function newProjectile:CastOnServer(start,destination,force)
local conversion = 196.2/9.8
local velocity = (destination - start).Unit * force * conversion
local a = Vector3.new(self.AlternateForce.X,self.AlternateForce.Y -self.Gravity * 9.8,self.AlternateForce.Z) * conversion
local t = 0
local totalTime = 0
local bounces = 0
local currentVelocity = velocity
local currentPosition = start
local raycastResult = nil
local found = false
local currentVelocity
local connection = runService.Heartbeat:Connect(function(dt)
if not found then
t += dt
totalTime += dt
currentVelocity = velocity + a * t
local projectilePosition = Vector3.new(
start.X + velocity.X * t + 0.5 * a.X * t * t,
start.Y + velocity.Y * t + 0.5 * a.Y * t * t,
start.Z + velocity.Z * t + 0.5 * a.Z * t * t
)
raycastResult = workspace:Spherecast(currentPosition,self.Radius,projectilePosition - currentPosition,self.Params)
print(raycastResult)
currentPosition = projectilePosition
if raycastResult then
print("ok")
if bounces >= self.MaxBounces then
found = true
else
local normal = raycastResult.Normal
velocity = currentVelocity - 2 * currentVelocity:Dot(normal) * normal
start = raycastResult.Position
currentPosition = raycastResult.Position
t = 0
bounces += 1
end
end
if totalTime > self.DespawnTime then
found = true
end
end
end)
while not found do
wait()
end
connection:Disconnect()
if raycastResult then
print("Detected")
end
end
return newProjectile
end
return projectile
Is this a lost cause? I dont know but any help would be appreciated.