The title explains it all. It would prefer be generating in a grid or based on how large the part will be, and be something similar to the video. Also preferrably client-sided and also removes parts that are out of range.
thanks in advance!
The title explains it all. It would prefer be generating in a grid or based on how large the part will be, and be something similar to the video. Also preferrably client-sided and also removes parts that are out of range.
You can make a big part and place it in ReplicatedStorage. Then you can make a serverscript(or a localscript) so it will appear below you. Below script is just an example. You can customize if you’d like.
local instance = game.ReplicatedStorage.Instance
game.Players.PlayerAdded:Connect(function(plr)
local char = plr.CharacterAdded:Wait()
local root = char:WaitForChild("HumanoidRootPart")
-- Add code here that detects if the character is going towards the part's end
local clonedInstance = instance:Clone()
clonedInstance.Parent = workspace
clonedInstance.Position = Vector3.new(root.Position.X, root.Position.Y - 4, root.Position.Z) -- Note that "- 4" is just an example. You can set it to what you want.end
the thing is i don’t know how to check if the player is near the end of a part. Although this might work, I want it to generate parts on a grid and remove them when the player walks away from them. Putting the part’s position on the player would not work for this.
Hello there!
If you want to create a grid you could do it chunk by chunk.
local GridSize = 4
local ChunkSize = 16
local function GenerateChunk(At)
local ChunkCordinates = At * ChunkSize
local StandingChunk
local OldChunk = Vector3.Zero
for i = 0, ChunkSize^2, 1 do
local Folder = instance.new("Folder")
Folder.Parent = Workspace --Create a Chunks Folder
local Floor = Instance.new("Part")
Floor.Size = Vector3.new(GridSize, GridSize, GridSize)
Floor.Parent = Workspace -- Crate the folder .Folder
Floor.Position = ChunkCordinates + Vector3.new((i % ChunkSize) * GridSize, 0, (math.floor(i / ChunkSize)) * Grid)
Floor.Name = toString(i) --Optional
end
Now to detect the player position to generate it near you could do
local Players = game:GetService("Players")
local player = Players.LocalPlayer
repeat task.Wait(1) until player.Character
local Character = player.Character
local Root = Character.HumanoidRootPart
local RenderDistance
Root:GetPropertyChangesSignal("Position"):Connect(function()
StandingChunk = math.floor(Root.Position / ChunkSize)
if StandingChunk ~= OldChunk then
for i = 0, RenderDistance^2, 1 do
GenerateChunk(StandingChunk + Vector3.new(i % RenderDistance, 0, math.floor(i / RenderDistance))
end
end
OldChunk = StandingChunk
end)
I think this Whould work. To delete the chunks is more complex and i’ll help you in a minute, i need to go. But basically you can add a table with the generated cords and check if those cords are further than the render distance, then delete the chunk
I hope it helps
is there a way i can generate multiple chunks at a time? if not then this is already pretty good!
Im back!
Just set the render distance to the size you want!
It’ll generate it around you
But there’s a tiny problem, the script right now generates even on top of existing chunks.
Do you want help solving that?
sorry, im not very experienced
Me neither! There are probably bether ways of doing it.
But just learn a bit every day and you’ll get far!
If you want me to explain the script feel free to ask
Let’s try to solve this
Firstly we need to save the loaded chunks informations in a table
local GridSize = 4
local ChunkSize = 16
local Loaded = {} --Table with the chunks
local function GenerateChunk(At)
local ChunkCordinates = At * ChunkSize
local StandingChunk
local OldChunk = Vector3.Zero
for i = 0, ChunkSize^2, 1 do
local Folder = instance.new("Folder")
Folder.Parent = Workspace --Create a Chunks Folder
table.add(Loaded, (toString(At.X) .. toString(At.Z)), Folder)
-- Here I added on the table an item (The chunck) with the name being the coordinates of the chunck
local Floor = Instance.new("Part")
Floor.Size = Vector3.new(GridSize, GridSize, GridSize)
Floor.Parent = Workspace -- Crate the folder .Folder
Floor.Position = ChunkCordinates + Vector3.new((i % ChunkSize) * GridSize, 0, (math.floor(i / ChunkSize)) * Grid)
Floor.Name = toString(i) --Optional
end
Now we will check if the coordinates that we wamt the chunck to generate are already ocupied
`if table.find(Loaded, (toString(At.X … toString(At.Z)), 1) ~= nil then return end
–if it’s occupied then leave the function`
Im still trying to figure out how to delete the chunks, once i discover it i’ll tell you
Here’s the entire code, hope it works
local Players = game:GetService("Players")
local player = Players.LocalPlayer
repeat task.Wait(1) until player.Character
local Character = player.Character
local Root = Character.HumanoidRootPart
--You can play with these values as you want!
local RenderDistance = 3
local GridSize = 4
local ChunkSize = 16
-- ;)
local Loaded = {} --Table with the chunks
local function GenerateChunk(At)
local ChunkCordinates = At * ChunkSize
local StandingChunk
local OldChunk = Vector3.Zero
for i = 0, ChunkSize^2, 1 do
if table.find(Loaded, (toString(At.X .. toString(At.Z)), 1) ~= nil then return end
local Folder = instance.new("Folder")
Folder.Parent = Workspace --Create a Chunks Folder
table.add(Loaded, (toString(At.X) .. toString(At.Z)), Folder)
local Floor = Instance.new("Part")
Floor.Size = Vector3.new(GridSize, GridSize, GridSize)
Floor.Parent = Workspace -- Crate the folder .Folder
Floor.Position = ChunkCordinates + Vector3.new((i % ChunkSize) * GridSize, 0, (math.floor(i / ChunkSize)) * Grid)
Floor.Name = toString(i) --Optional
end
Root:GetPropertyChangesSignal("Position"):Connect(function()
StandingChunk = math.floor(Root.Position / ChunkSize)
if StandingChunk ~= OldChunk then
for i = 0, RenderDistance^2, 1 do
GenerateChunk(StandingChunk + Vector3.new(i % RenderDistance, 0, math.floor(i / RenderDistance))
end
end
OldChunk = StandingChunk
end)
I think I found a way to delete the chunks! (Haven’t tested it yet)
local Distance = math.ceil(RenderDistance / 2)
for i = 0, Distance^2, 1 do
local Target = StandingChunk + Vector3.new(-Distance + i % Distance, 0, -Distance + math.floor(i / Distance))
local X = Target.X - StandingChunk.X
local Z = Target.Z - StandingChunk.Z
if X > -Distance and X < Distance then
if Z > -Distance and Z < Distance then
Table[toString(Target.X) .. toString(Target.Z)]:Destroy
end
end
end
Here is the updated code, tell me if it works
local Players = game:GetService("Players")
local player = Players.LocalPlayer
repeat task.Wait(1) until player.Character
local Character = player.Character
local Root = Character.HumanoidRootPart
--You can play with these values as you want!
local RenderDistance = 3
local GridSize = 4
local ChunkSize = 16
-- ;)
local Loaded = {} --Table with the chunks
local function GenerateChunk(At)
local ChunkCordinates = At * ChunkSize
local StandingChunk
local OldChunk = Vector3.Zero
for i = 0, ChunkSize^2, 1 do
if table.find(Loaded, (toString(At.X .. toString(At.Z)), 1) ~= nil then return end
local Folder = instance.new("Folder")
Folder.Parent = Workspace --Create a Chunks Folder
table.add(Loaded, (toString(At.X) .. toString(At.Z)), Folder)
local Floor = Instance.new("Part")
Floor.Size = Vector3.new(GridSize, GridSize, GridSize)
Floor.Parent = Workspace -- Crate the folder .Folder
Floor.Position = ChunkCordinates + Vector3.new((i % ChunkSize) * GridSize, 0, (math.floor(i / ChunkSize)) * Grid)
Floor.Name = toString(i) --Optional
end
Root:GetPropertyChangesSignal("Position"):Connect(function()
StandingChunk = math.floor(Root.Position / ChunkSize)
if StandingChunk ~= OldChunk then
for i = 0, RenderDistance^2, 1 do
GenerateChunk(StandingChunk + Vector3.new(i % RenderDistance, 0, math.floor(i / RenderDistance))
local Distance = math.ceil(RenderDistance / 2)
for i = 0, Distance^2, 1 do
local Target = StandingChunk + Vector3.new(-Distance + i % Distance, 0, -Distance + math.floor(i / Distance))
local X = Target.X - StandingChunk.X
local Z = Target.Z - StandingChunk.Z
if X > -Distance and X < Distance then
if Z > -Distance and Z < Distance then
Table[toString(Target.X) .. toString(Target.Z)]:Destroy
end
end
OldChunk = StandingChunk
end)
Hey again!
About the previous script. I was testing it and it didn’t work well, lol. Sry about that
i’m tring to fix it, but I haven’t been able to delete the chunks yet, but here is the updated code.
local Players = game:GetService("Players")
local player = Players.LocalPlayer
repeat task.wait(1) until player.Character
local Character = player.Character
local Humanoid = Character.Humanoid
local Root = Character.HumanoidRootPart
--You can play with these values as you want!
local RenderDistance = 3
local GridSize = 4
local ChunkSize = 16
-- ;)
local Loaded = {} --Table with the chunks
local Moving
local Checking = false
local StandingChunk
local OldChunk = Vector3.Zero
local ChunkSpace = ChunkSize * GridSize
local function GenerateChunk(At)
if Loaded[(tostring(At.X) .. tostring(At.Z))] ~= nil then return end
local ChunkCordinates = At * ChunkSpace
print(At, Loaded, ChunkCordinates)
local Folder = Instance.new("Folder")
Folder.Parent = workspace.Chunks
for i = 0, ChunkSize^2 -1, 1 do
Loaded[(tostring(At.X) .. tostring(At.Z))] = Folder
local Floor = Instance.new("Part")
Floor.Anchored = true
Floor.Color = Color3.fromRGB(50,200,50)
Floor.Size = Vector3.new(GridSize, GridSize, GridSize)
Floor.Parent = Folder
Floor.Position = ChunkCordinates + Vector3.new((i % ChunkSize) * GridSize, 0, (math.floor(i / ChunkSize)) * GridSize)
Floor.Name = tostring(i) --Optional
end
end
local function CheckCords()
while Moving do
Checking = true
StandingChunk = Vector3.new(math.floor(Root.Position.X / ChunkSpace), 0, math.floor(Root.Position.Z / ChunkSpace))
print('Check', StandingChunk)
local Distance = math.floor(RenderDistance/2)
if StandingChunk ~= OldChunk then
for i = 0, RenderDistance^2 - 1, 1 do
GenerateChunk(StandingChunk + Vector3.new(-Distance + (i % RenderDistance), 0, -Distance + math.floor(i / RenderDistance)))
end
end
OldChunk = StandingChunk
task.wait(0.1)
end
Checking = false
end
Humanoid:GetPropertyChangedSignal('MoveDirection'):Connect(function()
if Humanoid.MoveDirection ~= Vector3.zero then
Moving = true
if not Checking then CheckCords() end
else
Moving = false
end
end)
can you explain what the “At” part of the function does?
This code actually works really well though! But for now, I’ll mark it as solved when there’s a way toremove blocks.
Thats ok
The “At
” Variable is the coordinates in which the chunk will be generated. It is used to get the world coordinates (marked as ChunkCoordinates
) and position the chunk.
In exemple, the chunk with the coordinates 0,0 will generate at the world coordinates of 0,0
The chunk 1,0 will generate on the side of the chunk 0,0 at the world coordinates 64, 0. (64 is the size that the chunk ocupies in the world)
The at is also used to name the chunks in the Loaded table
In exemple, the chunk 0,0 will have the name “00”
The chunk 1,0 will have the name “10”
The chunk -1,-1 will have the name “-1-1”
It is used to check if the chunk is loaded
I’ll try to finish the code as soon as possible
It’s done! Sorry it took so long
local Players = game:GetService("Players")
local player = Players.LocalPlayer
repeat task.wait(1) until player.Character
local Character = player.Character
local Humanoid = Character.Humanoid
local Root = Character.HumanoidRootPart
--You can play with these values as you want!
local RenderDistance = 5 -- The Area around you that'll be loaded
local GridSize = 4 -- Size of each block that makes the Chunk
local ChunkSize = 16 -- Amount of Blocks that make the Chunk
local UseGrid = false --true = Each chunk is made of blocks, laggier. false = Each chunk is one block, Faster
-- Keep it false for better performance, or lower the chunksize for less blocks
-- ;)
local Loaded = {} --Table with the chunks
local Moving
local Checking = false
local StandingChunk
local OldChunk = Vector3.Zero
local ChunkSpace = ChunkSize * GridSize
local function GenerateChunk(At)
if Loaded[(tostring(At))] ~= nil then return end
local ChunkCordinates = At * ChunkSpace
local Folder = Instance.new("Folder")
Folder.Parent = workspace.Chunks
if UseGrid then
for i = 0, ChunkSize^2 -1, 1 do
Loaded[(tostring(At))] = Folder
local Floor = Instance.new("Part")
Floor.Anchored = true
Floor.Color = Color3.fromRGB(50,200,50)
Floor.Size = Vector3.new(GridSize, GridSize, GridSize)
Floor.Parent = Folder
Floor.Position = ChunkCordinates + Vector3.new((i % ChunkSize) * GridSize, 0, (math.floor(i / ChunkSize)) * GridSize)
Floor.Name = tostring(i) --Optional
end
else
Loaded[(tostring(At))] = Folder
local Floor = Instance.new("Part")
Floor.Anchored = true
Floor.Color = Color3.fromRGB(50,200,50)
Floor.Size = Vector3.new(ChunkSpace, GridSize, ChunkSpace)
Floor.Parent = Folder
Floor.Position = ChunkCordinates + Vector3.new(ChunkSpace / 2, 0, ChunkSpace / 2)
end
end
local function CheckCords()
while Moving do
Checking = true
StandingChunk = Vector3.new(math.floor(Root.Position.X / ChunkSpace), 0, math.floor(Root.Position.Z / ChunkSpace))
local Distance = math.floor(RenderDistance / 2)
if StandingChunk ~= OldChunk then
for i = 0, RenderDistance^2 - 1, 1 do
GenerateChunk(StandingChunk + Vector3.new(-Distance + (i % RenderDistance), 0, -Distance + math.floor(i / RenderDistance)))
end
for i = 0, RenderDistance * 2 + 3, 1 do
local Target = StandingChunk + Vector3.new(-Distance - 1 + (i % (RenderDistance + 2)), 0, -Distance - 1 + (math.floor(i / (RenderDistance + 2)) * (RenderDistance + 1)))
local Chunk = Loaded[(tostring(Target))]
if Chunk ~= nil then
Chunk:Destroy()
Loaded[(tostring(Target))] = nil
end
end
for i = 0, RenderDistance * 2 - 1 , 1 do
local Target = StandingChunk + Vector3.new(-Distance - 1 + (math.floor(i / (RenderDistance)) * (RenderDistance + 1)), 0, -Distance + (i % RenderDistance))
local Chunk = Loaded[(tostring(Target))]
if Chunk ~= nil then
Chunk:Destroy()
Loaded[(tostring(Target))] = nil
end
end
end
OldChunk = StandingChunk
task.wait(0.1)
end
Checking = false
end
Humanoid:GetPropertyChangedSignal('MoveDirection'):Connect(function()
if Humanoid.MoveDirection ~= Vector3.zero then
Moving = true
if not Checking then CheckCords() end
else
Moving = false
end
end)
Humanoid.WalkSpeed = 100 -- This is just for testing, feel free to delete this
Feel free to ask me any questions and to add things to it
you should also reuse parts because deleting parts gets laggy after a while
partcache/objectcache already implements this