Welding a car in a certain area

Hello again!
I post here quite often, but there’s nothing to do if I can’t find a solution.
So…
I want to do the following: If a player drives into a certain area and gets up from the driver’s seat, the car will be welded to that area.
And then when the player gets in the car again, the car is released.
I want to do such a thing for a ferry crossing game.

So far, I’ve tried to use values, put several functions in each other, and so on.
However, I’m not so good at scripting yet, and the only result I got was that the game crashed.

Here is a picture of the area where cars should weld. They should be welded to the same green part.
image

And script (probably just a bad joke)

local TouchedPart = nil

script.Parent.Touched:Connect(function(hit)
	if hit.Name == "CarDeckArea" then
		TouchedPart = hit
		script.Parent:GetPropertyChangedSignal("Occupant"):Connect(function(plr)
			if script.Parent.Occupant == nil then
				local Weld = Instance.new("WeldConstraint")
				Weld.Name = "CarDeckWeld"
				Weld.Part0 = script.Parent
				Weld.Part1 = TouchedPart
			else
				if script.Parent.Occupant ~= nil then
					if script.Parent:FindFirstChild("CarDeckWeld") then
						script.Parent:WaitForChild("CarDeckWeld"):Destroy()
					end
				end
			end
		end)
	else
		script.Parent.TouchEnded:Connect(function(hit)
			if hit.Name == "CarDeckArea" then
				return 
			end
		end)
	end
end)

Thanks!

1 Like

Will anchoring the car instead of welding be a better method for your case?

I weld just because it has to start moving with the ship. It must be attached to the ship. Later, I will move this green part to the ship model.

The Spatial Query API is a better option to use for this than Touched & TouchEnded. Every time the seat occupant changes, check to see if the player got up. If they did then query with GetPartsInPart along the lines of this snippit:

-- first, make an array of CarDeckWeld parts to use as a filtered list
local FilterList = {ship.CarDeckWeld1, ship.CarDeckWeld2}

-- second, create OverlapParams object for the query
local params = OverlapParams.new()
params.FilterType = Enum.RaycastFilterType.Whitelist
params.FilterDescendantsInstances = FilterList

-- third, handle occupant changed
car.Seat:GetPropertyChangedSignal("Occupant"):Connect(function(plr)
    if script.Parent.Occupant == nil then
        local overlappingParts = workspace:GetPartsInPart(car.BoundingPart, params)
        if #overlappingParts > 0 then
            local Weld = Instance.new("WeldConstraint")
            Weld.Name = "CarDeckWeld"
            Weld.Part0 = car.BoundingPart
            Weld.Part1 = overlappingParts[1]
        end
    end
end)

where car.BoundingPart is a part in the car, sized so it contains the entire car. that will ensure any part of the car can be parked on a CarDeckWeld part and still trigger the weld.

But how do I find the ship in line 4, If this green part is inside the ship and there are several ships in a game?


Thanks!

CollectionService is perfect for that. You can tag the green parts with an identifier, then get an array of all those tagged parts in the game using the GetTagged method.

I like this plugin for assigning tags in studio without needing to set them from code.

Edit: You dont have to manually make your FilterList array this way; you can retrieve it right from GetTagged():

-- assumes the green parts are tagged with "CarDeckWeld"
local FilterList = CollectionService:GetTagged("CarDeckWeld")

I just got this error. I’m a little confused now. I tagged the green part “CarDeckWeld” using that plugin.
The script is in a car model.
image.

You’re passing a value to a method that wants a reference to an object. I’d have to see the line of code that error is kicking from to be able to say anything more specific than that, sorry. A value is data, like in a variable. Something like workspace:GetPartsInPart("carPart", params) could kick that, because the string “carPart” cannot be cast to an object reference like the method is expecting.

Well. I’ll send everything I have right now

local car = script.Parent
local CollectionService = game:GetService("CollectionService")
 
-- first, make an array of CarDeckWeld parts to use as a filtered list
local FilterList = CollectionService:GetTags("CarDeckWeld")

-- second, create OverlapParams object for the query
local params = OverlapParams.new()
params.FilterType = Enum.RaycastFilterType.Whitelist
params.FilterDescendantsInstances = FilterList

-- third, handle occupant changed
car.DriveSeat:GetPropertyChangedSignal("Occupant"):Connect(function(plr)
	if script.Parent.Occupant == nil then
		local overlappingParts = workspace:GetPartsInPart(car.Body.BoundingPart, params)
		if #overlappingParts > 0 then
			local Weld = Instance.new("WeldConstraint")
			Weld.Name = "CarDeckWeld"
			Weld.Part0 = car.Body.BoundingPart
			Weld.Part1 = overlappingParts[1]
		end
	end
end)

Car:
image
Also

The GetTags(part) method is given a part, and returns an array of all the tag strings that have been tagged to that part. It can’t cast the string value "CarDeckWeld" to the part object it needs, which is what the error is saying.

You want to use GetTagged() instead. This method takes in a string tag and returns an array of all the parts that have that tag assigned to them.

Oh yes. I misspelled. There are no more errors.
However, the car is not welded when I leave the seat.

Verify GetTagged is returning the populated array of CarDeckWeld parts, as well as GetPartsInPart is correctly returning queried parts.

local FilterList = CollectionService:GetTags("CarDeckWeld")
print(FilterList)
local overlappingParts = workspace:GetPartsInPart(car.Body.BoundingPart, params)
if #overlappingParts > 0 then
    -- ...
else
    warn("No CarDeckWeld parts inside of car's BoundingPart")
end

FilterList print:
image
Edit: Got warning also now.

Disable log mode in your output so you can see the contents of that table instead of it’s registry address.

Make sure you have CanQuery set to true on the CarDeckWeld parts and the car BoundingParts.

Part has been found and CanQuery set to true.
image

I setup a demo place and even with CanQuery set to false; it’s still working for me.

It even works when the parts are less than a tenth of a stud overlapping.

This suggests the issue is with the tag on the CarWeldParts. Double check your spelling is identical to the string passed to GetTagged, and that there’s no leading or trailing spaces.

Everything should be working then. It’ll weld the car.Body.BoundingPart to the first overlapping part returned from GetPartsInPart. Could you have forgotten to weld the BoundingPart to the rest of the car body perhaps?

Everything seems to be spelled correctly.


I’m still getting this warning (No CarDeckWeld parts inside of car’s BoundingPart)
I have no idea.

That warning is logging when the character sits down; not when it stands up.

Based on the explorer structure in that video, this line would be checking the Occupant property on the “Bluevan” Model, not the driver’s seat.

Perhaps you meant for that to be:

car.DriveSeat:GetPropertyChangedSignal("Occupant"):Connect(function(plr)
	if car.DriveSeat.Occupant == nil then

The driver’s seat is still being checked.
image
The script is written like this. Still not working.

car.DriveSeat:GetPropertyChangedSignal("Occupant"):Connect(function(plr)
	if car.DriveSeat.Occupant == nil then

I’ll do a little more research and let you know when it starts working.