|
| 14 Oct 2014 06:56 PM |
Hello, I have this script I made that generates trees randomly around the map, and it works fine. The problem I'm having is that the trees can overlap, and I don't want them to. How would I go about making the script check to see if there is a tree there, and if there is, change the position to a new random place until there's not a tree? Here is the script:
repeat wait() until game.Lighting.Tree
local Mod = game.Lighting.Tree;
for i=1,math.random(12,18),1 do t = game.Lighting.Tree:Clone() t.Parent = game.Workspace t.PrimaryPart = t.Trunk t:SetPrimaryPartCFrame(CFrame.new(math.random(-125,125),7.5,math.random(-125,125))+game.Workspace.Base.Position) end
Any help is greatly appreciated. Note that I am not asking for you to give me the full script, as I would not learn that way. I'm just simply wondering how I would manage to do this. |
|
|
| Report Abuse |
|
|
RoflBread
|
  |
| Joined: 18 Jun 2009 |
| Total Posts: 3803 |
|
|
| 14 Oct 2014 07:27 PM |
| Make a table of the positions of every spawned tree, and then loop through it and check if the new tree is within X units of the others. |
|
|
| Report Abuse |
|
|
|
| 14 Oct 2014 08:17 PM |
Alright, I tried to do what you said, and it only half works. What my new script does is checks to see if there is a tree, and if there is, it doesn't place it. But it only checks for the tree that was placed last. For example, I named the trees based on the index of the for loop, so the script could generate one tree in one spot, then another tree far away from it. But then the third tree could be right next to the second tree, because it only checks for the second tree, not the first.
This is the script:
repeat wait() until game.Lighting.Tree
local distance = 20 local Mod = game.Lighting.Tree;
local trees = {game.Workspace.Tree.Trunk.Position}
for i=1,math.random(12,18),1 do t = game.Lighting.Tree:Clone() t.Parent = game.Workspace t.PrimaryPart = t.Trunk t.Name = "Tree" .. i for i,v in pairs (trees) do repeat t:SetPrimaryPartCFrame(CFrame.new(math.random(-125,125),7.5,math.random(-125,125))+game.Workspace.Base.Position) wait() until (t.Trunk.Position - v).magnitude > distance end table.insert(trees,1,t.Trunk.Position) end
What did I do wrong? How could I fix this? |
|
|
| Report Abuse |
|
|
| |
|
| |
|
| |
|
|
| 14 Oct 2014 10:46 PM |
| try adding parentheses to the "Tree" ..i script |
|
|
| Report Abuse |
|
|
|
| 14 Oct 2014 11:09 PM |
@Joshua It doesn't matter if you have parenthesis or not (at least in this situation). They all get named correctly, therefore, that isn't the problem. Thank you anyways though :) |
|
|
| Report Abuse |
|
|
|
| 14 Oct 2014 11:13 PM |
| I would for i, v in pairs to get every tree then I would have a Center part in every tree the I would get every tree's Center part's position then get the magnitude then use them to determine all possible locations to place the tree. |
|
|
| Report Abuse |
|
|
bob10110
|
  |
| Joined: 09 Dec 2007 |
| Total Posts: 679 |
|
|
| 14 Oct 2014 11:21 PM |
I would tackle this problem by first generating the randomized CFrame and hold it in a variable -- don't place the tree yet. Then check that position against all current tree positions in the table. If the position is good, then you can place the tree and add that position to the table; else, change the position and start the position checks again.
Pseudocode:
for number of desired trees do --while current tree has yet to be placed do ----generate proposed position for new tree ----for each existing position in table do ------check distance between positions ----end ----if proposed position works ------make tree ------add position to table ------break out of while loop ----end --end end |
|
|
| Report Abuse |
|
|
|
| 14 Oct 2014 11:37 PM |
empty = function(position) local trees = {} for I,v in pairs(Workspace:GetChildren()) do if v.Name == "Tree" then trees[#trees+1] = v end end for I,v in pairs(trees) do if (v:GetModelCFrame().p-position).magnitude < ( (v:GetExtentsSize())+5) then return false end end return true end
for i=1,math.random(12,18),1 do t = game.Lighting.Tree:Clone() t.Parent = game.Workspace t.PrimaryPart = t.Trunk repeat pos = CFrame.new(math.random(-125,125),7.5,math.random(-125,125))+game.Workspace.Base.Position if empty(pos) then t:SetPrimaryPartCFrame() a = true else a = false end until a end
--should work |
|
|
| Report Abuse |
|
|
|
| 15 Oct 2014 12:04 AM |
@Islandmaker
I got most of this figured out, except I'm having trouble with one thing. In your code:
if (v:GetModelCFrame().p-position).magnitude ...etc
that was the part I was having trouble with. It gave me the error:
bad argument #2 to '?' (Vector3 expected, got userdata)
This was the part I was having trouble with when trying to write the code based on what bob said. When I get all the trees with i,v in pairs, how would I know what to put for the magnitude? I tried:
(v.Trunk.Position - v.Trunk.Position).magnitude
but that ended up subtracting the position from itself. How would I do something like this?
(v.Trunk.Position - EVERY_OTHER_TREE.Trunk.Position).magnitude |
|
|
| Report Abuse |
|
|
|
| 15 Oct 2014 12:20 AM |
| if (v.Trunk.Position-position).magnitude < ( (v:GetExtentsSize())+5) then |
|
|
| Report Abuse |
|
|
|
| 15 Oct 2014 04:10 PM |
Thank you, islandmaker, but now it gives me this error on that line:
bad argument #2 to '?' (Vector3 expected, got userdata)
I'm assuming it's because I put CFrame.new() instead of Vector3.new(), but when I change the CFrame.new() to Vector3.new(), it still gives me the same error. What can I do about this? |
|
|
| Report Abuse |
|
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
| 15 Oct 2014 10:35 PM |
When I did this, I used raycasting to create a ray directly downwards. If it hit anything other than the ground, it would try again with a new random location.
This makes it possible for them to overlap slightly, but they won't be on top of each other |
|
|
| Report Abuse |
|
|
|
| 15 Oct 2014 10:49 PM |
Example:
local tree = game.Lighting.Tree local base = workspace.Base
for i = 1, math.random(12,18) do local hit,pos = nil,nil repeat local newpos = base.Position+Vector3.new(math.random(-125,125),15,math.random(-125,125)) local ray = Ray.new(newpos,Vector3.new(0,-20,0)) hit,pos = workspace:FindPartOnRay(ray,_) wait() -- Incase I did this wrong and it infinite loops until hit ~= nil local t = tree:clone() t.Parent = workspace t.PrimaryPart = t.Trunk t:SetPrimaryPartCFrame(CFrame.new(pos)) end
|
|
|
| Report Abuse |
|
|