How to improve projectile aiming?

So I need to know how to improve aiming for my projectiles. I’ve asked around and people say this way of aiming doesn’t work. I tested, they’re right sometimes the projectile doesnt shoot toward where it’s going.

What I mean by this is that the projectile goes in random directions sometimes. Here’s the localscript where it filters parts that get in the way:

local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
if not Character.Parent then Character.AncestryChanged:Wait() end
local Mouse = Player:GetMouse()
local Tool = script.Parent
local Fired = Tool:WaitForChild("Fired")
local id = "rbxassetid://"
local anim
if id then
	anim = Instance.new("Animation")
	anim.AnimationId = id
end
local camera = workspace.CurrentCamera
local length = 500
Mouse.TargetFilter = workspace
Mouse.Button1Down:Connect(function()
	if Player.Character and Player.Character.Humanoid.Health > 0 then
		if Tool.Parent == Player.Character then
			if id and anim then
				local hum = Player.Character.Humanoid
				local track = hum:LoadAnimation(anim)
				track:Play()
			end
			local raycastParams = RaycastParams.new()
			local Chars = workspace.Chars or workspace:WaitForChild("Chars")
			raycastParams.FilterDescendantsInstances = {Chars, Tool, workspace.Bullets, workspace.CurrentCamera}
			raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
			
			local unitRay = camera:ScreenPointToRay(Mouse.X, Mouse.Y)
			local raycastResult = workspace:Raycast(unitRay.Origin, unitRay.Direction * length, raycastParams)
			Fired:FireServer(
				{
					HitPosition = raycastResult and raycastResult.Position or nil;
					EndPosition = unitRay.Direction * length;
				}
			)
		end
	end
end)

Rather than using :ScreenPointToRay just use the Mouse.Hit.Position and calculate the direction by subtracting positions, something like this.

            local direction = (Mouse.Hit.Position - Player.Character.PrimaryPart.Position).Unit * length
			local raycastResult = workspace:Raycast(Player.Character.PrimaryPart.Position, direction, raycastParams)
			Fired:FireServer(
				{
					HitPosition = raycastResult and raycastResult.Position or nil;
					EndPosition = direction;
				}
			)

What about Mouse.Hit instead of Mouse.Hit.Position? Would that be more efficient, because Mouse.Hit.Position is a Vector3 right, so it may collide?

If you’re calculating a direction you need to be using Vector3 values, not CFrame which is what Mouse.Hit is.

I’ll give it a try and see if it helps

Should I keep the TargetFilter as workspace? I was told it might break things.

I don’t think you need that, no. Make sure you use the updated code, I just edited it because I forgot a .Unit

So like this right?

local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
if not Character.Parent then Character.AncestryChanged:Wait() end
local Mouse = Player:GetMouse()
local Tool = script.Parent
local Fired = Tool:WaitForChild("Fired")
local id = "rbxassetid://"
local anim
if id then
	anim = Instance.new("Animation")
	anim.AnimationId = id
end
local camera = workspace.CurrentCamera
local length = 500
Mouse.Button1Down:Connect(function()
	if Player.Character and Player.Character.Humanoid.Health > 0 then
		if Tool.Parent == Player.Character then
			if id and anim then
				local hum = Player.Character.Humanoid
				local track = hum:LoadAnimation(anim)
				track:Play()
			end
			local raycastParams = RaycastParams.new()
			local Chars = workspace.Chars or workspace:WaitForChild("Chars")
			raycastParams.FilterDescendantsInstances = {Chars, Tool, workspace.Bullets, workspace.CurrentCamera}
			raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
			local direction = (Mouse.Hit.Position - Player.Character.PrimaryPart.Position).Unit * length
			local raycastResult = workspace:Raycast(Player.Character.PrimaryPart.Position, direction, raycastParams)
			Fired:FireServer(
				{
					HitPosition = raycastResult and raycastResult.Position or nil;
					EndPosition = direction;
				}
			)
		end
	end
end)

Yeah, looks good, give that a shot.

This happened when I did that, basically the same problem. Some aiming angles just don’t work at all.

EDIT: Should I show the server side? Because that may be the problem…

That’d be because you clicked the sky in which case Mouse.Hit would be nil, just like :ScreenPointToRay() would be, I believe.

oh well how can I improve that? because it’s a problem if you can’t aim unless you click on the map

Nevermind, just checked, that’s not the issue. Your raycasting looks good to me, could it be something with how the server is creating the projectile?

You should probably handle raycasting on the server side instead of client

1 Like

I tried the server side, but that doesn’t really change the problem for some odd reason. here’s the server script:

Rem.OnServerEvent:Connect(function(FiredPlayer, Array)
	if FiredPlayer ~= Player then return end
	if not Deb then
		Deb=true
		local Character = Player.Character or Player.CharacterAdded:Wait()
		local Humanoid = Character:WaitForChild("Humanoid")
		local Track = Humanoid:LoadAnimation(script.CannonThrow)
		Track:Play()
		wait(Track.Length/.8)
		local CannonBall = game.ReplicatedStorage.CannonBall:Clone()
		CannonBall.Name = "CannonBall"
		CannonBall.Trail.Enabled=false
		Tool.Handle.Transparency = 1
		CannonBall.Parent = workspace
		local targetPosition = Array.HitPosition or Array.EndPosition
		CannonBall.CFrame = Tool.Handle.CFrame
		CannonBall.CFrame = CFrame.new(CannonBall.CFrame.p, targetPosition)
		local Downwards=0
		local ElapsedTime = 0
		local Hit
		local Damaged
		local RS
		RS = game:GetService("RunService").Heartbeat:Connect(function(v)
			ElapsedTime+=0			
			local Box = Hitbox.new(CannonBall.CFrame, HBSZ)
			local Parts = Box:FindPartsInRegion3WithIgnoreList(Character:GetChildren(), 50)
			for _,v in pairs(Parts) do
				if v ~= CannonBall and not v.Parent:IsA("Accessory") then
					explode(Player, Character, CannonBall)
					Hit=true
					CE:FireAllClients("Bomb", nil, CannonBall)
					CannonBall.Transparency = 1
					game.Debris:AddItem(CannonBall, 5)
					Tool:Destroy()
					RS:Disconnect()
				end
			end
			if CannonBall.Position.Y < workspace.Ocean.Position.Y then
				Hit=true
				Tool:Destroy()
				RS:Disconnect()
			end
			if not Hit then
				local Track = TS:Create(CannonBall, Info1, {CFrame = (CannonBall.CFrame + CannonBall.CFrame.LookVector * 6) - Vector3.new(0,Downwards/50,0)})
				Track:Play()
				Track:Destroy()
				Downwards=Downwards+.005
			end
		end)
	end
end)

??? isn’t that what I already have

It doesn’t return nil, I printed it and it prints coordinates. Only problem is that the coordinates aren’t correct.

I tested the script again, and clicked on parts of the map and it doesn’t aim right even when you click on parts.