Help with making map generate properly

So, I’m having a… bad problem at the moment.

I’m attempting to make map generation like doors, and for ease of building rooms, I’ve opted to make the doors place themselves through code, so I can code in broken doors that cant be opened in some rooms, and some kind of enemy like Dupe in DOORS.

However, this is causing a LARGE problem, the way I’m doing this is by having a part in the room that is used for the CFrame to place a door, and through the server, I’m creating a door at said position.


function PlaceDoor(Position)
	local NewDoor = script.Door:Clone()
	NewDoor.Parent = workspace.Doors
	task.wait(1/60)
	NewDoor.Openable.Value = true
	NewDoor.PrimaryPart.CFrame = Position

	for i, v in pairs(NewDoor.PrimaryPart:GetChildren()) do
		if v.Name == 'DoorWeld' then v:Destroy() end
	end

	NewDoor.Door.Anchored = true
	NewDoor.Doorframe.Anchored = true
end

The only problem with this though is that the client and server really like to desync a LOT and for some reason, the doors don’t get placed properly on the client when running the game at lower than 60FPS.
This auto fixes itself when the part moves, but only for the part that moves.

I don’t want to add the wait as it makes room generation slower, but it needs to be there or the doors don’t appear on the client. That’s also a problem with the rooms themselves, as their primary part snaps to the doors position to make a seamless connection.

I was also thinking of making the next room generate before opening the door, but I can’t think of a way to do that without causing an infinite loop of generating rooms.


Anyway, here are screenshots of the issue.

Client:


Server:


Here is part of the function to generate a room:

function CreateRoom(Position, PossibleRooms)
	task.wait()
	if #PossibleRooms <= 0 then warn('Error generating room | No rooms were left in the table') return nil end
	print('Creating room.')
	
	if RoomGenerationAttempts['TRY'..tostring(Position.Position.X + Position.Position.Z)] == nil then
		RoomGenerationAttempts['TRY'..tostring(Position.Position.X + Position.Position.Z)] = 0
	end
	
	RoomGenerationAttempts['TRY'..tostring(Position.Position.X + Position.Position.Z)] += 1
	
	print('Attempt '..RoomGenerationAttempts['TRY'..tostring(Position.Position.X + Position.Position.Z)])
	
	local SelectedRoom = PossibleRooms[math.random(1, #PossibleRooms)]:Clone()
	local Room = SelectedRoom:Clone()

	Room.Parent = workspace.Rooms
	task.wait(0.05)
	Room.PrimaryPart.CFrame = Position
	
	Room = CheckCollisions(Room)
	
	if Room ~= nil then Room = CheckName(Room) end
	
	if Room == nil and RoomGenerationAttempts['TRY'..tostring(Position.Position.X + Position.Position.Z)] < MaxGenerationAttempts then table.remove(PossibleRooms, table.find(PossibleRooms, SelectedRoom)) return CreateRoom(Position, PossibleRooms) end
	
	if Room ~= nil then
		Lighting(Room)
		print('Room created! Attempts: '..RoomGenerationAttempts['TRY'..tostring(Position.Position.X + Position.Position.Z)]..'| Room Type: '..Room.Name)
		table.remove(RoomGenerationAttempts, table.find(RoomGenerationAttempts, 'TRY'..tostring(Position.Position.X + Position.Position.Z)))
	else
		warn('Error generating room | Ran out of attempts.')
	end
	if Room ~= nil then LastRoomName = Room.Name end
	return Room or nil
end

Still need help with this -_-

It might help to do the Parenting after all of this code has ran.

Alternatively if you DO need this to run with the task.wait, you can wrap it in task.spawn so it doesn’t hold up everything else from loading in.

Yeah, ended up doing that and made the wait 0.2 seconds as 0.016 seconds was too little and having below 60 FPS would cause the issue to happen.

This unfortunately lets you see the doors pop into existence when a new room is created, so I wouldn’t call it a solution as it just brings in another issue.