PLEASE help this poor struggling soul!

I am trying to make a classic-style board game into a 3d game. My current goal is to make a system where the player can click on a boat (gray part right now) and it will then follow their mouse position over the game board. The tiles that the boat covers highlight green. There are three different sizes: 1 tile boat, 2 tile boat, 3 tile boat. This should be signified by the number of tiles lit up when the boat is hovered over them. Ideally, the boat would latch into exactly where it hypothetically would go if the player were to click when hovering over. Then they could click to place the piece in that spot. But for now im just trying (and failing) to the get basic hover functionality.

I had it half-way working by starting a renderstepping function when the player clicks on the boat, and moving the boats cframe to the players mouse.Hit.Position. This, however, caused it to not trigger the part.Touched property as it uses no physics. So I added a part inside of the boat part which I tried to make follow the boat using linearvelocity so it could trigger the tiles. However, it doesn’t move for some reason and I don’t know why.

Also, using mouse hit cframes created the problem of the mouse hit being on top of the part, and looping this overlap to make the part fly towards the screen. To fix this, I opted (with AI’s advice) to use raycasting and filter out the part from the raycast parameters. This had some annoying consequences, though, as the part no longer follows exactly where the mouse appears to be on screen, and the player can no longer click the part a second time to stop the renderstepping. Also, as seen in the video, it breaks apart terrible when interacting with multiple boats and somehow the part-flying-towards-the-screen issue returns :joy: .

The video shows how it breaks down in real time lol.
I have just begun learning to script and this is driving me crazy. After struggling a while I asked AI for help but it couldnt figure it out either haha. I’m really not sure how to fix it. Thank you for any help!

local plrs = game:GetService("Players")
local player = game:GetService("Players").LocalPlayer
local mouse = game:GetService("MouseService")
local cam = workspace:WaitForChild("Camera")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")



player.CharacterAdded:Connect(function(char)
	
	if player.Team and player.Team.Name == "Rorshack" then
cam.CameraType = Enum.CameraType.Scriptable
	local campart1 = Vector3.new(-382, 42.5, 45.5)
	local campart2 = Vector3.new(-382, 6.3, 101)
	
	cam.CFrame = CFrame.lookAt(campart1,campart2)
	char.HumanoidRootPart.CFrame = cam.CFrame * CFrame.new(0,-5,0)
	char.HumanoidRootPart.Anchored = true
	
	else
	cam.CameraType = Enum.CameraType.Scriptable
		local campart1 = Vector3.new(-382, 42.5, 154.4)
		local campart2 = Vector3.new(-382.8, 6.3, 108.6)

	cam.CFrame = CFrame.lookAt(campart1,campart2)
	char.HumanoidRootPart.CFrame = cam.CFrame * CFrame.new(0,-5,0)
	char.HumanoidRootPart.Anchored = true
	
	end
end)


local slotsFolder = workspace:FindFirstChild("Slots")
if not slotsFolder then
	return
end

local boatsFolder = workspace:FindFirstChild("Boats")
if not boatsFolder then
	return
end

local ActiveSlots = {}
local moving = false
local linearVelocity = nil
local conn = nil



local function getMouseHit(boat,raycastParams)

	local mouse = UserInputService:GetMouseLocation()
	local unitRay = cam:ScreenPointToRay(mouse.X, mouse.Y)
	local raycastResult = workspace:Raycast(unitRay.Origin, unitRay.Direction * 1000, raycastParams)
	if raycastResult then
		return raycastResult.Position
		
	end
	return nil
end

local function startMoving(boat)
	if moving then return end


	moving = true
	boat.CanCollide = false
	boat.CanTouch = false
	boat.Anchored = false

	
	local toucher = boat:FindFirstChild("Toucher")
	toucher.Anchored = false
	if not toucher then
		warn("No toucher")
	return end

	local linearVelocity = toucher.LinearVelocity
	
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude
	raycastParams:AddToFilter(boat)

	conn = RunService.RenderStepped:Connect(function()
		if not moving then
			if conn then conn:Disconnect() end
			return

		else
			local mousepos = getMouseHit(boat,raycastParams)
			local targetPos = mousepos
			local currentPos = toucher.Position
			local direction = (targetPos - currentPos)

			linearVelocity.VectorVelocity = direction.Unit * math.min(direction.Magnitude * 100, 100)

			boat.CFrame = CFrame.new(mousepos)
			task.wait(0.01)
			end
		end)
end


local function stopMoving(boat)

	local toucher = boat.Toucher
	moving = false
	if linearVelocity then
		linearVelocity:Destroy()
		linearVelocity = nil
	end
	
	if conn then
		conn = nil
	end
	
	toucher.Anchored = true
	boat.CanTouch = true
	boat.Anchored = true
end


local function BoatSetup(boat)
	if not boat:IsA("BasePart") then
		return
	end
	
	
	local clickDetector = boat:FindFirstChildOfClass("ClickDetector")
	if not clickDetector then
		clickDetector = Instance.new("ClickDetector")
		clickDetector.Parent = boat
	end
	
	clickDetector.MouseHoverEnter:Connect(function()
		boat.Color = Color3.fromRGB(91, 93, 105)
	end)
	
	clickDetector.MouseHoverLeave:Connect(function()
		boat.Color = Color3.fromRGB(163, 162, 165)
	end)


	clickDetector.MouseClick:Connect(function()
		if not moving then
			startMoving(boat)
		else
			stopMoving(boat)
		end
	end)
end




local function setupSlot(slot)
	if not slot:IsA("BasePart") then
		return
	end
	
	local clickDetector = slot:FindFirstChildOfClass("ClickDetector")
	if not clickDetector then
		clickDetector = Instance.new("ClickDetector")
		clickDetector.Parent = slot
	end
	
	local touchDebounce = false
	slot.Touched:Connect(function()
		if not touchDebounce then
			touchDebounce = true
		slot.Color = Color3.fromRGB(0, 170, 0)
		table.insert(ActiveSlots,slot)
		task.wait(0.1)
		touchDebounce = false
		else return
		end
	end)

	slot.TouchEnded:Connect(function()
		touchDebounce = false
		slot.Color = Color3.fromRGB(27, 42, 53)
		table.remove(ActiveSlots,slot)
	end)
	--clickDetector.MouseHoverEnter:Connect(function()
	--	slot.Color = Color3.fromRGB(0, 170, 0)
	--end)

	--clickDetector.MouseHoverLeave:Connect(function()
	--	slot.Color = Color3.fromRGB(27, 42, 53)
--	end)
end

-- Setup existing slots
for _, slot in slotsFolder:GetChildren() do
	setupSlot(slot)
end


-- Listen for new slots being added
slotsFolder.ChildAdded:Connect(function(child)
	setupSlot(child)
end)

for _, boat in boatsFolder:GetChildren() do
	BoatSetup(boat)
end

boatsFolder.ChildAdded:Connect(function(child)
	BoatSetup(child)
end)

Add all the boats to the raycast params filter. Generally just add the whole folder boats are parented to.

EDIT: Use a single raycast param for all the raycasts there, you use separate params for every movement, and they only exclude the piece you wanna move.

1 Like

I’m gonna separate this into 2 issues: getting the boats to snap to the grid and getting the raycast to stop hitting other boats.

Respositioning the Boats

Based on what I can glean, you’re using the position of the raycast result to determine where the boat should hover. If each square of that grid is an individual part, you could use the cframe of the instance of the raycast result to determine where the boat should hover instead. You might want to do a little bit of cframe math to make the boat hover just above the board.

With this, you can also make individual tiles turn green by just turning whatever the raycast result’s instance is to green and changing it back when the raycast result’s instance changes. As for lighting up the adjacent tiles for the longer boats, I’d just keep track of the orientation of the boat and light up the appropriate tiles manually.

Stopping Incorrect Raycasting

I would just change the filter to Include and add the board to the filter instead of each boat. This way, you won’t have to add all the other boats to the filter as well.

If you have it this way originally so that you can highlight the boats, I would go with what Purple just said (ie. add all the boats to the filter)

1 Like

@VioletElementalist @SourLemon100000

Both of these are so helpful thank you!!

It seems like the answer is often so simple but you just need a pair of eyes from the outside. That was getting really annoying, thank you for helping me through it :joy: