How do I ignore accessories/accoutrements with a raycast?

Hello all. I am using workspace:Raycast() for a gun system I’m working on, but the problem is it’s having trouble ignoring accessories.

I’ve tried printing everything within the character on the CharacterAdded event and it’s not picking up the attachments. I have this here code:

game.Players.PlayerAdded:Connect(function(Player)
	Player.CharacterAdded:Connect(function()
		for _, A in pairs(Character:GetDescendants()) do
			if A:IsA("Accessory") or A:IsA("Accoutrement") then
				print("Accessory: ", A)
				table.insert(IgnoreParts, A)
			end
		end
	end)
end)

and it’s not ignoring the accessories. I’ve tried getting all the children of the accessories (the physical parts/handle) and adding it to the ignore list but to no avail. Does anyone know how to fix this?

local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = THE TABLE OF INSTANCES HERE

local raycastResult = workspace:Raycast(part.Position, part.CFrame.LookVector*50, raycastParams)

add this to the third parameter of the raycast like the example above

1 Like

this basically tells the raycast to ignore all the instances in the array

Yes I’ve already done this but it still does not ignore accoutrements or accessories.

For some reason RaycastParams.Blacklist doesn’t work for me either so I used this and it sorta did something.


if accessory:IsDescendantOf("Head") then
    -- do something
end

Accessories are children of the character, not the head

replace it with model then

IsDescendantOf("Model")

Can you not blacklist the character? That would apply to all the character’s descendants, including the accessories.
I’m assuming by this post though that it didn’t work?

I can’t blacklist the character, or else my gun system won’t work. It’ll ignore all the parts in other characters even the hats :confused:

Hold on,

you forgot to add Character in Character added

	Player.CharacterAdded:Connect(function(Character )

If this doesn’t do the fix then…

Are you raycasting the gun locally, hence is this in a local script? If it is then the character will definitely not be fully loaded when the model joins in. To solve this you can use descendants Added and :GetDescendants to add the accessories to the ignore list as the game adds them to the character while loading.

game.Players.PlayerAdded:Connect(function(Player)
	Player.CharacterAdded:Connect(function(Character)
      --get accessories that have already loaded
      for _, A in pairs(Character:GetDescendants()) do
			if A:IsA("Accessory") or A:IsA("Accoutrement") then
				print("Accessory: ", A)
				table.insert(IgnoreParts, A)
			end
		end
      --Get accesories that haven't loaded yet if done locally
      Character.DescendantAdded:Connect(function(descendant)
         if descendant:IsA("Accessory") or descendant:IsA("Accoutrement") then
            print("Accessory: ", descendant)
            if not table.find(IgnoreParts,descendant) then
               table.insert(IgnoreParts, descendant)
            end
		end
      end)
	end)
end)

Also make sure to remove the instances from the list when they get destroyed using .AncestryChanged to detect if they have been removed from workspace or else you got a memory leak.

1 Like

Would you happen to know if the character model is deleted when the player dies?

Also I am raycasting on the server not the client but I set up the list of ignored parts on the client (so I can ignore only the local player’s body parts in the local player’s gunshot) and pass the table to the server

You need to add Character in CharacterAdded otherwise it won’t work
oh

I did this after @dthecoolest’s comment and it still does not work. What’s funny is that it’s actually ignoring it after I shoot the head two or three times

Hmm, Another way to ensure the player is fully loaded is to use Player:HasAppearanceLoaded() so a way to do it is to use the CharacterAppearanceLoaded event to do it.

Anyways, all I can do is guess at this point since you are not giving away the code which you don’t need to.

Just make sure you are using the same raycast params and not creating a new one every shot with the proper setup like what @retr0_11001 has done and that .FilterDescendantsInstances is equal to the IgnoreParts table and not a typo error and it should be fine.

Wait, my raycast function creates new Params for every cast, but it needs to since the ignore table is being passed into the event function. Can I change the .FilterDescendantsInstances every raycast?

Since it works I’ll mark it as the solution - for now!

Okay so I finally found a fix although it may not be very efficient.

Here is my Raycast function on the server:

As you can see the IgnoredPartsClient table is passed every time the event is fired. I defined the local RCParams before this function and instead changed the FilterDescendantInstances every time and I re-raycasted every time the raycast picked up a handle or accoutrement/accessory until it got to the head.

It works - but I don’t know if it’s efficient. If anyone can reccomend any other efficient ways of tackling this I’m all ears.

FW.OnServerEvent:Connect(function(Player, RCInfo, Ammo, Gun, IgnoredPartsClient)
	spawn(function()
		local Grip = Gun:FindFirstChild("Grip")
		local MouseTarg, MouseHitPos, Crouching, Sprinting = table.unpack(RCInfo)
		local Target = nil
		
		local function ServerRayCast()
			if MouseTarg ~= nil then
				local Spread = GunSettings.WeaponSettings[Gun.GunId.Value]["Spread"]
				if Crouching then Spread = Spread - (Spread / 2)
				elseif Sprinting then Spread = Spread * 1.5	
				end --Spread is halved if crouching
				
				local Direction = (MouseHitPos - Gun.Muzzle.Position).Unit * GunSettings.WeaponSettings[Gun.GunId.Value]["MaximumDistance"]
				local NewIgnoreTable = {}
				NewIgnoreTable = IgnoredPartsClient
				
				local function CalculateOffset(S) return ((math.random() - 0.5) * S / 100) end
				local RXOffset = CalculateOffset(Spread)
				local RZOffset = CalculateOffset(Spread)
				local RYOffset = CalculateOffset(Spread)
				Direction = CFrame.fromEulerAnglesXYZ(RXOffset, RYOffset, RZOffset) * Direction
				RCParams.FilterDescendantsInstances = NewIgnoreTable

				local R = workspace:Raycast(Gun.Muzzle.Position, Direction, RCParams)
				
				local function ReRaycast()
					print("ReRaycast fired. Instance = "..R.Instance.Name)
					table.insert(NewIgnoreTable, R.Instance.Parent)
					IP:FireClient(Player, R.Instance.Parent)
					RCParams.FilterDescendantsInstances = table.pack(NewIgnoreTable, R.Instance)

					R = workspace:Raycast(Gun.Muzzle.Position, Direction, RCParams)
					print("Returning new instance. New instance = "..R.Instance.Name)
					return R.Instance
				end
				
				if R ~= nil and R.Instance.Name == "Handle" or R.Instance.Parent:IsA("Accessory") or R.Instance.Parent:IsA("Accoutrement") then
					print("Hat detected, ignoring")
					local Hat = true
					while Hat do
						wait()
						local NewPart = ReRaycast()
						if R ~= nil and R.Instance.Name == "Handle" or R.Instance.Parent:IsA("Accessory") or R.Instance.Parent:IsA("Accoutrement") then
							Hat = true
						else
							Hat = false
						end
					end
				end
				print(R.Instance.Name)
				
				if R == nil or R.Position == nil or R.Instance == nil then Target = nil else Target = table.pack(R.Position, R.Instance) end
			end
		end
		
		if Gun.Ammo.InClip.Value > 0 then ServerRayCast() end
		if Gun.Ammo.InClip.Value == 0 then Grip.UST.SoundId = "rbxassetid://410814187"; Grip.UST:Play(); return end
		Ammo.InClip.Value = Ammo.InClip.Value - 1
		GunfireVisual(Player, Gun)
		CalculateTarget(Player, Target, Gun)
	end)
end)
2 Likes