How do I make a simple generation system like in 3008

I wanted to recreate 3008 (the roblox experience made by uglyburger0), except without the walls at the edge of the maps, since I want it to be infinite. For that I know that I have to do a chunk system, a render distance system for the players and also making sure that chunks can save and reload (as well as them being updated depending on what day it is, since in 3008, food respawns every few days).

On small issue though, I have no idea how I’m gonna achieve this, since I have no idea how generation, or chunk systems work.

Any help is appreciated.

7 Likes

Creating a chunk system is something that has personally been on my bucket list, but I haven’t gotten around to programming that quite yet. However I’ve found a multi part series explaining procedural terrain generation (with chunking) which could certainly be of use to you.

I’m positive the system can be edited/configured to your liking, and should allow you to edit how ‘chunks’ are generated; you can scrap all the terrain stuff, and just create a Part which takes up the entire chunk x and z.

As for the saving and or loading, you obviously will have to use the DatastoreService to save/load chunks. But, again, I haven’t programmed something like this yet, so that’s all the information I can really provide you with.

1 Like

Sorry for late response, but thanks for the tutorial series! One thing I’d like to ask is if you, by any chance, knew how I could implement DataStoreService into the code, since I really am very bad at this kind of thing, since I pretty much never did it before

1 Like

Well firstly, if you don’t have an already vast or well understanding of datastores, you probably shouldn’t be dwelling in something as sophisticated as a saving/loading chunk system. I’m not trying to be discouraging - I’m just being realistic.

Boast aside, to save chunks with data within them you’ll first want to save an array of chunks in a datastore. Something along the lines of this:

-- services
local datastoreService = game:GetService("DataStoreService")
local players = game:GetService("Players")

-- variables
local DATASTORE_KEY = "ChunkData/"
local DEFAULT_DATA = {}

local chunkDatabase = datastoreService:GetDataStore("ChunkDatabase")

-- functions
local function playerAdded(player: Player)
	-- guard clause to make sure the function isn't called twice on the rare occurence
	if (player:GetAttribute("LoadedInChunkData")) then return end
	
	player:SetAttribute("LoadedInChunkData", true)
	
	-- get the chunk data
	local chunkData = chunkDatabase:GetAsync(DATASTORE_KEY .. player.UserId)
	
	-- guard clause to make sure that if there's no data, it defaults to a regular table
	if (not chunkData) then chunkData = DEFAULT_DATA end
	
	print(chunkData)
end

players.PlayerAdded:Connect(playerAdded)

-- for loop to catch any players which loaded in before the script initalization
for index, player in ipairs(players:GetPlayers()) do
	playerAdded(player)
end

The output of running this code will give us an array looking something like this (of course if the data existed. It wouldn’t actually print this):

{
	{
		x = 1, -- this is the x position of the chunk
		y = 1, -- and the y position of the chunk
		metadata = {
			items = {}, -- this metadata table contains additional data such as what is contained within the chunk; chairs, tables, loose items, etc...
		},
	},
	{
		x = 2, -- this is the x position of the chunk
		y = 1, -- and the y position of the chunk
		metadata = {
			items = {}, -- this metadata table contains additional data such as what is contained within the chunk; chairs, tables, loose items, etc...
		},
	},
	..., -- and so on for however many chunks you have
}

With this data you can create chunks. You can use the metadata within each ‘chunk data’ to reconstruct the loose items, models, etc… If you don’t know how to save loose items, or models in a datastore, you can read a tutorial about serialization.

This is all I can really say because I have no idea what you want your game to look like. I don’t know if it’s multiplayer, or single player. I don’t know if you save loose items, models or the latter. The list goes on.

I don’t particularly have much time as I don’t forum post for a living, but if you have any additional questions, feel free to ask.

1 Like

Here are some basic instructions:

First you need to decide what your different levels of chunks are, and how to assign the chunks.

Once you do that, it’s pretty trivial to fill chunks with items and decorations (I’ll get to that).

Here is a chunk level schematic I designed for this fairly quickly:

If you click on the diagram it will become more detailed.

Basically, any time you want a chunk, run a “generateChunk(x, y)” function based on the details above.

If you search up “wave function collapse” there are lots of tutorials that explain how to program it in a simple way. Basically just have a list of chunks, then for each chunk a list of which chunks can go in which direction from the chunk. Find all the valid chunks for a square, then randomly pick one. Then continue all fill in all the chunks.

To save the chunks, I wouldn’t use object serialization because the memory would get out of hand fast. I would instead save only the changes to chunks, like:

  • What objects have been moved
  • Where the moved objects are
  • What objects have been added
  • What state changes have been made to objects
  • etc
2 Likes

Just wanted to know, since I still feel kinda insecure in doing it since it is my first time, the chunks that aren’t saved can just be cloned from a folder containing them all, correct?

1 Like

yes you can do that if what ur saying is what im thinking

Yep! For example, you’d probably have a model for each of the mini chunks (pillar chunks, living room decor chunk, cafeteria chunk, etc) in ServerStorage then clone them into the workspace when you need them.

One thing I forgot to consider, you can also just rotate the big 3x3 chunks once you’re done generating them, and you can rotate the mini chunks too.

I would do saving after programming generation, but for saving make sure to only save the changes. You can regenerate most of the chunk data just by generating it again with the x,y seed, so you only need to save the changes to the generated chunk.

I was thinking about making it so chunks when they generate they would have a script inside them to spawn the furniture, and once the chunk deloads, it checks if anything was changed before deloading and if yes, then the script would save that into a datastore.

Then, once generated that, will only spawn what it remembers being here.

I also had in mind to make it so any man-made structure doesn’t deload but when far enough from the player it gets anchored, to avoid it falling in the void, since i was thinking about making render distance system server-side, and then adding fog so players can’t see other chunks loading/deloading

How do you think that would go?

That should work. You get 60 data store get requests per min plus 10 per min per player, so that should be enough.

I like to store stuff on the server in compressed formats but thinking about it datastores are easier and way less restricted. Roblox has pretty good services for that (not to mention free).

Hello, I know I’m sending this kinda late, but do you know how I could make a chunk system with the wave function collapse algorithm?

Do you want to make the entire thing with the wave function collapse algorithm or just the smaller parts?

For the smaller parts/mini-chunks:

  • Loop through each of the unassigned mini-chunks in any order
    • Loop through each of the possible tiles
      • Loop through the surrounding tiles, checking if the current tile is possible
      • If the tile is possible, add it to a table
    • Once you’ve found all the tiles possible for that mini-chunk, pick one at random.
    • Apply the random attributes to that tile (color changes, random scattering of items, etc)
    • Move to the next unassigned mini-chunk

This video does a good job explaining wave function collapse:

(You don’t need to do any of the “lowest number of states” things because you shouldn’t run into any cases where you reach something impossible. The lowest number of states thing is to avoid selecting tiles that end up not fitting together.)

If you want to do it in a simple way, you can do something like this:

-- Each of your tiles get a few tags about where they can go
-- You can also use attributes in the Models for this then just make this automatically
relationsTable = {
   HorizontalStraightPathWithCouches = {"Left Entrance", "Right Entrance"},
   VerticalStraightPathWithCrates = {"Top Entrance", "Bottom Entrance"},
   TopRightCornerWithFoodArea = {"Top Entrance", "Right Entrance"},
}

Then have a loop like this (warning: pseudo code):

for miniChunkx = 1, 3:
    for miniChunkz = 1, 3:
        miniChunk = bigChunk[miniChunkx][miniChunkz]
        possibilityTable = {}
        if miniChunk is unassigned
            -- Get the requirements, would look something like {Needs = {"Right Entrance"}, CantHave = {"Top Entrance", "Left Entrance"}}
            requirements = getRequirements(bigChunk, miniChunkx, miniChunkz)
            for tile, tileReqs in pairs(relationsTable) do
                if tileIsValid(tileReqs, requirements) then
                    table.insert(possibilityTable, tile)
                end
            end
            miniChunk = selectRandom(possibilityTable)
        end
    end
end
1 Like

This is funny. I am actually attempting to make my own 3008 game too!

What I am 99% sure @uglyburger0 uses is a Procedural Generation System.

You could make a simple script that just places models in a grid, but you wouldn’t be able to have Rectangle plots that way.

There are videos of people designing Dungeon Generators on YouTube. You could modify their design to make a grid.

Then, all you would need is the Render Distance and Chunk Loading/Unloading.

Ah. I see that 3008 uses a much simpler system.

They just have square tiles surrounded in walkways then just randomly place tiles. That’s really easy to do if you’re interested in something less complex.

Yeah, the only thing is, I have no idea how to do chunk systems, I think I am starting to understand how to do the wave collapse, but my only problem is still that I don’t know how to port it into a chunk system, all I really know is that to make a chunk system I have to do the wave collapse inside a ModuleScript.

Another thing I know is that I have to check the player’s position (I want the chunks to be rendered server-side, so I want to use the player character instead of the camera)… only issue is: I don’t really know how to do that…

1 Like

We are pretty much at the same stage of being lost.

1 Like

Maybe we could use a system that multiplies the render distance value (for example 15) times the width of the plot? Only thing to really figure out is how to always render the same chunks and not generate different chunks everytime (actually, I don’t know if this issue could appear, considering the ModuleScript is only ran once, which means it shouldn’t change generation everytime, but maybe a seed system can help), and also avoid chunks overlapping from other players (since I want to load the chunks server-side)

(Sorry for late response, got busy)

1 Like

https://devforum.roblox.com/t/can-you-actually-manually-unrender-an-object/2707921/5?u=trtman33

Does that mean that if I generate the entire map at once, BUT I make it so only chunks near players have their transparency set to 1?

That means that only chunks that are (DistanceAmount) away from players will render.