How can i utilize raycasting for a hitscan type weapon for my game?

Okay, i just want to raycast a ray that goes up to 80 studs. I’ve managed to do everything else, but this part simply just stumped me.

Summing up, i want to do this:

invoke raycast with the limitations applied
create a part that goes up to that, then fade it out with tweenservice, then delete the part
if the part hits someone, deal damage (random number from 10 to 20) then make it unable to deal more damage

Server script

local Tool = script.Parent
local Handle = Tool:WaitForChild("Handle")
local Player = Tool.Parent.Parent.Character
local Humanoid = Player:WaitForChild("Humanoid")
local CanUse = false
local CanHurt = false
local Remote = Tool.ShareInfo
local Attachment = Handle.Barrel

if Humanoid.Animator == nil then
	local Animator = Instance.new("Animator", Humanoid)
end
local Animator = Humanoid.Animator
local Equip = Animator:LoadAnimation(script.Equip)
local Idle = Animator:LoadAnimation(script.Idle)
Idle.Looped = true
local Shoot = Animator:LoadAnimation(script.Shoot)

if Humanoid.RigType == Enum.HumanoidRigType.R15 then
	warn("Sorry, this gear does not support R15! Please switch the game to R6 via Game Settings > Avatar > R6.")
	Tool:Destroy()
end

Tool.Equipped:Connect(function()
	CanHurt = false
	CanUse = false
	Handle.Equip:Play()
	Equip:Play()
	Equip.Stopped:Wait()
	if Tool.Parent == Player then
		Idle:Play()
		CanUse = true
	end
end)

Tool.Unequipped:Connect(function()
	CanHurt = false
	Shoot:Stop()
	Idle:Stop()
	Equip:Stop()
end)

Tool.Activated:Connect(function()
	if CanUse == true then
		CanUse = false
		Remote:FireClient()
		Handle.Fire:Play()
		Idle:Stop()
		CanHurt = true
		Shoot:Play()
		Shoot.Stopped:Wait()
		CanHurt = false
		if Tool.Parent == Player then
			Idle:Play()
			CanUse = true
		end
	end
end)

local function FadePart(Part)
	local TS = game:GetService("TweenService")
	local TInfo = TweenInfo.new(0.3, Enum.EasingStyle.Linear)
	local Tween = TS:Create(Part, TInfo, {Transparency = 1})
	Tween:Play()
end

local function DoStuff(RaycastResult, RayDirection, RayOrigin)
	local RayPart = Instance.new("Part")
	RayPart.Size = Vector3.new(0.3, 0.3, (RayDirection - RayOrigin).Magnitude)
	RayPart.CFrame = CFrame.new((RayDirection + RayOrigin) / 2, RayDirection)
	RayPart.Anchored = true
	RayPart.CanCollide = false
	RayPart.Parent = workspace
	RayPart.Color = Color3.fromRGB(76, 177, 255)
	RayPart.Material = Enum.Material.Neon


	spawn(FadePart(RayPart))
	local HitPart = RaycastResult.Instance
	if HitPart and HitPart:IsA("Model") then
		local Humanoid = HitPart:FindFirstChildOfClass("Humanoid")
		if Humanoid then
			Humanoid.Health = Humanoid.Health - math.random(10, 20)
		end
	end
end

Remote.OnServerEvent:Connect(DoStuff)

Local script

local Remote = script.Parent:WaitForChild("ShareInfo")

local Mouse = game.Players.LocalPlayer:GetMouse()

local function PerformRaycast()
	local RayOrigin = script.Parent.Handle.Barrel.Position
	local RayDirection = (Mouse.Hit.Position - RayOrigin).unit * 60

	local RaycastParameters = RaycastParams.new()
	RaycastParameters.FilterDescendantsInstances = {game.Players.LocalPlayer}
	RaycastParameters.FilterType = Enum.RaycastFilterType.Exclude
	RaycastParameters.IgnoreWater = true

	local RaycastResult = workspace:Raycast(RayOrigin, RayDirection, RaycastParameters)

	if RaycastResult then
		Remote:FireServer(RaycastResult, RayDirection, RayOrigin)
	end
end

Remote.OnClientEvent:Connect(PerformRaycast)

Apologies for the bad/messy code, it’s my first time coding gears. But it works and doesn’t bring my FPS down to 5, so i’m happy with it.

9 Likes

i just realized i forgot to edit that magnitude part before sending it here. whoops.

5 Likes

The distance of a raycast is controlled by multiplying the direction by a number. So you’d want to change

(Mouse.Hit.Position - RayOrigin).unit * 60

to

(Mouse.Hit.Position - RayOrigin).unit * 80
6 Likes

Thing is, i already did that. But, whenever the remote fires from the server, it says that “Argument 1 is missing or nil”??

6 Likes

When recieving a remote event from the client, the first parameter is always the player that fired it. RaycastResult is being declared at the player, so it should be

DoStuff(Player, RaycastResult, RayDirection, RayOrigin)

You should also make sure that it’s the player with the weapon that’s firing, not someone else.

3 Likes

image

How can i make sure it’s only the player that has it fires it? Sorry, i’m tired.

4 Likes

image
I thought it wouldn’t be necessary because of the way the stuff is structured.

6 Likes

You can find the player’s character, then use game.Players:GetPlayerFromCharacter() and see if it matches up with who’s calling the event.

I reccomend you place a watch with the debugging tool to see what’s nil.

4 Likes

What exactly do you mean by “debugging tool”?

4 Likes

Basically, in a script, you right click on a line and select breakpoint > insert breakpoint (or you can left click next to the line number). When the script is run and reaches this line, the game will pause. In the script tab you’ll see three buttons under the debugger tab, Step In, Step over, and Step Out.

Step In will progress the script to the next line of code, and the other two are used for skipping. To moniter the variables that are being changed, you can go to the view tab and enable the watch tab, which shows each variable in the script.

The point of it is to allow you to see things in ‘slow-mo’ incase you’ve overlooked something that’s causing unintended behaivor. If you can find out what’s being sent as nil, you can narrow down what’s the issue.

3 Likes

OOOOOH… I mean, i literally found a probable patch. I just had to add an argument to the FireServer thing, which ended up being the script.Parent.Parent of the tool… which ended up being the Player of whoever had the weapon. I’ll see if it works.

EDIT: Yep, it works! But the part(raycast part which deals damage) is still invisible.
EDIT 2: I’ll scrap that part… the rest works.

4 Likes

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