The culprit was the module script being improperly coded, I completely re-did the script and I will run you through it.
Lead Obstacle:
-->: Services
local scriptService = game:GetService("ServerScriptService")
-->: Variables
local obstacle = script.Parent
local obstacleLead = script.Parent.PrimaryPart
local obstacleProperties = require(scriptService.MainOperatingScripts.ObstacleManagement.ObstacleProperties)
local obstacleSpeed = obstacleProperties.obstacleSpeed
local obstacleFrequency = obstacleProperties.obstacleFrequency
local obstacleDecay = obstacleProperties.obstacleDecay
local decayState = 0
-->: Runs
while wait(obstacleFrequency) do
if decayState == obstacleDecay then
obstacle:Destroy()
break
end
obstacle:SetPrimaryPartCFrame(obstacle.PrimaryPart.CFrame + Vector3.new(0,0,obstacleSpeed))
decayState = decayState + 1
end
Obstacle Properties Module:
local module = {}
module.obstacleSpeed = 0.2 -- In Studs
module.obstacleFrequency = 0.001-- In Seconds
module.obstacleDecay = 600 -- In Frequency Ticks
return module
The reason I am using a module is because these obstacles are generated once every few seconds, and there are hundreds of different obstacles. So rather than having to go into each obstacle and change its mover code when I want to make a change, I can just head to settings and adjust them from there.
However let’s say I do need to edit the mover script! I have a script that handles all of the obstacles by assigning them a number and copying the mover script into the models. So each model wont have the mover script in it until the game starts. Here is that code:
Obstacle Prepper:
-->: Services
local serverStorage = game:GetService("ServerStorage")
local scriptStorage = game:GetService("ServerScriptService")
-->: Variables
local obstacleStorage = serverStorage.ObstacleStorage.Active
local baseScript = script.Parent.ObstaclePrepper.LeadObstacle
local children = obstacleStorage:GetChildren()
-->: Runs
for i, child in pairs(children)do
if child:IsA("Model") then
child.Name = i
local replicated = baseScript:Clone()
replicated.Parent = child
replicated.Disabled = false
end
end
You can see near the end, specifically here replicated.Disabled = false
that I enable the script, however that script will not run until the obstacle has been called and cloned by the Obstacle Handler because it is inside of Server Storage (which does not run scripts). As I mentioned earlier that script creates a number and assigns it to each obstacle so that the Obstacle Handler can find it easier. This also allows me to give the obstacles names that are easy to recognize in studio too.
Studio Mode: ![image](//devforum-uploads.s3.dualstack.us-east-2.amazonaws.com/uploads/original/4X/d/4/b/d4bcd68d1d47724ba651c0eb290aff6210b4c488.png)
Play Mode: ![image](//devforum-uploads.s3.dualstack.us-east-2.amazonaws.com/uploads/original/4X/3/4/2/34295b0092f7beacde8b76e4dc0d2d96eafd8219.png)
Obstacle Handler:
-->: Services
local serverStorage = game:GetService("ServerStorage")
local scriptStorage = game:GetService("ServerScriptService")
-->: Variables
local initiated = false
local obstacleStorage = serverStorage:WaitForChild("ObstacleStorage")
-->: Functions
function addPiece()
local obsID = math.random(2) --: # Of Active Obstacles.
local selected = obstacleStorage.Active:FindFirstChild(obsID)
local obstacle = selected:Clone()
obstacle.Parent = workspace
end
-->: Runs
while wait(9 --[[Interval]]) do
addPiece()
if initiated == false then --: Check If Operating As Expected.
initiated = true
print("ObstacleHandler was successfully initiated.")
end
end
This last bit is really simple, the Obstacle Handler uses math.random()
to generate a random number and then finds a model in Obstacle Storage with that number and clones it. This occurs once every 9 seconds.
Hierarchy:
![image](//devforum-uploads.s3.dualstack.us-east-2.amazonaws.com/uploads/original/4X/9/f/5/9f5cb6ac6b965f40ea63ffbf8c83fb9ca3ba30c5.png)