# Detecting in part is in another?

Hello Developers,
Recently I’ve made a spawning system which spawns a random item randomly inside a region3 on the X, Y axis but I need the item to spawn on top of surfaces and not just on the floor. I’ve tried using .Touched and Region3 but Touched wouldn’t register properly and Region3 kept and making the parts position move to the surface position but it would happen anywhere in the region not when the part is actually inside another one.

This is how I calculate the x and y but like I said I do not know how to calculate the y.

``````	local X, Z = SpawnRegion.Size.X, SpawnRegion.Size.Z
local X, Z = math.random(1, X), math.random(1, Z)
local X, Z = (Spawn.Position - Vector3.new(Spawn.Size.X/2)) + Vector3.new(X, 0, 0), (Spawn.Position - Vector3.new(Spawn.Size.Z/2)) + Vector3.new(Z, 0, 0)
print(X)
Item.Parent = game.Workspace.ItemSpawns
Item.Anchored = true
local Items = Item:GetChildren()
for i, v in pairs(Items) do
if v:IsA("Part") then
v.Anchored = true
elseif v:IsA("UnionOperation") then
v.Anchored = true
end
end
local IgnoredPlayers = {}
for i, Player in pairs(game.Players:GetChildren()) do
if Player and Player.Character then
table.insert(IgnoredPlayers, Player.Character)
end
end
local PartsInWhitelist = game.Workspace:FindPartsInRegion3WithIgnoreList(SpawnRegion, IgnoredPlayers, 100)
Item.Position = Vector3.new(X.X, Spawn.Position + Vector3.new(Spawn.Size.Y/2), Z.Z)
``````

Full script (Region3 for Y axis):

``````--[Variables]--
local SpawnSettings = require(script.SpawnSettings)
local Spawns = SpawnSettings.Spawns
local Spawn = script.Parent
local SpawnCorner1 = Spawn.Position - Vector3.new(Spawn.Size.X /2, Spawn.Size.Y/2, Spawn.Size.Z/2)
local SpawnCorner2 = Spawn.Position + Vector3.new(Spawn.Size.X /2, Spawn.Size.Y/2, Spawn.Size.Z/2)
local SpawnRegion = Region3.new(SpawnCorner1, SpawnCorner2)
local ServerStorage = game:GetService("ServerStorage")

local function SpawnItem()
local ItemTypeNumber = 0
for i, v in pairs(SpawnSettings.Items) do
ItemTypeNumber = ItemTypeNumber +1
end
ItemTypeNumber = math.random(1, ItemTypeNumber)
local ItemType = SpawnSettings.Items[ItemTypeNumber]
ServerStorage:WaitForChild(ItemType)
local ItemNumber = 0
for i, v in pairs(SpawnSettings.Spawns[ItemType]) do
ItemNumber = ItemNumber +1
end
print(ItemType)
local ItemNumber = math.random(1, ItemNumber)
local ItemName = SpawnSettings.Spawns[ItemType][ItemNumber]
--ANYTHING ABOVE IS NOT IMPORTANT TO THE QUESTION--
--ANYTHING ABOVE IS NOT IMPORTANT TO THE QUESTION--
--ANYTHING ABOVE IS NOT IMPORTANT TO THE QUESTION--
local Item = ServerStorage:WaitForChild(ItemType):WaitForChild(ItemName):Clone()
local X, Z = SpawnRegion.Size.X, SpawnRegion.Size.Z
local X, Z = math.random(1, X), math.random(1, Z)
local X, Z = (Spawn.Position - Vector3.new(Spawn.Size.X/2)) + Vector3.new(X, 0, 0), (Spawn.Position - Vector3.new(Spawn.Size.Z/2)) + Vector3.new(Z, 0, 0)
print(X)
Item.Parent = game.Workspace.ItemSpawns
Item.Anchored = true
local Items = Item:GetChildren()
for i, v in pairs(Items) do
if v:IsA("Part") then
v.Anchored = true
elseif v:IsA("UnionOperation") then
v.Anchored = true
end
end
local IgnoredPlayers = {}
for i, Player in pairs(game.Players:GetChildren()) do
if Player and Player.Character then
table.insert(IgnoredPlayers, Player.Character)
end
end
table.insert(IgnoredPlayers, Spawn)
local PartsInWhitelist = game.Workspace:FindPartsInRegion3WithIgnoreList(SpawnRegion, IgnoredPlayers, 100)
Item.Position = Vector3.new(X.X, Spawn.Position + Vector3.new(Spawn.Size.Y/2), Z.Z)
wait()
for i, Part in pairs(PartsInWhitelist) do
local PartCorner1 = Part.Position - Vector3.new(Part.Size.X /2, Part.Size.Y/2, Part.Size.Z/2)
local PartCorner2 = Part.Position + Vector3.new(Part.Size.X /2, Part.Size.Y/2, Part.Size.Z/2)
local PartRegion = Region3.new(PartCorner1, PartCorner2)
table.insert(IgnoredPlayers, Part)
local PartsInWhitelistParts = game.Workspace:FindPartsInRegion3WithIgnoreList(PartRegion, IgnoredPlayers, 1)
local p = Instance.new("Part", workspace)
p.Anchored = true
p.Transparency = 0.6
p.Size = PartRegion.Size
p.CFrame = PartRegion.CFrame
if PartsInWhitelistParts ~= nil then
for i, v in pairs(PartsInWhitelistParts) do
local Y = Part.Position - Vector3.new(Spawn.Size.Y/2)
Item.Position = Vector3.new(X.X, Y.Y, Z.Z)
end
end
end
end

SpawnItem()
``````

This is what I’m trying to do.

2 Likes

cant you just use GetTouchingParts
just read up on it, appearently that’s not how it works

1 Like

Hello!

I would calculate the y by doing this:

``local y = part.Y + part.Size.y/2``

You have to get the parts in the region3 and then do the code above.

1 Like

I’m going to update the code with the full script including my region 3 progress. I tried using region 3 like I said but I had no luck.

1 Like

If i understand this correctly you want the item to go ontop of the part?

This would be done by doing:

``````if PartsInWhitelistParts ~= nil then
for i, v in pairs(PartsInWhitelistParts) do
local Y = Part.Position.Y + Part.Size.Y/2 --This is what i've changed!
Item.Position = Vector3.new(X.X, Y.Y, Z.Z)
end
end``````

This works but sometimes its still going up even when its not inside the part. I’m 99% sure my regions are correct aswell

1 Like

I’m pretty sure you actually can use `:getTouchingParts()` in this instance. The only thing is that the object in question needs to have a TouchInterest. So if you wrapped your spawned item in an invisible brick that extended to the bounds of the model, put a TouchInterest in it, then you could use that method.

Alternatively, I believe that if you raycast down from the model’s PrimaryPart (given that it’s in a reasonably central location on the model) you should be able to find any parts that it’s currently inside of/above. Then you can just use the properties of the Ray (getting the hit part/position) to move the spawned object up to the hit part’s top surface.

2 Likes

Could you elaborate on why that wouldn’t work?

Just use FindPartOnRay, probably ignoring everything that is not the map with it.
You also do not need to use region3. You can just store a CFrame and a Size vector, that way you can rotate it if you would like (which is not possible with Region3).
Then you can just find the location from something like `Region.CFrame * CFrame.new(size.X * rand(), size.Y * rand(), size.Z * rand())` where `rand()` returns something between -0.5 and 0.5. You can shoot the ray down from the sky or top of the region to find where the floor is.

1 Like

Hope this would help:

With the informations in my tutorial you can compare each corner with the corner of your model, i am working on a corner module script, wait a bit and i can send you the script i made (it work). Thanks for waiting @aIphabox. So, just make a script that check the position, and if it was false then use coroutines or spawn functions for create a loop and always check until if it was in the Region. Its just a idea, but hope it will help you.

1 Like

So, i found it. This is the first part:

``````local CornerModule = {}

--The Variables
local Helper = require(script.VerticesController)

function CornerModule:IsInRegion(Region, Part)
--Check if the Region parameter is a Region3
if typeof(Region) == "Region3" and typeof(Part) == "Instance" then
if Helper.CheckValues(Part, Region) == true then
--If all Corners are in the Region3 then return true
return true
else
--Else return false
return false
end
else
--If nothing work then the Parameters are incorrect and the Module will launch a error message
error("CornerModule error message from function GetCorners() : Incorrect Parameters.")
end
end

return CornerModule
``````

And the second was on Github.