Find Random Position in Part

When I was developing a game, I wanted a player to spawn randomly within an X and Z of a part. Back then, I didn’t know how to do that. Eventually, I found out that you could use the following script:
(explained below)

local part = game.Workspace.Zone

local x = part.Position.X + math.random(-part.Size.X/2,part.Size.X/2)
local y = part.Position.Y + math.random(-part.Size.Y/2,part.Size.Y/2)
local z = part.Position.Z + math.random(-part.Size.Z/2,part.Size.Z/2)

game.Workspace.Part.Position = Vector3.new(x,y,z)

-- this script will get a random position inside of a part and move a smaller part into that position
  • First, we need to get the position of the part in a said axis. Doing this will get the absolute center of the part.
  • Next, we use a math.random() to choose a random value with the minimum/maximum value being the size of the part divided by two (because it’s in the absolute center, so we take the value behind and in front and half it)
  • Then, add the size to the position. This will spawn the part at the position and add a random few studs depending on the size so it appears inside the part.
  • Now we can repeat for the other two axis and you have yourself a random position within the part.

(yes it works for models too)

FINAL RESULT

  • I found this helpful
  • I did not find this helpful

0 voters

19 Likes

Its great that you was able to do your own research and create a solution to your problem on your own, It probably greatly helped build confidence in your developer skills.

Now that you’ve figured this out here is a more advanced version for future usage.

Using just the Position of the Zone part can have issues if the Zone part has been rotated so it is best to use CFrame to correct for this issue.

local Zone = game.Workspace.Zone
local Part = game.Workspace.Part

Part.Position = (Zone.CFrame * CFrame.new(
    (math.random() - 0.5) * Zone.Size.X,
    (math.random() - 0.5) * Zone.Size.Y,
    (math.random() - 0.5) * Zone.Size.Z
)).Position

29 Likes

Nice. It will definitely help developers, even if it is simple.

However, for anyone who wants to use something like this to spawn players randomly within a part, as OP wanted to use this script for, using this script directly might cause issues.

To teleport a player, simply assigning a new position to a PrimaryPart (i.e. HumanoidRootPart for the model of the player’s character) might end up only teleporting that part rather than the entire model. Also, you might also find it useful to set an orientation to a given player to add more flare to spawning players or make the players face the right direction when spawning.

In this case, you might want to use CFrame objects, plus a function that all models have called SetPrimaryPartCFrame, which modifies the entire model’s position and orientation based on the CFrame object given. However, considering what this Roblox API page says regarding the function, you might want to use a different method which I will describe a bit later.

Here is the code using CFrame objects the SetPrimaryPartCFrame function:

local x = game.Workspace.Zone.Position.X + math.random(-game.Workspace.Zone.Size.X/2,game.Workspace.Zone.Size.X/2)
local y = game.Workspace.Zone.Position.Y + math.random(-game.Workspace.Zone.Size.Y/2,game.Workspace.Zone.Size.Y/2)
local z = game.Workspace.Zone.Position.Z + math.random(-game.Workspace.Zone.Size.Z/2,game.Workspace.Zone.Size.Z/2)

-- Let the variable "character" be the Character instance of the Player 
-- and assume that you already assigned that variable with the Player's
-- Character instance.

newCFrame = CFrame.new(Vector3.new(x,y,z))
character:SetPrimaryPartCFrame(newCFrame)

The new method uses what is known as a PVInstance, which contains position and velocity information and cannot be created. However, all models have one, and you can get it using the function GetPivot, and use the method PivotTo to set the new position.

Here is the same code as above but now using the newer technique (we still use CFrame objects!):

local x = game.Workspace.Zone.Position.X + math.random(-game.Workspace.Zone.Size.X/2,game.Workspace.Zone.Size.X/2)
local y = game.Workspace.Zone.Position.Y + math.random(-game.Workspace.Zone.Size.Y/2,game.Workspace.Zone.Size.Y/2)
local z = game.Workspace.Zone.Position.Z + math.random(-game.Workspace.Zone.Size.Z/2,game.Workspace.Zone.Size.Z/2)

-- Again, let the variable "character" be the Character instance 
-- of the Player and assume that you already assigned that 
-- variable with the Player's Character instance.

newCFrame = CFrame.new(Vector3.new(x,y,z))
charPivot = character:GetPivot()
character:PivotTo(charPivot * newCFrame)

Since I have not used PVInstance before, I am not sure if the result will be slightly different. like the orientation, but if those differences occur, CFrame objects can be used to change the orientation if need be (or slightly modify the code, whatever approach best suits the situation).

If you want to change orientation, the page on CFrames might be useful, but you might need to be familiar with radians or use Lua methods to covert degrees to radians.

Hope this is helpful for anyone who wants to use this script to teleport/spawn models or players.

2 Likes