You can write your topic however you want, but you need to answer these questions:
I am trying to make my raycast weapons pass through blocks that are cannotcollide.
2.I am not sure how to script this, and I am using the older raycast method.
I do not know what to do, and I am not the best at raycast scripting.
local ray = Ray.new(hole.CFrame.p, (mouse.hit.p - hole.CFrame.p).unit * range.Value)
local touch, position = workspace:FindPartOnRay(ray, player.Character, false, true)
--//Hit detection
if touch then
hitRemote:FireServer(touch)
end
shootRemote:FireServer()
--//Trace
if allowTracing.Value then
--//Create
local trace = Instance.new("Part")
trace.Anchored = trace
trace.CanCollide = false
trace.Transparency = .5
trace.BrickColor = BrickColor.new("Medium blue")
trace.Material = Enum.Material.Neon
--//Calculate
local distance = (hole.CFrame.p - position).magnitude
trace.Size = Vector3.new(.25, .25, distance)
trace.CFrame = CFrame.new(hole.CFrame.p, position) * CFrame.new(0, 0, -distance/2)
trace.Parent = workspace
remotes.Oof:FireServer(hole.CFrame.p, mouse.hit.p
)
--//Clean-up
game:GetService("Debris"):AddItem(trace, 0.02)
wait(.02)
This is on a local script.
I also cast a ray on server.
If possible, Iâd like to convert to the new raycast method as I think it is smoother, but I do not understand how to.
Try using the new method, WorldRoot:RayCast allows you to filter parts using collision groups inside of the RaycastParams. Not sure if itâs possible with Ray.new.
local raycastParams = RaycastParams.new()
local origin = hole.CFrame.p
local direction = (mouse.hit.p - hole.CFrame).unit * range.Value
raycastParams.FilterDescendantsInstances = {player.Character}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.IgnoreWater = true
local raycastResult = workspace:Raycast(origin, direction, raycastParams)
local position
if raycastResult then
local touch = raycastResult.Instance
position = raycastResult.Position
hitRemote:FireServer(touch)
else
position = origin + direction
end
Something like this would work but you I feel like you need to loop everything in workspace that are non-collidable, how I do this is I put this inside a function, and check the part that has been hit if itâs set to cancollide false, if the part is not collidable I will fire again the function, something like that
local InstancePart = raycastResult.Instance -- getting the part that has been hit.
if InstancePart.CanCollide == false then -- checking if it is false.
-- do stuff
end
Yes something like that, then fire the function that is used to raycast like:
local function rayCast(origin, dir)
--put your stuff here
if hitPart.CanColide == false then -- make sure the hitpart doesn't have a humanoid in its parent
rayCast(hitPosition, CFrame.new(hitPosition, hitPosition - hitNormal).LookVector * range) -- Some bits of my old gun system
end
end
local fPart, fPosition, fNormal = workspace:FindPartOnRayWithIgnoreList(Ray, Ignore)
-- "the f in front means FIRST" --
if fPart.CanCollide == false then
Ignore = {tool.Parent; fPart}
else
Ignore = {tool.Parent}
end
local Part, Position, Normal = workspace:FindPartOnRayWithIgnoreList(Ray, Ignore)
This is a deprecated method, however It works fine.
No, I only converted your old raycast to the new API.
You have 3 options to do that:
Create an array with all CanCollide false parts in your game and set raycastParams.FilterDescendantsInstances to it. You can use workspace:GetDescendants() or CollectionService:GetTagged() (if you tag all CanCollide false parts before that, it can be done in studio edit mode with the command bar) to find all the CanCollide false parts in your game.
Instead of using the CanCollide property, make a new Collision Group which doesnât collide with Default and set all of the CanCollide false partsâ Collision Group to it.
If your raycast hits a CanCollide false part, raycast again from where the last ray ended (new origin vector). You would also have to decrease the direction vector based on how far from the last origin the ray traveled, so the rays donât go too far. Repeat this until you get a result which isnât a CanCollide false part.
The 3rd method is probably the best if your game has a lot of CanCollide false parts, but also the hardest to implement.
@Epic_2219 Hello, unfortunately I am not enough experienced to have a answer, but I would council getting all the RayCast functions, and then use them at there designed place.
And by the way, this is not working.
Is this implemented correctly?
local function fire()
--//Checks
if canShoot:InvokeServer() then
--//Initialize
--[[local SPREAD = 1000 -- set some value for it
local spreadPosition = Vector3.new(
hole.CFrame.p.X + math.random(-SPREAD, SPREAD)/1000,
hole.CFrame.p.Y + math.random(-SPREAD, SPREAD)/1000,
hole.CFrame.p.Z + math.random(-SPREAD, SPREAD)/1000
)]]
local raycastParams = RaycastParams.new()
local origin = hole.CFrame.p
local direction = (mouse.hit.p - hole.CFrame).unit * range.Value
raycastParams.FilterDescendantsInstances = {player.Character}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.IgnoreWater = true
local raycastResult = workspace:Raycast(origin, direction, raycastParams)
local position
if raycastResult then
local touch = raycastResult.Instance
position = raycastResult.Position
hitRemote:FireServer(touch)
else
position = origin + direction
end
end
end
OLD:
local function fire()
--//Checks
if canShoot:InvokeServer() then
--//Initialize
--[[local SPREAD = 1000 -- set some value for it
local spreadPosition = Vector3.new(
hole.CFrame.p.X + math.random(-SPREAD, SPREAD)/1000,
hole.CFrame.p.Y + math.random(-SPREAD, SPREAD)/1000,
hole.CFrame.p.Z + math.random(-SPREAD, SPREAD)/1000
)]]
local ray = Ray.new(hole.CFrame.p, (mouse.hit.p - hole.CFrame.p).unit * range.Value)
local touch, position = workspace:FindPartOnRay(ray, player.Character, false, true)
--//Hit detection
if touch then
hitRemote:FireServer(touch)
end
shootRemote:FireServer()
--//Trace
if allowTracing.Value then
--//Create
local trace = Instance.new("Part")
trace.Anchored = trace
trace.CanCollide = false
trace.Transparency = .5
trace.BrickColor = BrickColor.new("Medium blue")
trace.Material = Enum.Material.Neon
--//Calculate
local distance = (hole.CFrame.p - position).magnitude
trace.Size = Vector3.new(.05, .05, distance)
trace.CFrame = CFrame.new(hole.CFrame.p, position) * CFrame.new(0, 0, -distance/2)
trace.Parent = workspace
remotes.Oof:FireServer(hole.CFrame.p, mouse.hit.p
)
--//Clean-up
game:GetService("Debris"):AddItem(trace, 0.02)
wait(.02)
end
end
end
Oh, my bad. I missed a â.pâ for the direction variable. Should have been:
local direction = (mouse.hit.p - hole.CFrame.p).unit * range.Value
I only changed the top of your old code to show you how you can use the new Raycasting API with your code. The rest of the code should still work, I didnât bother copy pasting it (the shootRemote:FireServer() part and anything below).