What are some of the most efficient ways to shoot a projectile toward a player's mouse?

Hello, I’m trying to make a script that allows the player to shoot a projectile toward the direction of their mouse.

So far the way I’m doing it is through UserInputService it gets the input that the player has clicked the mouse and fires a remote event to create the projectile. Then I use another remote event to fire to all clients to tween the projectile (I heard that you should always tween on the client or something).

The problem with my code is that sometime the damage is delayed and the player takes damage a few seconds later and the hitbox is just atrocious.

Are there any alternate/better ways to make a projectile shoot toward a player’s mouse or how can I improve upon my script?

RE.OnServerEvent:Connect(function(player , MouseHit , AmmoAmount)
	if AmmoAmount.Value > 0 then
		local debounce = true
		local character = player.Character
		local RightHand = character.RightHand
		local Animator = character.Humanoid.Animator
		
		AmmoAmount.Value = AmmoAmount.Value - 1
		
		local projectile = Instance.new("Part")
		projectile.Shape = "Ball"
		projectile.Size = Vector3.new(1.5 , 1.5 , 1.5)
		projectile.Color = player.PlayerColor.Value
		projectile.CanCollide = false
		projectile.Parent = workspace
		projectile.CFrame = CFrame.new(RightHand.CFrame.Position , MouseHit.Position)

		local weld = Instance.new("WeldConstraint")
		weld.Parent = projectile
		weld.Part0 = projectile
		weld.Part1 = RightHand
		
		local BodyForce = Instance.new("BodyForce")
		BodyForce.Force = Vector3.new(0 , (workspace.Gravity * projectile:GetMass()) , 0)
		BodyForce.Parent = projectile
		
		local animation = Animator:LoadAnimation(game:GetService("ReplicatedStorage").ThrowAnimation)
		animation:Play()
		
		wait(.3)
		
		weld:Destroy()
		projectile.CFrame = CFrame.new(RightHand.CFrame.Position , MouseHit.Position)
		BCE:FireAllClients(projectile)
						
		projectile.Touched:Connect(function(hit)
			local HitPlayer = game.Players:GetPlayerFromCharacter(hit.Parent)
			if hit.Parent:FindFirstChild("Humanoid") then
				if player.Name ~= HitPlayer.Name and debounce then
					debounce = false
					local HitHumanoid = hit.Parent:FindFirstChild("Humanoid")
					HitHumanoid.Health = HitHumanoid.Health - 50
					projectile:Destroy()
					
					wait(.1)
					
					debounce = true
				end				
			end
		end)
		
		wait(2)
		
		projectile:Destroy()
	end
end)

The projectile tween in client

BCE.OnClientEvent:Connect(function(projectile)
	local info = TweenInfo.new(2 , Enum.EasingStyle.Linear , Enum.EasingDirection.In , 0 , false , 0)
	local goal = {CFrame = projectile.CFrame + projectile.CFrame.LookVector * 400}
	local tween = service:Create(projectile , info , goal)
	tween:Play()
end)

Thanks in advance! :+1:

3 Likes

It looks like you’re only moving the projectile on the client and .Touched is being done server-side. As far as the server is aware, the projectile has only had its CFrame moved on its axis to face the target location. Therefore, players will only be damaged if they walk into the projectile that is suspended in the air.

Unfortunately for a script like this, you will have to do the tweening on the server.

1 Like