Thank you so much! Took me some time trying to figure out the offsets of each faces.
Here’s the final code:
local SS = game:GetService("ServerStorage")
local crystal = SS.Assets.RedCrystal
local part = script.Parent
local function OrientationFromFace(face: string)
local cframe = {
["up"] = CFrame.new(),
["down"] = CFrame.Angles(math.rad(180),0,0),
["right"] = CFrame.Angles(0,0,math.rad(-90)),
["left"] = CFrame.Angles(0,0,math.rad(90)),
["front"] = CFrame.Angles(math.rad(-90),0,0),
["back"] = CFrame.Angles(math.rad(90),0,0)
}
return cframe[string.lower(face)]
end
local function OffsetFromFace(part1: BasePart, part2: BasePart, face: string)
local cframe = {
["up"] = CFrame.new(0, (part2.Size.Y/2) + (part1.Size.Y/2), 0),
["down"] = CFrame.new(0, -(part2.Size.Y/2) - (part1.Size.Y/2), 0),
["right"] = CFrame.new((part2.Size.X/2) + (part1.Size.X), 0, 0),
["left"] = CFrame.new(-(part2.Size.X/2) - (part1.Size.X), 0, 0),
["front"] = CFrame.new(0, 0, -(part2.Size.Z/2) - (part1.Size.Z)),
["back"] = CFrame.new(0, 0, (part2.Size.Z/2) + (part1.Size.Z))
}
return cframe[string.lower(face)]
end
local function RandomOffset(part: BasePart, face: string)
local x,y,z = part.Size.X / 2, part.Size.Y / 2, part.Size.Z / 2
local size = {
["up"] = CFrame.new(Random.new():NextNumber(-x,x), 0, Random.new():NextNumber(-z,z)),
["down"] = CFrame.new(Random.new():NextNumber(-x,x), 0, Random.new():NextNumber(-z,z)),
["right"] = CFrame.new(0, Random.new():NextNumber(-y,y), Random.new():NextNumber(-z,z)),
["left"] = CFrame.new(0, Random.new():NextNumber(-y,y), Random.new():NextNumber(-z,z)),
["front"] = CFrame.new(Random.new():NextNumber(-x,x), Random.new():NextNumber(-y,y), 0),
["back"] = CFrame.new(Random.new():NextNumber(-x,x), Random.new():NextNumber(-y,y), 0)
}
return size[string.lower(face)]
end
local function PlaceCrystal(face: string)
local clone = crystal:Clone()
local spikeCFrame = part.CFrame * OffsetFromFace(clone, part, face) * RandomOffset(part, face) * OrientationFromFace(face)
clone.CFrame = spikeCFrame
clone.Parent = workspace
task.delay(.2, function()
clone:Destroy()
end)
end
local selections = {"front", "back", "up", "down", "left", "right"}
while task.wait(.2) do
for i = 1,5 do
PlaceCrystal(selections[Random.new():NextInteger(1, #selections)])
end
end
I just have one question, why do you need this line?
CFrame.new():ToObjectSpace(part.CFrame)
I tried it out with just
part.CFrame
and so far it works just fine? Isn’t part.CFrame
already relative to itself, or am I just not getting it?