What do you want to achieve? Keep it simple and clear!
I’m spawning multiple monster blocks in a smallish field and I want the objects to have enough space to not touch each other.
What is the issue? Include screenshots / videos if possible!
The Instances are overlapping and causing issues with their CFrames. Bumping and jumping and pushing each other in order to occupy the same position.
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I’ve tried destroying the parts if they touch each other, but I’m not sure if my definitions are up to par.
I’ve also tried changing math.random to ((math.random)*10) in order to spawn items at farther intervals but of course they still occasionally overlap.
I’ve tried several ways to do this including multiple different attempts at definitions, several of them run without any errors but do not destroy any rocks.
My Rock is stored in rep storage and is parented to folder in game.Workspace.Rocks
local function onTouch(otherPart)
print (otherPart.Parent)
if otherPart.Parent == Rock
then rock:Destroy()
else
and
local rock = script.Parent
local label = rock.Health
local hit_sound = rock.Hit
local break_sound = rock.Break
local debounce = false
local hp = rock.Stats.HP.Value
local maxHP = rock.Stats.MaxHP.Value
local swings = rock.Stats.Swings.Value
local rockPos = rock.Position
local Rocks = game.Workspace.Rocks
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local function Round(n, decimals) --Decimal rounding for rounding total swing calculation fractions down
decimals = decimals or 0
return math.floor(n * 10^decimals) / 10^decimals
end
local function onTouch(otherPart) --THIS IS WHERE I TRY TO DESTROY OVERLAP!
print (otherPart.Parent)
if otherPart.Parent.Parent == game.Workspace.Rocks
then rock:Destroy()
else
local tool = otherPart.Parent
if tool:IsA('Tool') and tool.Mining.Value == true and debounce == false and tool.Name == "Hammer" then
debounce = true
local hp = rock.Stats.HP.Value
swings = swings +1
rock.Stats.Swings.Value = rock.Stats.Swings.Value +1
wait()
print ("tool is "..tool.Name)
local player = tool.parent
print ("player is "..player.Name)
print ("maxHP is "..maxHP)
local power = tool.Power.Value
print ("power is "..power)
--total swings needs WHOLE NUMBER VALUE
local calcSwings = (maxHP/power)
local totalSwings=((Round(calcSwings, 0)+1))
print ("totalSwings is "..totalSwings)
rock.Stats.HP.Value = rock.Stats.HP.Value - power
print ("stored HP value is "..rock.Stats.HP.Value)
local currentHP = maxHP - ((swings) * power)
print ("calculated HP is "..currentHP)
print ("swings at "..swings)
rock.Stats.swingsLeft.Value = totalSwings - swings
hit_sound:Play()
--total swings needs whole number value for GUI
local swingsLeft = rock.Stats.swingsLeft.Value
label.Green.Size = UDim2.new(swingsLeft/totalSwings, 0, 1, 0)
end
if rock.Stats.HP.Value <= 0 then
break_sound:Play()
wait(.5)
rock:Destroy()
local crystals= ReplicatedStorage:FindFirstChild('Crystals'):GetChildren()
print(crystals)
local randomCrystal = crystals[math.random(1,#crystals)]:Clone()
randomCrystal.Parent = game.Workspace
randomCrystal.Position = rockPos+Vector3.new(0,-3,0)
local collectScript = ServerStorage:FindFirstChild("Collect"):Clone()
collectScript.Parent = randomCrystal
end
wait(1)debounce = false
end
end
rock.Touched:Connect(onTouch)
Sorry my code is so ugly, I’m still really new. There’s a lot of old debugging prints in there. I hope it doesn’t make it too difficult to read. I’m hoping there’s a method that doesn’t require me to write a new method of finding random positions. If you need that code it is,
local rock = game.ReplicatedStorage.Rock
local count = Instance.new("IntValue")
--local anchorPOS = rock.Anchor.Position
local function makeRock()
local clone = rock:Clone()
local clonePOS = Vector3.new(math.random(-50,50), 4, math.random(-50,50))
clone.Anchor.Position = clonePOS
clone.Position = clonePOS
clone.Parent = workspace.Rocks
count.Value += 1
local connection
connection = clone:GetPropertyChangedSignal("Parent"):Connect(function()
connection:Disconnect()
count.Value -= 1
if count.Value < 50 then
makeRock()
end
end)
end
for i = 1, 50 do
makeRock()
wait()
end
you may want to compare the clonePOS with the other positions of the other ‘monsters’, and call the random function again if it is within a certain distance from another one. This can be quite inefficient if you have a lot of them in a small space but it could work for your application.
Thanks that’s definitely something else I can check out. I’m so new at scripting that I’m just excited to make things work and don’t particularly mind inefficiencies yet. The instances should only be a dozen or so, I just wanted the issue fixed before I start designing an area to actually put them.
I also tried spawning them in predetermined positions but my client wasn’t updating after they initially spawned.
Not tested yet, but I’ve come up with something that might work. Keep in mind that after it tries 10 times, it will just set the position to the previous position (which is within the exclusion radius) but hopefully this works for the most part for you. Feel free to change the radius of exclusion (marked with comments) to define how close two rocks can be to each other before it re-calculates a new random position. You can also change the maxitteration variable to something higher or lower depending on your results.
local rock = game.ReplicatedStorage.Rock
local count = Instance.new("IntValue")
--local anchorPOS = rock.Anchor.Position
local rockPositions = {}
local function makeRock()
local clone = rock:Clone()
local found = true
local maxitteration = 10 --a 'timeout' to stop calculating after this amount so that you're computer doesn't die
local clonePOS = Vector3.new(math.random(-50,50), 4, math.random(-50,50))
for i=0, maxitteration do
for _,v in ipairs(rockPositions) do
if (v - clonePOS).Magnitude <= 5 then --radius of exclusion
found = false
break --too close, break the loop and re-generate a random point
end
end
if found then
break
else
clonePOS = Vector3.new(math.random(-50,50), 4, math.random(-50,50))
end
end
table.insert(rockPositions,clonePOS)
clone.Anchor.Position = clonePOS
clone.Position = clonePOS
clone.Parent = workspace.Rocks
count.Value += 1
local connection
connection = clone:GetPropertyChangedSignal("Parent"):Connect(function()
connection:Disconnect()
count.Value -= 1
if count.Value < 50 then
makeRock()
end
end)
end
for i = 1, 50 do
makeRock()
wait()
end
Thank you! It doesn’t seem to work when I swap it into my MakeRocks script, but I see what you were aiming at. Hopefully I can get it to work after dinner, it looks like a really cool idea to make sure the instances are spaced out!
I may have misplaced a variable declaration. Try this:
local rock = game.ReplicatedStorage.Rock
local count = Instance.new("IntValue")
--local anchorPOS = rock.Anchor.Position
local rockPositions = {}
local function makeRock()
local clone = rock:Clone()
local maxitteration = 10 --a 'timeout' to stop calculating after this amount so that you're computer doesn't die
local clonePOS = Vector3.new(math.random(-50,50), 4, math.random(-50,50))
for i=0, maxitteration do
local found = true
for _,v in ipairs(rockPositions) do
if (v - clonePOS).Magnitude <= 5 then --radius of exclusion
found = false
break --too close, break the loop and re-generate a random point
end
end
if found then
break
else
clonePOS = Vector3.new(math.random(-50,50), 4, math.random(-50,50))
end
end
table.insert(rockPositions,clonePOS)
clone.Anchor.Position = clonePOS
clone.Position = clonePOS
clone.Parent = workspace.Rocks
count.Value += 1
local connection
connection = clone:GetPropertyChangedSignal("Parent"):Connect(function()
connection:Disconnect()
count.Value -= 1
if count.Value < 50 then
makeRock()
end
end)
end
for i = 1, 50 do
makeRock()
wait()
end
After you have had something to eat let me know if this works, and if not check if there are any errors. I’ll hop on studio and try to apply this.
Wow, that is absolutely amazing! I haven’t learned maxiteration or magnitude of vectors yet. I’ll put the terms on my to do list! I drastically increased the concentration to make sure they don’t overlap and your script did it with flying colors! Thank you!!!