Projectile Attack Problems

  1. What do you want to achieve? Keep it simple and clear!
    I’m trying to make a smooth attack projectile

  2. What is the issue?
    The server and the client don’t seem to match up, even though it’s firing through a remote event so the client should be seeing whats on the server. There also seems to be a slight delay on the server.

Module Script

local module = {}
local damage = false
local hitlist = {}
local TweenService = game:GetService("TweenService")
local runservice = game:GetService("RunService")

function module.energyAttack(player, mousehit)
	local energyattack = game.ReplicatedStorage.EnergyAttack:Clone()
	local attachment = Instance.new("Attachment")
	local humanoidrootpart = player.Character.HumanoidRootPart
	attachment.Parent = energyattack
	local linearvelocity = Instance.new("LinearVelocity")
	linearvelocity.MaxForce = 100000
	linearvelocity.Attachment0 = attachment
	linearvelocity.Parent = energyattack
	energyattack.Position = humanoidrootpart.Position + humanoidrootpart.CFrame.LookVector * 5
	linearvelocity.VectorVelocity = (mousehit - energyattack.Position).Unit * 100
	energyattack.Parent = workspace
	local tweeninfo = TweenInfo.new()
	
	local goal = {
		Size = Vector3.new(10,10,10),
		Transparency = 1
	}
	
	local params = OverlapParams.new()
	params.FilterDescendantsInstances = {
		player.Character,
		energyattack
	}
	params.FilterType = Enum.RaycastFilterType.Exclude
	runservice.Heartbeat:Connect(function(dt)
		local hit = workspace:GetPartsInPart(energyattack, params)
		for i,v in pairs(hit) do
			if v:IsA("BasePart") then
				
				TweenService:Create(energyattack,tweeninfo,goal):Play()
			end
		end
	end)
	
	game.Debris:AddItem(energyattack,1)
	damage = false
end

return module

Server Script

local remote = game.ReplicatedStorage.RemoteEvent
local attackhandler = require(game.ReplicatedStorage.ModuleScript)

remote.OnServerEvent:Connect(function(player, mousehit)
	attackhandler.energyAttack(player, mousehit)
end)

Local Script

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character.Humanoid
local uips = game:GetService("UserInputService")
local remote = game.ReplicatedStorage.RemoteEvent
local mouse = player:GetMouse()

uips.InputBegan:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.F then
		remote:FireServer(mouse.Hit.Position)
	end
end)

Heres a video showing it
https://gyazo.com/8525345f48776b298c73e328e691e8e5

I’m not clear of exactly what your problem is, but I can say that:

  • There will always be a delay from server-client and client-server, we can’t do anything about it.

I know there is delay from server to client, that isn’t the problem. As in the link video, the projectile stops for a second on the server but not on the client. The clients touched is also firing even if it doesnt touch anything but on the server touch does not fire and the tween does not play. The client and the server aren’t seeing the same thing even though it’s being fired through a remote event so the client should see whats on the server.

The projectile is probably acting wonky because the client is attempting to assert network ownership over it since it’s so close.

If you want to make projectiles that feel smooth, you’re going to have to make them client-sided. I’ve got a guide here.

I was doing some testing and it seems that if you click multiple times the spatial query does not stop, I think this might be causing the lag in the video. How do I make the spatial query stop even though I disconnect it already?

https://gyazo.com/e19c377d776702b84c5fdcbf86168773

Module Script

local module = {}
local damage = false
local tweenservice = game:GetService("TweenService")
local heart

function module.EnergyAttack(player, mousehit, clicks)
	local energyattack = game.ReplicatedStorage.EnergyAttack:Clone()
	local torso = player.Character.HumanoidRootPart
	
	local linearvelocity = Instance.new("LinearVelocity")
	local attachment = Instance.new("Attachment")
	attachment.Parent = energyattack
	
	linearvelocity.Attachment0 = attachment
	linearvelocity.MaxForce = 100000
	linearvelocity.VectorVelocity = (mousehit - torso.Position).Unit * 50
	linearvelocity.Parent = energyattack
	
	energyattack.Position = torso.Position + Vector3.new(0,5,0) + torso.CFrame.LookVector * 5
	energyattack.Name = energyattack.Name.. " "..clicks
	energyattack.Parent = workspace
	
	heart = game:GetService("RunService").Heartbeat:Connect(function(dt)
		
		local params = OverlapParams.new()
		params.FilterDescendantsInstances = {player.Character, energyattack}
		params.FilterType = Enum.RaycastFilterType.Exclude
		
		local hit = workspace:GetPartsInPart(energyattack, params)
		
		local goal = {
			Size = Vector3.new(10,10,10),
			Transparency = 1
		}
		
		for i,v in pairs(hit) do
			print(v, energyattack.Name)
			
			if v:IsA("BasePart") then
				
				attachment:Destroy()
				linearvelocity:Destroy()
				energyattack.Anchored = true
				tweenservice:Create(energyattack,TweenInfo.new(), goal):Play()
			end
		end
	end)
	
	task.wait(1)
	energyattack:Destroy()
	heart:Disconnect()
end
return module

The lag is because you have a spatial query function connected to HeartBeat, and it’s on the server as well. If it absolutely must be on the server (given that it’s fired from a player, it shouldn’t), you should use raycasts instead. My previous guide on hitboxes covers how to make raycasts, though I believe it needs to be updated.

As for it hitting multiple times, it is because you disconnect the function after a second passes, not after it hits a target. You can self-disconnect a function by declaring it as an empty value and then assigning a function to it.

local heart
heart = game:GetService("RunService").Heartbeat:Connect(function(dt)
	if HitThing then
		heart:Disconnect()
	end
end