Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Randomly generating parts in a set radius?

Asked by 10 years ago

I'm looking to render grass in my game, but i decided it would be best to just do it on the client so I could choose to only show grass in a set radius.

I'm not sure where to start, how would I consistently place the grass(e.g. grass leaves radius, comes back in and remains in the same spot) should I generate and store all the points or would using a seed work? If I stored all the points in a table I'm not sure if I want to iterate over the entire thing every time the player moves to check if grass is in an area. I'm sure there's a way to organize my points, like in chunks but that's something I've never done..

tl;dr How would you locally generate grass in a set radius around a player?

**Edit: ** I've come up with a solution, but I'm still open to more efficient ideas.

Currently I'm generating all the grass positions in clusters, I take a table place a random point in it, and then from that point I generate more random points within an area and place those in another table within that table so it looks something like: {{point = vector3, grass= {vector3, vector3, vector3}}

From that I can then check for clusters near the camera and render the grass associated with them. It seems to handle 10,000 grass pieces alright, but sometimes the fps dip down for a moment when instancing the grass. I've tested up to 20,000 and have faired alright, but the frame rate drops lower more noticeably when instancing parts. Maybe I can find a way to recycle parts, or sort my data better.

If anyone is interested in the code:

local renderDistance = 100 -- studs radius

local player = game.Players.LocalPlayer
local camera = Workspace.CurrentCamera 
local base = Workspace.Test

math.randomseed(tick())

function randomPoint(center, size)
    return Vector3.new(
        math.random(center.X - size.X/2, center.X + size.X/2),
        center.Y + size.Y/2,
        math.random(center.Z - size.Z/2, center.Z + size.Z/2)
    )   
end

function inTable(tab, val)
    for i,v in pairs(tab) do
        if v == val then
            return i
        end
    end
    return nil
end
function fade(part, dir)
    if dir == "In" then
        Spawn(function()
            for i = 1, 0.5, -0.05 do --bleh, too tired to make this function useful...
                part.Transparency = i
                wait()
            end
        end)
    elseif dir == "Out" then
        Spawn(function()
            for i = 0, 1, 0.05 do
                part.Transparency = i
                wait()
            end
        end)
    end
end

function grass(cf, size)
    local g = Instance.new("Part")
    g.Anchored = true
    g.CanCollide = false
    g.Name = "Grass"
    g.BrickColor = BrickColor.new("Grime")
    g.Transparency = 1
    g.Size = size
    g.CFrame = cf
    g.Parent = camera
    local mesh = Instance.new("SpecialMesh", g)
    mesh.MeshType = "FileMesh"
    mesh.MeshId = "http://www.roblox.com/asset/?id=17659272"
    mesh.Scale = (size/2)
    return g
end

local grasses = {} --{{Vector3.new(clusterPosition),{grass, grass, grass}},{Vector3.new(clusterPosition),{grass, grass, grass}}}
local num = 10000
local clusters = 0
while num > 0 do
    --grass cluster
    clusters = clusters + 1
    local clusterPoint = randomPoint(base.Position, base.Size)
    local clusterSize = math.random(5,100)
    grasses[clusters] = {point=clusterPoint, points = {},grass = {}}
    for i = 5, clusterSize do
        local cf = CFrame.new(randomPoint(clusterPoint, Vector3.new(clusterSize, base.Size.Y,clusterSize)))
        * CFrame.Angles(math.rad(-45),math.rad(1,360),0) 
        - Vector3.new(0,0.25,0)
        grasses[clusters].points[i] = cf  
        grass(cf, Vector3.new(1,1,1)*math.random(3,4))
    end
    num = num - clusterSize
end

--render grass
local camPos = camera.CoordinateFrame
local visibleClusters = {}
while wait(0.2) do
    if camPos ~= camera.CoordinateFrame then
        camPos = camera.CoordinateFrame
        for i,v in pairs(grasses) do
            local dist = (camPos.p - v.point).magnitude
            local visible = inTable(visibleClusters, v.point)
            if dist > renderDistance and visible then
                --hide cluster
                for _,g in pairs(v.grass) do
                    g:Destroy()
                end
                table.remove(visibleClusters, visible)
            elseif dist < renderDistance and not visible then
                table.insert(visibleClusters, v.point)
                for k,pos in pairs(v.points) do
                    v.grass[k] = grass(pos, Vector3.new(3,3,3))
                    fade(v.grass[k], "In")
                end
            end
        end
    end
end

Answer this question