Attaching a characters hands to a steering wheel

Sorry for the really late reply but I think I have just what your looking for. I was able to make the arms point at the attachments you have in the steering wheel. The arms were too short to reach on their own so I made the character lean forward by editing the Waist joint. If you don’t want the character to lean forward and still reach the wheel you will need to adjust your model so that can happen. There is a variable in the code that controls how many degrees forward the character is leaning you can mess with that if you edit the car. If you want to make the turning more dramatic you can edit how much the steering wheel turns in your constraints properties I think, my code should still work with it

The only downside to this code is that the joint movement dont replicate to the server :confused: Something I suggest is that when the player gets on the car you could tell the server to get the character into the starting pose so its leaning forward with arms out so its touching the wheel. The actual steering part could be purely client side, if your making some kind of racing game its unlikely any other players will be paying close enough attention to notice that other player’s arms aren’t turning the wheel anyway.

You can copy and paste this into a localscript and this should work, here is my save file too just in case
ChassisSteering.rbxl (68.9 KB)

local plr = game.Players.LocalPlayer
local char = workspace:WaitForChild(plr.Name)
local handLeft = workspace.Chassis.Parts.SteeringWheel.HandLeft
local handRight = workspace.Chassis.Parts.SteeringWheel.HandRight

--These two angles were found by trial and error, adjust if you want
local characterLeanAngle = math.rad(20)--How many degrees the character is leaning forward
local neckAngle = math.rad(-15)--How many degrees the head is looking up/down

local steppedEvent

---Create Welds identical to Motor6Ds to override animations
function configureJointsForSteering()
	local rightShoulder = char:WaitForChild("RightUpperArm").RightShoulder
	local leftShoulder = char:WaitForChild("LeftUpperArm").LeftShoulder
	local rightElbow = char.RightLowerArm.RightElbow
	local leftElbow = char.LeftLowerArm.LeftElbow
	
	--Torso Weld is to keep the player leaning forward so the arms reach the steering wheel
	local torsoWeld = Instance.new("Weld")
	torsoWeld.Part0 = char.UpperTorso.Waist.Part0
	torsoWeld.Part1 = char.UpperTorso.Waist.Part1
	torsoWeld.C0 = char.UpperTorso.Waist.C0 *CFrame.Angles(-characterLeanAngle, 0, 0)
	torsoWeld.C1 = char.UpperTorso.Waist.C1
	torsoWeld.Name = "WaistWeld"
	torsoWeld.Parent = char.UpperTorso
	
	
	--Neck weld is to make the player's head look up, since the character is leaning forward the head is naturally looking down, so we need to adjust
	local neckWeld = Instance.new("Weld")
	neckWeld.Part0 = char.Head.Neck.Part0
	neckWeld.Part1 = char.Head.Neck.Part1
	neckWeld.C0 = char.Head.Neck.C0 *CFrame.Angles(-neckAngle, 0, 0)
	neckWeld.C1 = char.Head.Neck.C1
	neckWeld.Name = "NeckWeld"
	neckWeld.Parent = char.Head
	
	--Shoulder welds so we can make them move towards the steering wheel
	local rightShoulderWeld = Instance.new("Weld")
	rightShoulderWeld.Part0 = rightShoulder.Part0
	rightShoulderWeld.Part1 = rightShoulder.Part1
	rightShoulderWeld.C0 = rightShoulder.C0
	rightShoulderWeld.C1 = rightShoulder.C1
	rightShoulderWeld.Parent = rightShoulder.Parent
	rightShoulderWeld.Name = "RightShoulderWeld"
	rightShoulder = rightShoulderWeld
	
	local leftShoulderWeld = Instance.new("Weld")
	leftShoulderWeld.Part0 = leftShoulder.Part0
	leftShoulderWeld.Part1 = leftShoulder.Part1
	leftShoulderWeld.C0 = leftShoulder.C0
	leftShoulderWeld.C1 = leftShoulder.C1
	leftShoulderWeld.Parent = leftShoulder.Parent
	leftShoulderWeld.Name = "LeftShoulderWeld"
	leftShoulder = leftShoulderWeld
	
	--Elbow welds to keep the arms straight
	rightElbow = Instance.new("Weld")
	rightElbow.Part0 = rightShoulder.Part1
	rightElbow.Part1 = char.RightLowerArm
	rightElbow.C0 = CFrame.new(0, -rightElbow.Part1.Size.Y/2, 0)
	rightElbow.Name = "RightElbowWeld"
	rightElbow.Parent = char.RightLowerArm
	
	leftElbow = Instance.new("Weld")
	leftElbow.Part0 = leftShoulder.Part1
	leftElbow.Part1 = char.LeftLowerArm
	leftElbow.C0 = CFrame.new(0, -leftElbow.Part1.Size.Y/2, 0)
	leftElbow.Name = "LeftElbowWeld"
	leftElbow.Parent = char.LeftLowerArm
	
	
	return rightShoulder, leftShoulder
end


function cleanupJoints()
	local waistWeld = char.UpperTorso:FindFirstChild("WaistWeld")
	local neckWeld = char.Head:FindFirstChild("NeckWeld")
	local rs = char.RightUpperArm:FindFirstChild("RightShoulderWeld")
	local ls = char.LeftUpperArm:FindFirstChild("LeftShoulderWeld")
	local re = char.RightLowerArm:FindFirstChild("RightElbowWeld")
	local le = char.LeftLowerArm:FindFirstChild("LeftElbowWeld")
	
	if waistWeld then
		waistWeld:Destroy()
	end
	
	if neckWeld then
		neckWeld:Destroy()
	end
	
	if rs then
		rs:Destroy()
	end
	
	if ls then
		ls:Destroy()
	end
	
	if re then
		re:Destroy()
	end
	
	if le then
		le:Destroy()
	end
end

function handsOnWheel(rightShoulder, leftShoulder)
    --Find the positions on the wheel we want the hand to point to
	local rightTargetPosition = CFrame.new(rightShoulder.Part0.CFrame:PointToObjectSpace(handRight.WorldPosition)) *(rightShoulder.C0 - rightShoulder.C0.p)
	local leftTargetPosition = CFrame.new(leftShoulder.Part0.CFrame:PointToObjectSpace(handLeft.WorldPosition)) *(leftShoulder.C0 - leftShoulder.C0.p)
	
    --Adjust target positions so that the center of the hand will point to target position, otherwise the top left part of the hand will point to target position
	rightTargetPosition = rightTargetPosition *CFrame.new(-rightShoulder.Part1.Size.X/2, -rightShoulder.Part1.Size.Y/2, 0)
	leftTargetPosition = leftTargetPosition *CFrame.new(leftShoulder.Part1.Size.X/2, -leftShoulder.Part1.Size.Y/2, 0)
	
    --Rotate arms 90 degrees downward so that the end of the hand will point to target position
	local rightC0 = CFrame.new(rightShoulder.C0.p, rightTargetPosition.p) *CFrame.Angles(math.rad(90), 0, 0)
	local leftC0 = CFrame.new(leftShoulder.C0.p, leftTargetPosition.p) *CFrame.Angles(math.rad(90), 0, 0)
	
	rightShoulder.C0 = rightC0
	leftShoulder.C0 =  leftC0
end

--When someone sits in the vehicle seat
workspace.Chassis.VehicleSeat:GetPropertyChangedSignal("Occupant"):Connect(function()
	if workspace.Chassis.VehicleSeat.Occupant == char.Humanoid then
		local rightShoulder, leftShoulder = configureJointsForSteering()
		
		--Setup event that will move hands to the wheel
		steppedEvent = game["Run Service"].RenderStepped:Connect(function()
			handsOnWheel(rightShoulder, leftShoulder)
		end)
	else
		cleanupJoints()--Put joints back to normal
		
		if steppedEvent then
			steppedEvent:Disconnect()--Stop making the players hands stay on the wheel and stop memory leaks
		end
	end
end)
30 Likes