How to know what material terrain is with mouse target

So I have a game where you place units such as a tank or a battleship. The map is made out of roblox terrain. I want to place the battleship only in the water, and tanks only on land.

checkCollision() is called on renderstepped. Everytime it is called I need to check to see if the mouses target is terrain. If it is I need to know if it is on water, or on non water. How would I go about that?

1 Like

The Mouse API is considered legacy and has been largely superseded by better alternatives, such as UserInputService and ContextActionService.

This function replicates the behaviour of Mouse.Target using the newer API members provided to us:

local workspaceService = game:GetService("Workspace")
local userInputService = game:GetService("UserInputService")

local currentCamera = workspaceService.CurrentCamera

-- Instance<BasePart>?, Vector3, Vector3, EnumItem<Material> getMouseHit()
local function getMouseHit()
    local mouseLocation = userInputService:GetMouseLocation()
    local viewportPointRay = currentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    local extendedRay = Ray.new(viewportPointRay.Origin, viewportPointRay.Direction * 1000)
    
    return workspaceService:FindPartOnRay(extendedRay)
end

The first result returned from a call to this function is a BasePart (including possibly the Terrain object) or nil, if nothing was hit. The fourth result is the material of the BasePart or terrain cell hit. You can use these to your advantage:

local hit, position, normal, material = getMouseHit()
if hit and hit:IsA("Terrain") then
    print("Terrain material is " .. tostring(material))
end
13 Likes

It turns out Camera:ViewportPointToRay should be used over ScreenPointToRay for this, otherwise the GUI inset is accounted for. I’ve edited the code appropriately.

1 Like