Add a Tilt Effect

Hello! In my project, I have a rectangular prism part that interacts with the world and acts as something of a vehicle hitbox. I also have a union operation that looks like a scooter and is just decoration, per say since it does not interact with the world; it is just constrained to the rectangular prism (which is invisible). I want to add something of a tilt effect so when the rectangular prism turns, the union operation tilts in the direction the rectangular prism is turning. I already have the information necessary to detect when the rectangular prism is turning; I just need to make it turn. I will also note that I am using an AlignOrientation constraint to handle the orientation of the rectangular prism, but for some reason it requires that the PrimaryAxes of both the rectangular prism attachment and union operation attachment are <1, 0, 0>. I tried using a HingeConstraint, but to make the union operation tilt on the correct axes, the PrimaryAxes of both aforementioned attachments need to be <0, 0, -1>. This messes with the AlignOrientation constraint and does not allow the scooter to move correctly. How can I add the tilt effect, preferably with constraints, so that the union operation tilts appropriately?

In case it helps:

Code that handles tilting the union operation (scooterAppearance) with HingeConstraint


Function that updates scooter tilt (called every frame)

local function updateScooterTilt(deltaTime: number)
	local neutralState: CFrame = scooterPhysicsBox.CFrame + scooterPhysicsBox.CFrame.UpVector * appearanceOffsetFromPhysicsBox
	local currentTurnDirection: string = scooter:GetAttribute("turnDirection")
	
	if not scooter:GetAttribute("isGrounded") or currentTurnDirection == turnDirections.none then
		--scooterTiltConstraint.TargetAngle = 0
		scooterAppearance.CFrame = scooterAppearance.CFrame:Lerp(neutralState, coordinateFrameInterpolationAlpha * deltaTime)
	elseif currentTurnDirection == turnDirections.right then
		--scooterTiltConstraint.TargetAngle = -math.deg(maxTiltAngle)
		scooterAppearance.CFrame = scooterAppearance.CFrame:Lerp(neutralState * CFrame.Angles(0, 0, -maxTiltAngle), coordinateFrameInterpolationAlpha * deltaTime)	
	elseif currentTurnDirection == turnDirections.left then
		--scooterTiltConstraint.TargetAngle = math.deg(maxTiltAngle)
		scooterAppearance.CFrame = scooterAppearance.CFrame:Lerp(neutralState * CFrame.Angles(0, 0, maxTiltAngle), coordinateFrameInterpolationAlpha * deltaTime)
	end
end

Code that handles orienting the rectangular prism (scooterPhysicsModel)


Helper function to calculate reorientation angle given alignment vector

local function calculateReorientationAngle(alignment: Vector3): number
	return math.acos(prism.CFrame.UpVector:Dot(alignment))
end

Helper function to calculate reorientation axis given alignment vector and angle

local function determineReorientationAxis(alignment: Vector3, angle: number): Vector3
	local axis = nil

	if angle < 0.00001 or angle > math.pi + 0.00001 then
		axis = Vector3.xAxis
	else
		axis = prism.CFrame.UpVector:Cross(alignment)
	end

	return axis
end

Function called every frame to align prism up vector w/ surface normal

local function updateScooterOrientation()	
	local targetCFrame: CFrame = scooterPhysicsBox.CFrame

	if surfaceNormal then
		local angle = calculateReorientationAngle(surfaceNormal)
		local axis = determineReorientationAxis(surfaceNormal, angle)

		targetCFrame = CFrame.fromAxisAngle(axis, angle) * prism.CFrame.Rotation + prism.Position
	else
		local targetUpVector: Vector3 = Vector3.new(0, 1, 0)
		local angle = calculateReorientationAngle(targetUpVector)
		local axis = determineReorientationAxis(targetUpVector, angle)

		targetCFrame = CFrame.fromAxisAngle(axis, angle) * prism.CFrame.Rotation + prism.Position
	end
	
	alignOrientation.CFrame = targetCFrame
end
1 Like

Bumping due to no responses and I haven’t figured it out

Would be nice if you sent a video to see exactly what logic error is happening.
Just spit balling, but with how you apply a visual tilt effect if your code is revolved around the rotation of the scooter itself in the first place?

Next time, I will provide a video when it will be helpful, but it appears I just fixed it. The solution was to use an AlignOrientation constraint (for tilting the union operation scooter) in addition to an AlignPosition (to make it stay with the rectangular prism) for the appearance. The HingeConstraint only allows rotating on one axis which is desirable, but it does not let you change the axis without having to rotate the the Attachment(s). I changed the code handling the appearance to:

local function updateScooterTilt(deltaTime: number)
	local neutralState: CFrame = scooterPhysicsBox.CFrame + scooterPhysicsBox.CFrame.UpVector * appearanceOffsetFromPhysicsBox
	local currentTurnDirection: string = scooter:GetAttribute("turnDirection")
	
	if not scooter:GetAttribute("isGrounded") or currentTurnDirection == turnDirections.none then
		alignOrientation.CFrame = neutralState
	elseif currentTurnDirection == turnDirections.right then
		alignOrientation.CFrame = neutralState * CFrame.Angles(0, 0, -maxTiltAngle)
	elseif currentTurnDirection == turnDirections.left then
		alignOrientation.CFrame = neutralState * CFrame.Angles(0, 0, maxTiltAngle)
	end
end
1 Like

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