I am making a combat system and have setup my hitboxes which all works fine. However I want to use raycasting just to make sure there is nothing in front of the player just to prevent damaging through walls/objects. I am trying to cast a ray from the players humanoid root part to the hit humanoids root parts and checking the ray doesn’t hit anything else other than the target but for some reason it doesn’t always print even with no wall or object in front of the player? But when I remove the raycasting code it always prints regardless which works as intended so I’m not sure what is happening and I’m fairly new to raycasting.
for i,v in pairs(hitHumanoids) do
if (v) then
local rayOrigin, rayDirection = humanoidRootPart.Position, v.PrimaryPart.Position
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {character}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.IgnoreWater = true
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
if (raycastResult) then
if (raycastResult.Instance.Parent == v) then
print(v.Name)
end
end
end
end
I’m not sure if this is the correct answer because the way you described what you want to achieve didn’t exactly map in my head, particularly which script does what, but if I understand you correctly, if you don’t want a raycast to go through a wall, you can use this script.
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local RAY_RADIUS = 1
local RAY_COLOR = BrickColor.Red()
local RAY_TRANSPARENCY = 0.5
local RAY_INTERVAL = 0 -- Ray shoot interval in seconds set it to zero for no interval
local RAY_DURATION = 0 -- How long until we stop shooting
--- function to get player hit returns a player and humanoid
local function GetPlayerHit(origin: Vector3, direction: Vector3): (Player?, Humanoid?)
local result = workspace:Raycast(origin, direction)
if result then
local character, humanoid = result.Instance, nil
--- idk if this is necesery but just repeat get parent until we have the character
repeat
character = character.Parent
humanoid = character and character:FindFirstChild("Humanoid")
until character == nil or humanoid
if not character or not humanoid then
return
end
return Players:GetPlayerFromCharacter(character), humanoid
end
return nil, nil -- to silent the warning
end
local function DrawRay(origin: Vector3, direction: Vector3)
local part = Instance.new("Part")
part.Name = "Ray"
part.Anchored = true
local result = workspace:Raycast(origin, direction)
local len = (origin - (origin + direction)).Magnitude
if result then
len = (origin - result.Position).Magnitude
end
part.Size = Vector3.new(RAY_RADIUS, RAY_RADIUS , len)
part.Material = Enum.Material.SmoothPlastic
part.BrickColor = RAY_COLOR
part.Transparency = RAY_TRANSPARENCY
part.CFrame = CFrame.new(origin, direction) * CFrame.new(0, 0, -len*0.5)
part.Parent = workspace
return part
end
--- Ray loop
do
local part = script.Parent
local lastRayPart = nil
local timePassed = RAY_INTERVAL
RunService.Heartbeat:Connect(function(dt: number)
if lastRayPart and lastRayPart.Parent then -- if debris is to slow
lastRayPart:Destroy()
end
timePassed += dt
if timePassed < RAY_INTERVAL then -- Return if its not time yet
return
end
if timePassed > RAY_INTERVAL + RAY_DURATION then -- Reset the time passed after the duration has been reached
timePassed = 0
end
local origin = part.Position
local direction = part.CFrame.LookVector*1000
lastRayPart = DrawRay(origin, direction)
local player, humanoid = GetPlayerHit(origin, direction)
if player then -- do something example
humanoid:TakeDamage(50)
end
end)
end
This is a common mistake with raycasts. Raycast direction IS NOT the position of the target part.
Direction is the vector3 transformed to the raycast orgin object space.
For example, Vector 0,10,0 will not direct the ray to the 10 studs above the middle of the map, but rather 10 studs above the humanoid that shot the ray!
Furthermore, if you want the ray to always hit the target humanoid, it is a good idea to make it a bit longer than the distance to the target.
Here is the code:
local rayOrigin = humanoidRootPart.Position
local rayDirection = CFrame.lookAt(rayOrigin, v.PrimaryPart.Position).LookVector
-- now that you have a proper direction vector, it size is only 1 stud. You need to multiply it by the distance to the target humanoid, and even a bit more as mentioned
rayDirection *= (rayOrigin - v.PrimaryPart.Position).Magnitude
rayDirection *= 1.1 -- optional, make sure the ray always hits the target humanoid