How to make multiple raycasts easily

Hello developers

I’m doing a cooking system, it currently looks like this:

The red lines are the raycasts, and here comes the problem.

I need to make one ray in every corner of the ingredient, the thing is that i don’t know how to make more than one without making a lot of variables and configuring them all for all the ingredients because of the sizes and more.

This would be for better collisions, to detect with the rays, which is the higher ingredient to land the next on.

This is an example:

image

i need to achieve something like that.

I saw that some people uses Raycast Hitbox 4.01: For all your melee needs! to make more than one raycast easily, but i don’t know how to use that for this type of job.

This is my code:


--//Services
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")

--//Variables
local LocalPlayer = Players.LocalPlayer
local Mouse = LocalPlayer:GetMouse()
local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local CurrentCamera = workspace.CurrentCamera

local RS = game:GetService("ReplicatedStorage")

--//Controls
local Point = nil
local Clicking = false
local tweenInfo = TweenInfo.new(0.1)

--//Initialization
if game.Loaded then
	CurrentCamera.CameraType = Enum.CameraType.Scriptable
	CurrentCamera.CFrame = workspace.CamaraMostrador.CFrame
end

--//Functions


Mouse.Button1Up:Connect(function()
	
	Clicking = false
	
	if Point then
		
		
		
		local RayParams = RaycastParams.new()
		RayParams.FilterDescendantsInstances = {game.Workspace.Mostrador,game.Workspace.Baseplate}
		RayParams.FilterType = Enum.RaycastFilterType.Blacklist
		
		local NewRay = Ray.new(Point.Position,Point.CFrame.YVector * -3)
		local Result = workspace:Raycast(NewRay.Origin,NewRay.Direction)
		
		local MidPoint = NewRay.Origin + NewRay.Direction/2
		
		local Part = Instance.new("Part")
		Part.Parent = game.Workspace
		Part.Anchored = true
		Part.CanCollide = false
		Part.CanTouch = false
		Part.CanQuery = false
		Part.BrickColor = BrickColor.new("Really red")
		Part.Transparency = 0.6
		Part.Size = Vector3.new(0.1,0.1,NewRay.Direction.Magnitude)
		Part.CFrame = CFrame.lookAt(MidPoint,NewRay.Origin)
		
		local TSinfo = TweenInfo.new(0.2)
		
		local TsAnim = TweenService:Create(Point,TSinfo,{Position = Result.Position + Vector3.new(0,0.12,0)})
		TsAnim:Play()

		
		--Point.Position = Result.Position

	end
	
	
	Point = nil
	Mouse.TargetFilter = nil
	
end)

Mouse.Button1Down:Connect(function()
	if Mouse.Target and not Mouse.Target.Locked and Mouse.Target:IsA("BasePart") and Mouse.Target:FindFirstChild("Value") then
		Point = Mouse.Target
		Mouse.TargetFilter = Point
		Clicking = true
		
		RS.Sounds.GrabSound:Play()
		
		local TweenAnimation = TweenService:Create(Point, TweenInfo.new(0.2), {Position = Point.Position + Vector3.new(0, Point.Size.Y + 0.5, 0)})
		TweenAnimation:Play()
	end
end)

Mouse.Move:Connect(function()
	if Clicking == true and Point then
		local TweenAnimation = TweenService:Create(Point, tweenInfo, {Position = Mouse.Hit.Position + Vector3.new(0, Point.Size.Y + 0.5, 0)})
		TweenAnimation:Play()

		--[[
		Point.Position = Vector3.new(PosX,PosY,PosZ)
		]]
	 end
end)


(It’s a local script)

Any help is appreciated

Thank you!! :slightly_smiling_face:

2 Likes

I wrote a function that takes a part as an argument and will raycast downwards from any attachments named “RaycastAttachment” in the part, and returns a dictionary of results that are keyed by the attachments.

I took a similar approach to using RaycastHitbox with the attachments, and you can change any part of the function if necessary, such as the RaycastParams.

function raycastDownward(part)
	local results = {};
	local raycastParams = RaycastParams.new();
	raycastParams.FilterDescendantsInstances = {part};
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist;
	
	for _, attachment in next, part:GetChildren() do
		if attachment:IsA("Attachment") and attachment.Name == "RaycastAttachment" then
			local origin = attachment.WorldPosition;
			local direction = Vector3.new(0, -5, 0);
			
			results[attachment] = workspace:Raycast(origin, direction, raycastParams);
		end
	end
	
	return results;
end
2 Likes

I tried to implement it to the code like this:


--//Services
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")

--//Variables
local LocalPlayer = Players.LocalPlayer
local Mouse = LocalPlayer:GetMouse()
local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local CurrentCamera = workspace.CurrentCamera

local RS = game:GetService("ReplicatedStorage")

--//Controls
local Point = nil
local Clicking = false
local tweenInfo = TweenInfo.new(0.1)

--//Initialization
if game.Loaded then
	CurrentCamera.CameraType = Enum.CameraType.Scriptable
	CurrentCamera.CFrame = workspace.CamaraMostrador.CFrame
end

--//Functions

function raycastDownward(part)
	local results = {};
	local raycastParams = RaycastParams.new();
	raycastParams.FilterDescendantsInstances = {part};
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist;

	for _, attachment in next, part:GetChildren() do -- Line 35
		if attachment:IsA("Attachment") and attachment.Name == "RaycastAttachment" then
			local origin = attachment.WorldPosition;
			local direction = Vector3.new(0, -5, 0);

			results[attachment] = workspace:Raycast(origin, direction, raycastParams);
		end
	end

	return results;
end




Mouse.Button1Up:Connect(function()
	
	Clicking = false
	
	if Point then
		
		raycastDownward(Point)
		
		local Highest = nil
		
		-- Check highest part
		
		local Results = raycastDownward() -- Line 62
		
		for _,TheRay in pairs(Results) do
			if not Highest then
				Highest = TheRay
				continue
			end
			
			if TheRay.Instance.Position.Y > Highest.Instance.Position.Y then
				Highest = TheRay
			end
		end

		
		local TSinfo = TweenInfo.new(0.2)
		
		local TsAnim = TweenService:Create(Point,TSinfo,{Position = Highest.Position + Vector3.new(0,0.12,0)})
		TsAnim:Play()

		
		--Point.Position = Result.Position

	end
	
	
	Point = nil
	Mouse.TargetFilter = nil
	
end)

Mouse.Button1Down:Connect(function()
	if Mouse.Target and not Mouse.Target.Locked and Mouse.Target:IsA("BasePart") and Mouse.Target:FindFirstChild("Value") then
		Point = Mouse.Target
		Mouse.TargetFilter = Point
		Clicking = true
		
		RS.Sounds.GrabSound:Play()
		
		local TweenAnimation = TweenService:Create(Point, TweenInfo.new(0.2), {Position = Point.Position + Vector3.new(0, Point.Size.Y + 0.5, 0)})
		TweenAnimation:Play()
	end
end)

Mouse.Move:Connect(function()
	if Clicking == true and Point then
		local TweenAnimation = TweenService:Create(Point, tweenInfo, {Position = Mouse.Hit.Position + Vector3.new(0, Point.Size.Y + 0.5, 0)})
		TweenAnimation:Play()

		--[[
		Point.Position = Vector3.new(PosX,PosY,PosZ)
		]]
	 end
end)


But i got these errors:

The parts have the attachments with the right name

Also, i think that the problem comes when i return the “Results” variable

1 Like

You have to pass the part argument when calling the function.

1 Like