hey, so recently I’ve been working on a crater module, and I feel like my code is a bit awkward and messy
some problems in my module are lack of customizability, and adding more parameters will clutter and decrease readability in the function
my module is still in beta, so sorry if my code looks rlly messy
Impact crater module
local craterService = {}
local checkDistance = 8
local function typecheck(t, ...) : boolean
for _, v in {...} do
if typeof(v) ~= t then
return false
end
end
return true
end
local function smoothen(part:BasePart)
part.BackSurface = Enum.SurfaceType.Smooth
part.BottomSurface = Enum.SurfaceType.Smooth
part.FrontSurface = Enum.SurfaceType.Smooth
part.LeftSurface = Enum.SurfaceType.Smooth
part.RightSurface = Enum.SurfaceType.Smooth
part.TopSurface = Enum.SurfaceType.Smooth
end
--Service functions
function craterService:BuildCrater(
originPoint:Vector3,
rockAmount:number,
originOffset:number,
lookAt:number
)
--Building the crater
local lookatPos = originPoint - Vector3.new(0, lookAt, 0)
for i = 0, rockAmount - 1, 1 do
local angle = 360 / rockAmount
local currentCFrame = CFrame.new(originPoint) * CFrame.Angles(0, math.rad(angle * i), 0)
local offset = currentCFrame.LookVector * originOffset
local craterSizeX = 2 * originOffset / 4
local craterSizeZ = 2 * originOffset / 6
--local craterSizeY = 2 * originOffset / 4
--Positioning
local newPart = Instance.new("Part")
newPart.Position = originPoint + offset
newPart.Size = Vector3.new(craterSizeX, 2, craterSizeZ)
newPart.CFrame = CFrame.lookAt(newPart.Position, lookatPos)
newPart.Anchored = true
--Material checking
local position = newPart.Position + Vector3.new(0, 3, 0)
local direction = Vector3.new(0, -checkDistance, 0) --TEMPORARY!!
local raycastResult = workspace:Raycast(position, direction)
if raycastResult then
--Debris configuration
smoothen(newPart)
newPart.Material = raycastResult.Material
newPart.Color = raycastResult.Instance.Color
newPart.Position = raycastResult.Position
newPart.Anchored = true
newPart.Parent = workspace
else
print("Nothing was hit")
end
end
end
function craterService:Debris(
part:BasePart,
position:Vector3,
amount:number,
size:number
)
local Lmin = 12
local Lmax = 25
local Amin = 5
local Amax = 10
for i = 1, amount do
local rockDebris = Instance.new("Part")
--Replicating properties
-- !! REMEMBER TO USE MATERIAL MAP
rockDebris.Material = part.Material
rockDebris.Color = part.Color
rockDebris.Size = Vector3.new(size, size, size)
rockDebris.Anchored = false
rockDebris.Position = position + Vector3.new(0, 2, 0)
rockDebris.CanCollide = true
rockDebris.Parent = workspace
smoothen(rockDebris)
--Force decision
local mass = math.round(rockDebris:GetMass())
local linearForce = Vector3.new(math.random(Lmin, Lmax), math.random(Lmin, Lmax), math.random(Lmin, Lmax))
local angularForce = Vector3.new(math.random(Amin, Amax), math.random(Amin, Amax), math.random(Amin, Amax))
local linearImpulse = linearForce * mass
local angularImpulse = angularForce * mass
print(`Mass: {mass}`)
print(`Force: {linearForce}`)
if math.random(1, 2) == 1 then
linearForce *= Vector3.new(-1, 1, -1)
angularForce *= Vector3.new(-1, 1, -1)
linearImpulse = linearForce * mass
angularImpulse = angularForce * mass
end
print(`Linear Impulse: {linearImpulse}`)
print(`Angular Impulse: {angularImpulse}`)
rockDebris:ApplyImpulse(linearImpulse)
rockDebris:ApplyAngularImpulse(angularImpulse)
end
end
return craterService
this is what it looks like now
my goal with my crater is:
- a lot of customizability (e.g. minvelocity, maxvelocity, cratersize, craterangle, etc.)
- be able to set properties in the script beforehand, like this:
crater.MinVelo = 10
crater.MaxVelo = 50
crater.DebrisMaterial = Enum.Material.Slate
crater:BuildCrater()
- check which surface the player/object has touched (for example: if the object touches the ground, the crater will spawn on the ground, if it touches the wall, the crater will spawn on the wall)
if anybody has any suggestions, please help me out! thanks ![]()

