I’m choosing a random position and want to see if I can spawn something there. Of course, if there’s, say, a building, or maybe a mountain there, I don’t want to be able to spawn it.
I’m pretty sure there’s a Method to detect if a part is inside a Vector3, but how would I check for terrain?
My only idea is to just raycast downwards and see if it returns anything, but would that work if the random position is inside the mountain?
Either way, if there’s a better method, let me know, I guess.
I don’t know if that code would work because it is late at the time of writing this so just check it. Then you could use a modified version of this code to check
local location = --Location that was chosen in Vector3 format
if(location in badLocations) then
--Get a new location
)
Again this won’t work if you just copy and paste this and don’t change it.
local function isPointInNonEmptyTerrainCell(position: Vector3): boolean
local regionMinCorner = Vector3.new(math.floor(position.X / 4) * 4, math.floor(position.Y / 4) * 4, math.floor(position.Z / 4) * 4)
local regionMaxCorner = regionMinCorner + Vector3.new(4, 4, 4)
local region = Region3.new(minCorner, maxCorner)
local materials = workspace.Terrain:ReadVoxels(region, 4) -- a 3D array (array of arrays) of occupancies is returned as well but this code doesn't use it so I didn't make a variable for it.
return materials[1][1][1] ~= Enum.Material.Air
end
This isn’t perfectly accurate at telling whether a point is inside terrain because the terrain mesh is not necessarily entirely inside the 4x4x4 terrain cells that have an occupancy higher than 0, and it doesn’t necessarily fill a cell entirely unless the occupancy is 1.
math.floor(n / 4) * 4 where n is a number gives n rounded down to a number divisible by 4.
In the case of positive n:
n / 4 gives how many times 4 fits into n (not cecessarily an integer, for example, two and a half fours fit into ten, so if n == 10, then n / 4 gives 2.5).
math.floor(n / 4) rounds this down to an integer (this tells how many whole fours fit into n).
math.floor(n / 4) * 4 gives the highest number divisible by four that is less than or equal to n (the next number divisible by four is math.floor(n / 4) * 4 + 4, but it is larger than n).
regionMinCorner is the corner in which all coordinates are less than or equal to the corresponding coordinate in any other corner of the cube-shaped region of the terrain cell in which position is. Position is a world space point that can have any numbers as coordinates.
Terrain cell regions are 4x4x4 cubes, and the origo whose coordinates (0, 0, 0) are divisible by 4 is one cell corner (a corner of the eight cells around origo). Thus, the coordinates of all cell corners are divisible by 4 and any number divisible by 4 is a corner coordinate of some terrain cells.
A point is in a region when it’s in the space between the boundaries of the region. For a given position.X, the cell corner X coordinates (boundary X coordinates of the cell) are math.floor(position.X / 4) * 4 and math.floor(position.X / 4) * 4 + 4. Each of these corner X coordinates is the X coordinate of four corners of the cube-shaped cell region (a cube has 8 corners)). position.X is between these coordinates. When position.X is at the boundary between cells (divisible by four), the code considers it to be in the cell with higher minimum coordinate (in this case position.X and math.floor(position.X / 4) * 4 (which is regionMinCorner.X) are equal).
In short, the code creates a Region3 that contains position and contains exactly one terrain cell. Choosing a higher minimum corner coordinate than what is calculated in the code or a lower maximum corner coordinate would result in the corresponding coordinate of position being outside the region. Choosing a lower minimum corner coordinate or a higher maximum corner coordinate would cause the region to include more than one terrain cell although it would still contain the position coordinate.