Problems with a moving scene system

  1. What do you want to achieve? Keep it simple and clear!
    A moving scene system.

  2. What is the issue? Include screenshots / videos if possible!
    During the movement spaces are created between the chunks of the scene, giving an undesired result.

robloxapp-20220714-1508475.wmv (450,7 KB)

Also, because the start and end parts move relative to the player’s position, since my map will be a very long train and I don’t want to have so many moving chunks, it further distorts the movement of the chunks when the player it starts to move.

robloxapp-20220714-1516479.wmv (3,4 MB)

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I have tried everything, this started with the interpolation service but then I decided that it would be much better with Lerp, unfortunately I have no idea how to fix this. I did not find anything similar in the forum, just a post that had no response from anyone.

I do not ask for any code, just the way or what I could try to solve this, since I have no idea how to do it.

Here I leave the code of the main module script.

local Functions = {}

local Presets = game.ReplicatedStorage.Scenary
local Scenary_Folder = game.Workspace.Scenary
local Place_Holders = Scenary_Folder.Place_Holders
local Objects = Scenary_Folder.Objects
local Debug = require(script.Parent.Debug)
local Tables = require(script.Parent.Tables)
local Run_Service = game:GetService("RunService")
local Need_To_Wait = false
local Debug_ = false

function Functions:Return_Dictionary(ID)
	local Dictionary = Tables.Active_Assets[ID]
	return Dictionary
end

function Functions:Weld(Model)
	local PrimaryPart = Model.PrimaryPart

	for i, v in pairs(Model:GetChildren()) do
		if v ~= PrimaryPart and v:IsA("BasePart") then
			if Need_To_Wait then wait() end	
			local Weld = Instance.new("Weld")
			Weld.Parent = PrimaryPart
			Weld.Part0 = PrimaryPart
			Weld.Part1 = v
			Weld.C0 = PrimaryPart.CFrame
			Weld.C1 = v.CFrame
			Weld.Name = v.Name
		end
	end
end

function Functions:Main(ID)
	local Signal;
	local Dictionary = Functions:Return_Dictionary(ID)
	local Config = Dictionary["Config"]
	local Sync = {
		["ID"] = false;
		["Tick_S"] = false;
	}
	
	local Start = Config["Start_Point"]
	local End = Config["End_Point"]
	
	local Speed = Config["Speed"]
	local Quantity = Config["Chunks"]
	
	local Distance_From_Each = Config["Distance_From_Each"]
	local Distance_Between = -(Start.Position.Z - End.Position.Z)
	
	local function Synchronize(Need_Adjust, Run_Id)
		for i = 1, Quantity do
			Speed = Config["Speed"]
			local Chunk = Dictionary["Chunk"..i]

			local Last_CFrame = Chunk["Last_CFrame"]
			local Work_Speed = Chunk["Work_Speed"]
			local Speed = Config["Speed"]

			if Need_Adjust then
				local Distance_From_Start = (Last_CFrame.Position.Z - Start.Position.Z)
				local Alpha =  Distance_From_Start/Distance_From_Each
				local Result = (Alpha * Speed)/1

				--For debugging --
				if Debug_ and Work_Speed ~= false then
					local info = Speed - Result
					local Percent = math.floor((Alpha * 100)/1)
					local value1 = (math.floor(Work_Speed * 100))/100
					local value2 = (math.floor(Result * 100))/100
					local value3 = (math.floor(info * 100))/100

					Debug:Print("Chunk: "..i.."\nPercent complete: "..Percent.."%\nOriginal Speed: "..value1.."\nNew Speed: "..value3.."\nOur math give us: "..value2)
				end

				Chunk["Work_Speed"] = Speed - Result
			end

			if not Need_Adjust then Chunk["Work_Speed"] = Speed end
			if Debug_ and Work_Speed ~= false then Debug:Print("Chunk: "..i.." Time to complete: "..Work_Speed) end

			Chunk["Our_Speed"] = Speed
			Chunk["Initial"] = Last_CFrame

			if Sync["ID"] == Run_Id then
				Chunk["Tick_S"] = Sync["Tick_S"]
				Config["Tick_S"] = Sync["Tick_S"]
			else
				local The_Tick = tick()
				Chunk["Tick_S"] = The_Tick
				Config["Tick_S"] = The_Tick
				Sync["ID"] = Run_Id
				Sync["Tick_S"] = The_Tick
			end
		end
	end
	
	local function Get_Chunk(i, Next)
		if Next then
			if i == Quantity then
				return 1
			else
				return i + 1
			end
		else
			if i == 1 then
				return Quantity
			else
				return i - 1
			end
		end
	end
	
	Signal = Run_Service.RenderStepped:Connect(function()
		local Run_Id = game.HttpService:GenerateGUID(false)
		Speed = Config["Speed"]
		
		if Config["Started"] == false then
			Config["Started"] = true
			local Alpha;
			local The_Tick = tick()
			
			for count = Quantity - 1, 0, -1 do
				Alpha = (count*1)/Quantity
				local i = count + 1
				Functions:Create(ID, i)
				Dictionary["Chunk"..i]["Alpha"] = Alpha
				Dictionary["Chunk"..i]["Our_Speed"] = Speed
				Dictionary["Chunk"..i]["Tick_S"] = The_Tick
				local Model = Dictionary["Chunk"..i]["Model"]
				
				Model.PrimaryPart.CFrame = Start.CFrame:Lerp(End.CFrame, Alpha)
				
				Dictionary["Chunk"..i]["Last_CFrame"] = Model.PrimaryPart.CFrame
				Dictionary["Chunk"..i]["Initial"] = Model.PrimaryPart.CFrame
				Config["Tick_S"] = The_Tick
			end
		end
		
		for i = 1, Quantity do
			local Chunk = Dictionary["Chunk"..i]
			local Last_Alpha = Chunk["Alpha"]
			local Started_At = Config["Tick_S"]
			local Last_Tick = Chunk["Tick_S"]
			local Model = Chunk["Model"]
			local Work_Speed = Chunk["Work_Speed"]
			local Our_Speed = Chunk["Our_Speed"]
			local Initial = Chunk["Initial"]
			local Last_CFrame = Chunk["Last_CFrame"]
			
			if Work_Speed == false or Speed ~= Our_Speed or Last_Tick ~= Started_At then
				Synchronize(true, Run_Id)
				Last_Alpha = Chunk["Alpha"]
				Started_At = Config["Tick_S"]
				Last_Tick = Chunk["Tick_S"]
				Model = Chunk["Model"]
				Work_Speed = Chunk["Work_Speed"]
				Our_Speed = Chunk["Our_Speed"]
				Initial = Chunk["Initial"]
			end
			
			if Speed > 0 then
				local Our_Alpha = math.min((tick() - Started_At) / Work_Speed, 1)
				local Distance_From_Start = (Last_CFrame.Position.Z - Start.Position.Z)
				local Alpha =  Distance_From_Start/Distance_From_Each
				Chunk["Alpha"] = Alpha
				
				Last_CFrame = Initial:Lerp(End.CFrame, Our_Alpha)
				
				if Model then Model.PrimaryPart.CFrame = Last_CFrame end
				
				Chunk["Last_CFrame"] = Last_CFrame
				
				if Our_Alpha == 1 then
					warn("Chunk: "..i.." finished\n")
					Model:Destroy()
					Functions:Create(ID, i)
					
					local num = Get_Chunk(i, true)
					local next_chunk = Dictionary["Chunk"..num]
					Chunk["Alpha"] = 0
					Chunk["Initial"] = next_chunk["Last_CFrame"] - Vector3.new(0, 0, next_chunk["Model"].PrimaryPart.Size.Z)
					Chunk["Work_Speed"] = false
					Chunk["Last_CFrame"] = next_chunk["Last_CFrame"] - Vector3.new(0, 0, next_chunk["Model"].PrimaryPart.Size.Z)
					
					local Model = Chunk["Model"]
					if Model then Model.PrimaryPart.CFrame = (next_chunk["Last_CFrame"] - Vector3.new(0, 0, next_chunk["Model"].PrimaryPart.Size.Z)):Lerp(End.CFrame, 0) end
				end
			else
				Model.PrimaryPart.CFrame = Start.CFrame:Lerp(End.CFrame, Last_Alpha)
			end
		end
	end)
	
	script.Stop.Event:Connect(function(Call_ID)
		if Call_ID == ID then
			Signal:Disconnect()
		end
	end)
end

function Functions:Create(ID, Chunk_Number)
	local I_D = Functions:Return_Dictionary(ID)
	local Type = I_D["Config"]["Type"]
	local Model_OBJ;
	
	local function Find_Priority()
		if Tables.Priority_List[ID] then
			if Tables.Priority_List[ID][1] then
				local Access = Tables.Priority_List[ID][1]
				table.remove(Tables.Priority_List[ID], 1)
				return true, Access
			end
		end
		return false
	end
	
	local Finded, Model = Find_Priority()
	
	if Finded then
		Model_OBJ = Model:Clone()
	else
		local Presets_T = Presets[Type]:GetChildren()
		local Random_ = math.random(1, #Presets_T)
		local Model = Presets_T[Random_]
		Model_OBJ = Model:Clone()
	end
	
	Functions:Weld(Model_OBJ)
	Model_OBJ.Parent = Objects
	
	local Dictionary = Functions:Return_Dictionary(ID)
	
	Model_OBJ:SetAttribute("Number", Chunk_Number)
	Model_OBJ.Name = ("Chunk"..Chunk_Number)
	Dictionary["Chunk"..Chunk_Number]["Model"] = Model_OBJ
end

function Functions:New(Start)
	local Type_Of = Start:GetAttribute("Type")
	local Models_P = Presets[Type_Of].Model.PrimaryPart
	local Distance_Each = -(Start.Position.Z - Start.End.Position.Z)
	local Models_Quantity = math.floor(Distance_Each/Models_P.Size.Z)
	
	local ID = game.HttpService:GenerateGUID(false)
	local Export_Table = {}
	Export_Table["Config"] = {
		["Start_Point"] = Start;
		["End_Point"] = Start.End;
		["Speed"] = 0;
		["Chunks"] = Models_Quantity;
		["Distance_From_Each"] = Distance_Each;
		["Type"] = Type_Of;
		["Tick_S"] = false;
		["Started"] = false;
	}
	
	for i = 1, Models_Quantity do
		Export_Table["Chunk"..i] = {
			["Model"] = false;
			["Alplha"] = false;
			["Last_CFrame"] = false;
			["Tick_S"] = false;
			["Work_Speed"] = false;
			["Our_Speed"] = false;
			["Initial"] = false;
		}
	end
	
	Tables.Active_Assets[ID] = Export_Table
	
	Functions:Main(ID)
	
	return ID
end

function Functions:Cancel(ID)
	script.Stop:Fire(ID)
end

function Functions:Speed(ID, New_Speed)
	local Dictionary = Functions:Return_Dictionary(ID)
	Dictionary["Config"]["Speed"] = New_Speed
end

function Functions:Add_Priority(ID, Models)
	local function Add()
		for i, v in pairs(Models) do
			table.insert(Tables.Priority_List[ID], v)
		end
	end
	
	if Tables.Priority_List[ID] then
		Add()
	else
		Tables.Priority_List[ID] = {}
		Add()
	end
end

return Functions

And here I attach a file of the place so you can try it without problems.

Scenary.rbxl (46,0 KB)

Thanks in advance,

Bruno