How to calculate internal Y offset when character is sitting down?

When a player sits in a seat, the character gets properly positioned. I am trying to find the formula to recreate this

At the moment. the C0 offset is the seat.Size.Y/2, what I’m more interested in is calculating the C1 offset

image

1 Like

@XAXA found the precise solution!

local forceSit = function(character: Model, humanoidRootPart: BasePart, humanoid: Humanoid, part: BasePart)
	local joints = humanoidRootPart:GetJoints()
	for _, joint in joints do
		if joint.Name == "SeatWeld" then joint:Destroy() end
	end

	local leftUpperLeg = character:FindFirstChild("LeftUpperLeg") :: BasePart?
	local rootJoint = character:FindFirstChild("Root", true) :: Motor6D?
	local leftHip = character:FindFirstChild("LeftHip", true) :: Motor6D?

	local seatThickness = part.Size.Y

	local hrpToTopOfSeat = 0
	if leftUpperLeg ~= nil and leftUpperLeg:IsA("BasePart") and leftHip ~= nil and leftHip:IsA("Motor6D") and rootJoint ~= nil and rootJoint:IsA("Motor6D") then
		hrpToTopOfSeat = rootJoint.C0.Position.Y - rootJoint.C1.Position.Y + leftHip.C0.Position.Y + leftHip.C1.Position.Z - leftUpperLeg.Size.Z / 2
	end

	local weld = Instance.new("Weld")
	weld.Part0 = part
	weld.Part1 = humanoidRootPart
	weld.C0 = CFrame.new(0, seatThickness / 2, 0) * CFrame.fromOrientation(-math.pi / 2, 0, 0)
	weld.C1 = CFrame.new(0, hrpToTopOfSeat, 0) * CFrame.fromOrientation(-math.pi / 2, 0, 0)
	weld.Name = "SeatWeld"
	weld.Parent = part

	return weld
end

Original post (approximate solution):

After some experimentation, I came up with this expression for R15:

(HumanoidRootPart.Size.Y + LeftUpperLeg.Size.Z) / -2

Interestingly (debatable), it does not resort to the right leg if the left leg has been severed. If it is missing, the leg term is simply zero.

As for R6:

(HumanoidRootPart.Size.Y + 1) / -2
2 Likes

you could do character:GetExtentsSize().Y

You could do it like this (at least this is what I think you’re trying to do (custom seat attempted).

Also, apologies in advance for the terrible scripting practices–if I’m being honest I just didn’t care enough to make it look pretty.

SCRIPT MADE IN R6 ENVIRONMENT! MODIFY FOR R15 IF NEEDED.

By the way, it doesn’t work entirely like a ROBLOX seat because you can immediately exit it by holding space. I didn’t feel a need to actually correct this feature.

Setup:

local recent = nil

script.Parent.Touched:Connect(function(p)
	if script.Parent.Weld.Part1 then return end

	local c = p:FindFirstAncestorOfClass("Model")

	if c == recent then return end

	c.Humanoid.Sit = true

	recent = c

	script.Parent.Weld.Part1 = c.HumanoidRootPart
	script.Parent.Weld.C1 = CFrame.new(0, -c["Left Leg"].Size.Z - c.Torso.Size.Y / 2, 0)
	
	local f

	f = c:FindFirstChildOfClass("Humanoid"):GetPropertyChangedSignal("Sit"):Connect(function()
		if c.Humanoid.Sit then return end

		script.Parent.Weld.Part1 = nil

		task.wait(1)

		recent = recent ~= c and recent
		
		f:Disconnect()
	end)
end)

I’m going to mark this as the solution

Edit: After further testing, this does not seem to be a 1:1 match but it is close. It would be nice if Roblox would document these things!

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