You can write your topic however you want, but you need to answer these questions:
-
What do you want to achieve? Keep it simple and clear!
I want to make that the left Turn direction is correct (btw I am pretty sure i next up the name for the models, but that shouldn’t really matter and plus I am to lazy to fix them) -
What is the issue? Include screenshots / videos if possible!
-
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I have tried using just on turnModel and both didn’t work, rn only the model named rightTurn works. Tried usingmath.rad(-90)
for theLEFT_TURN_ANGLE
but it didn’t change much
This is the rightTurnModel
local module = {}
--[[
Constants and probabilities
LEFT_TURN_ANGLE : Angle (in radians) for a left turn.
RIGHT_TURN_ANGLE : Angle (in radians) for a right turn.
TURN_CHANCE : Probability that a turn occurs when allowed.
TURN_COOLDOWN : Number of straight segments forced after a turn.
]]
local LEFT_TURN_ANGLE = math.rad(90)
local RIGHT_TURN_ANGLE = math.rad(-90)
local TURN_CHANCE = 0.5
local TURN_COOLDOWN = 10
local TemplateModels = {
initial = roadPrefabs:WaitForChild("Road_Initial"),
straight = roadPrefabs:WaitForChild("Road_Straight"),
leftTurn = roadPrefabs:WaitForChild("Road_LeftTurn"),
rightTurn = roadPrefabs:WaitForChild("Road_RightTurn")
}
--[[
alignModel(newModel, snapCFrame)
Aligns the newModel so that its BackConnector is exactly at snapCFrame.
This ensures each road segment attaches to the previous segment's FrontConnector.
]]
local function alignModel(newModel, snapCFrame)
local backConnector = newModel:WaitForChild("BackConnector")
local offset = backConnector.CFrame:ToObjectSpace(newModel.PrimaryPart.CFrame)
newModel:SetPrimaryPartCFrame(snapCFrame * offset)
end
--[[
spawnSegment(templateType, snapCFrame, overridePOI)
Creates a physical road segment of the specified templateType
and snaps its BackConnector to snapCFrame.
Arguments:
templateType (string) : "initial", "straight", "leftTurn", or "rightTurn"
snapCFrame (CFrame) : The position/orientation for the segment's BackConnector
overridePOI (bool) : Whether to force a point of interest on this segment
Returns:
table {
model : The spawned Model
type : The templateType
hasPOI : Whether the segment contains a POI
frontCFrame : CFrame of the segment's FrontConnector
finish2D : { x, y } 2D position of FrontConnector (for path logic)
}
]]
function module.spawnSegment(templateType, snapCFrame, overridePOI)
local templateModel = TemplateModels[templateType]
if not templateModel then
error("Unknown template type: " .. tostring(templateType))
end
local newModel = templateModel:Clone()
newModel.Parent = workspace.Roads
-- Align the new road piece
alignModel(newModel, snapCFrame)
local frontConnector = newModel:WaitForChild("FrontConnector")
local frontPos = frontConnector.Position
local finish2D = { x = frontPos.X, y = frontPos.Z }
local hasPOI = overridePOI or (math.random() < 0.2)
local segment = {
model = newModel,
type = templateType,
hasPOI = hasPOI,
frontCFrame = frontConnector.CFrame,
finish2D = finish2D
}
return segment
end
--[[
getRotationChange(templateType)
Returns how much we rotate the direction (in radians) for each segment type.
"leftTurn" => +LEFT_TURN_ANGLE
"rightTurn" => -RIGHT_TURN_ANGLE
"straight" => 0
"initial" => 0
]]
local function getRotationChange(templateType)
if templateType == "leftTurn" then
return LEFT_TURN_ANGLE
elseif templateType == "rightTurn" then
return -RIGHT_TURN_ANGLE
else
return 0
end
end
--[[
generateRandomRoad(start2D, direction, numSegments)
Generates a sequence of road segments in 3D space, starting from a given
2D coordinate (start2D) at a certain direction. The result is numSegments
segments (including the initial one). Periodically spawns turns based on
TURN_CHANCE, with a cooldown period that forces straight segments after a turn.
Arguments:
start2D : { x, y } initial 2D point
direction : (number) heading in radians
numSegments: (number) how many total segments to spawn
Returns:
segments : table of spawned segment data
]]
function module.generateRandomRoad(start2D, direction, numSegments)
local segments = {}
local cooldown = 0
local function getSnapCFrame(pos2D, dir)
return CFrame.new(pos2D.x, 0, pos2D.y) * CFrame.Angles(0, dir, 0)
end
local segType = "initial"
local snapCFrame = getSnapCFrame(start2D, direction)
local segment = module.spawnSegment(segType, snapCFrame, true)
table.insert(segments, segment)
segment.model.Name = string.format("%s_Segment_%d", segType, 1)
-- Update the 2D position and direction for the next piece
local current2D = segment.finish2D
local currentDirection = direction + getRotationChange(segType)
-- Generate subsequent segments
for i = 2, numSegments do
if cooldown > 0 then
segType = "straight"
cooldown -= 1
else
if math.random() < TURN_CHANCE then
segType = (math.random() < 0.5) and "leftTurn" or "rightTurn"
cooldown = TURN_COOLDOWN
else
segType = "straight"
end
end
snapCFrame = getSnapCFrame(current2D, currentDirection)
local newSeg = module.spawnSegment(segType, snapCFrame)
table.insert(segments, newSeg)
newSeg.model.Name = string.format("%s_Segment_%d", segType, i)
-- Update to next
current2D = newSeg.finish2D
currentDirection = currentDirection + getRotationChange(segType)
end
generationFinished:Fire(segments)
return segments
end
return module
Thanks for the help