Finding Available Spawn Point For Vehicle Spawning

I’m wanting to make a Delivery System. My first main issue is that I want the vehicle to spawn in a free area. So if there are 3 points and 2 points have other players vehicles on them I want the vehicle to spawn on the point which has no other vehicles. Basically a free spawn point for the vehicle.

My issue is that I don’t know how to find the available point.

Spawning Vehicle:

local VehC = game:GetService('ServerStorage').Veh
		VehC.Parent = game.Workspace
		VehC:MoveTo(workspace.DeliveryTruckSpawns.Part.Position) -- This would be the available spawn point 

Example:
image

Have you tried looking at other posts?

I believe this issue has been solved before such as using Region3 or the newer spatialQuery.

I have looked at posts regarding Region3 but I didn’t understand them a single bit, so I’m hoping to get some more help by making a post about the specific issue.

Hi, First of all, You can create a value inside the already spawned points for a little debounce (such as boolvalues, if outside of script) and then loop through all the spawn points to see which one doesn’t have the value.

I’ll give that a go, thank you.

So would I do something like this?

		for _, v in pairs(workspace.SpawnPoints:GetChildren()) do
                         
		end

how would I detect which ones have a “true” and “false” value?

You can replace the ‘v’ with whatever you basically want since it’s the name of the thing that was last checked. So, let’s say you name it “SpawnChecked” for now. You can then do:

		local ValueCheck = SpawnChecked:FindFirstChild("Tag") -- Check for already made value.
				if ValueCheck == nil and ValueCheck.Value == false then -- If there's no value, make.
					local ValueCheck = Instance.new("BoolValue", SpawnChecked)
					ValueCheck.Name = "Tag"
					ValueCheck.Value = true
					-- Spawn car.
					
				end

Works perfectly, expect the vehicle spawns at all the points, as well makes the BoolValue Tag to all of them as well.

				local VehC = game:GetService('ServerStorage').Veh:Clone()
				VehC.Parent = game.Workspace
				VehC:MoveTo() -- What point would it move to? ValueCheck.Parent.Position?

Here is the entire part:

		for _, SpawnChecked in pairs(workspace.DeliveryTruckSpawns:GetChildren()) do
			
			local ValueCheck = SpawnChecked:FindFirstChild("Tag") -- Check for already made value.
			if ValueCheck == nil then -- If there's no value, make.
				local ValueCheck = Instance.new("BoolValue", SpawnChecked)
				ValueCheck.Name = "Tag"
				ValueCheck.Value = true
				local VehC = game:GetService('ServerStorage').Veh:Clone()
				VehC.Parent = game.Workspace
				VehC:MoveTo(ValueCheck.Parent.Position)

			end
		end

I see what was the problem, it was because none of the points had the Tag value so it spawned at all of them.

Looking around it seems that none of the posts were detailed and use the new SpatialQuery like this one though it is on the right track using region 3.

Plus I will also have to do something similar for my game so here is my shot at it, make sure to modify the if condition which checks the models name for an occupied part.

--Change this within the below code with your own condition
        if model.Name == "NameOfCar" then --Check the name of the model if it is another car, make sure to change here
            return true
        end
local function checkSpawnPointIsOccupied(spawnPart)
    local cframeLocationCheck = spawnPart.CFrame
    local sizeOfLocationCheck = spawnPart.Size*Vector3.new(1,10,1) --Modify the size if you want

    local filter = {}

    for i, player in pairs(game:GetService("Players"):GetPlayers()) do
        local character = player.Character
        table.insert(filter, character) --Get all player characters to filter out
    end

    table.insert(spawnPart)

    local query = OverlapParams.new()
    query.FilterDescendantsInstances = filter
    query.FilterType = Enum.RaycastFilterType.Blacklist

    local parts = workspace:GetPartBoundsInBox(spawnPart.CFrame, sizeOfLocationCheck, query)


    local regionVisualizer = Instance.new("Part") --Part to visualize workspace only
    regionVisualizer.CFrame = cframeLocationCheck
    regionVisualizer.Size = sizeOfLocationCheck
    regionVisualizer.Anchored = true
    regionVisualizer.Transparency = 0.5
    regionVisualizer.CastShadow = false
    regionVisualizer.CanCollide = false
    regionVisualizer.Parent = workspace
    game:GetService("Debris"):AddItem(regionVisualizer, 0.5)

    for _, part : BasePart in pairs(parts) do
        if part.Locked == true then
            --Skip locked parts like baseplate
            continue
        end

        local model = part:FindFirstAncestorOfClass("Model") --See if part belongs to a car model.
        if model.Name == "NameOfCar" then --Check the name of the model if it is another car, make sure to change here
            return true
        end
    end

    return false
end

local spawnPoints = workspace.SpawnPoints:GetChildren()

local spawnedSuccess = false
for _, spawnPointPart in pairs(spawnPoints) do
    local isOccupied = checkSpawnPointIsOccupied(spawnPointPart)
    if isOccupied then
        continue --Keep searching
    else
        --Not occupied can spawn car here
        local VehC = game:GetService('ServerStorage').Veh:Clone()
        VehC.Parent = game.Workspace
        VehC:MoveTo(spawnPointPart.Position)
        spawnedSuccess = true
        break --stop for loop searching for non occupied spawn points
    end
end

if spawnedSuccess == false then
    warn("All spawn points are full! :(")
end

Oh, my bad…! I just realised the big mistake. I’m pretty sure you can break the looping by simply putting break after you spawn the car. (Haven’t tested it.)

I added the break to stop it going to them all which fixed it but it still adds the “Tag” Value to all of the points.

		for _, SpawnChecked in pairs(workspace.DeliveryTruckSpawns:GetChildren()) do
			
			local ValueCheck = SpawnChecked:FindFirstChild("Tag") -- Check for already made value.
			if ValueCheck == nil then -- If there's no value, make.
				local ValueCheck = Instance.new("BoolValue")
				ValueCheck.Name = "Tag"
				ValueCheck.Value = true
				local VehC = game:GetService('ServerStorage').Veh:Clone()
				VehC.Parent = game.Workspace
				ValueCheck.Parent = SpawnChecked
				VehC:MoveTo(ValueCheck.Parent.Position)
				break	
			end
		end

How about you make the values without the script and then use the script to only check the values if they are true/false?

Won’t that just make them all true though?

No, no. Just add bool values and keep the values off. Then change the if ValueCheck == nil then to if SpawnChecked.Value == false then, And also delete the instance.

Awesome, it works! Thank you, I’ll also look at your script @dthecoolest :slight_smile:

1 Like
	for _, SpawnChecked in pairs(workspace.DeliveryTruckSpawns:GetChildren()) do
		
		local ValueCheck = SpawnChecked:FindFirstChild("Tag") -- Check for already made value.
		if SpawnChecked.Tag.Value == false then -- If there's no value, make.
			local VehC = game:GetService('ServerStorage').Veh:Clone()
			VehC.Parent = game.Workspace
			SpawnChecked.Tag.Value = true
			VehC:MoveTo(SpawnChecked.Position)
			break	
		end
	end

I’m sorry if all that was a lot to do, but I’m glad I was able to help in some way. Good luck with your game! :sweat_smile:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.