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
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?
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.
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
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)