Get CellMaterial of terrain region

I want to get the CellMaterial of a smooth terrain region, but using Terrain::ReadVoxels is only returning “Enum.Material.Slate” no matter which CellMaterial the region is. I also thought Enum.Material was for BaseParts except for Terrain, which has me scratching my head.

Is this intended? I don’t see any other way to get CellMaterial from smooth terrain, so if someone could point me in the right direction that’d be great. Thanks.

Alright, I managed to find Terrain::GetCell but it appears deprecated without a successor, and it’s also - from what I can tell using it - rather unreliable.

Does anyone know if there’s either a better way or a better way coming soon?

I tried Terrain:ReadVoxels() and it printed correct materials. How exactly are you getting the material? Do you have a 4x4x4 stud gridaligned region that you give to the ReadVoxels function or do you do it differently?

I copy/pasted the code from here but was reading a 2x2x2 region (specifically, directly in front of my characters head). Was trying to detect Enum.CellMaterial.Water but the ‘materials’ table only contained Enum.Material.Slate. I was scratching my head because no parts contain that material in my game

Could you show the code you use to create the region?

The original code is deleted, but it was along the lines of

local cast = (head.CFrame * CFrame.new(0, 0, (-head.Size.Z / 2) - 0.15)).p;
local ray = workspace:Raycast(head.Position, cast);
local offset = Vector3.new(1.5, 1.5 1.5);
local ray_pos = ray.Position;
local region = Region3.new(ray_pos - offset, ray_pos + offset):ExpandToGrid(4);
-- then readvoxels w/ region

I imagine if I messed up anywhere it’d be creating the region because the raycast works, but it doesn’t explain why I wasn’t getting an Enum.CellMaterial value back. How is Enum.Material useful when reading smooth terrain?

I made a function that you can use to create a gridAligned, 4x4x4 stud region. The region can then be given to :ReadVoxels(). I think you could do something like this.

local function round(n, divBy)
    local mod = n % divBy
    if mod < divBy/2 then
        return n-mod
    else return n+(divBy-mod)
    end
end

local function getCellCenter(pos)
    local xm, ym, zm = pos.X < 0 and -1 or 1, pos.Y < 0 and -1 or 1, pos.Z < 0 and -1 or 1
    local vectorToRound = Vector3.new(math.abs(pos.X), math.abs(pos.Y), math.abs(pos.Z))-Vector3.new(2, 2, 2)
    local positiveCenter = Vector3.new(round(vectorToRound.X, 4), round(vectorToRound.Y, 4), round(vectorToRound.Z, 4))+Vector3.new(2, 2, 2)
    local actualCenter = positiveCenter*Vector3.new(xm, ym, zm)
    return actualCenter
end

local function make4x4x4GridRegion(pos)
    local cellCenter = getCellCenter(pos)
    return Region3.new(cellCenter-Vector3.new(2, 2, 2), cellCenter+Vector3.new(2, 2, 2))
end

local cast = -- try giving this the same value you gave it before, it might work
local region = make4x4x4GridRegion(cast)
-- use ReadVoxels with the region