Hello! I am trying to make a scooter tilt whenever it turns via the CFrame. My model consists of a “physics box” which is a rectangular prism interacting with the world and an “appearance” which is the thing that makes the scooter look like a scooter and is something of an aesthetic thing since it can’t collide with anything. My goal to make this appearance tilt relative to the physics box and according to the physics box turn direction.
I already have a system in place where I can just access the current turn direction and so this is essentially the code so far:
local physicsBox: Part = -- physics box
local appearance: UnionOperation = -- scooter appearance
local function updateTilt()
local maxTiltAngle = 20 -- degrees
if currentTurnDirection == turnDirections.none then
appearance.CFrame = appearance.CFrame:Lerp(physicsBox.CFrame, 0.05)
elseif currentTurnDirection == turnDirections.right then
-- TODO: Tilt appearance right
elseif currentTurnDirection == turnDirections.left then
-- TODO: Tilt appearance left
end
end
RunService.Heartbeat:Connect(updateTilt)
bumping since I haven’t found a solution yet; I tried this but it didn’t quite do the trick… it doesn’t always tilt the correct direction and it results in the back of the scooter being lifted up
local appearanceOffsetFromPhysicsBox: number = -- appearance offset from physics box
local function updateTilt()
local neutralState: CFrame = scooterPhysicsBox.CFrame + scooterPhysicsBox.CFrame.UpVector * appearanceOffsetFromPhysicsBox
if currentTurnDirection == turnDirections.none then
scooterAppearance.CFrame = scooterAppearance.CFrame:Lerp(neutralState, 0.05)
elseif currentTurnDirection == turnDirections.right then
scooterAppearance.CFrame = scooterAppearance.CFrame:Lerp(neutralState * CFrame.fromAxisAngle(neutralState.LookVector, maxTiltAngle), 0.05)
elseif currentTurnDirection == turnDirections.left then
scooterAppearance.CFrame = scooterAppearance.CFrame:Lerp(neutralState * CFrame.fromAxisAngle(neutralState.LookVector, -maxTiltAngle), 0.05)
end
end
I think you might be overcomplicating this a bit, have you tried using CFrame.Angle? You can use that to obtain a tilt motion. If I were to guess, the tilting angle would be on the Z axis.
local physicsBox: Part = -- physics box
local appearance: UnionOperation = -- scooter appearance
local maxTiltAngle = 20 -- degrees
local function updateTilt()
local tiltAngle = maxTiltAngle
if currentTurnDirection == turnDirections.none then
appearance.CFrame = appearance.CFrame:Lerp(physicsBox.CFrame, 0.05)
elseif currentTurnDirection == turnDirections.right then
appearance.CFrame = appearance.CFrame:Lerp(physicsBox.CFrame * CFrame.Angles(0, 0, math.rad(tiltAngle)), 0.05)
elseif currentTurnDirection == turnDirections.left then
appearance.CFrame = appearance.CFrame:Lerp(physicsBox.CFrame * CFrame.Angles(0, 0, math.rad(-tiltAngle)), 0.05)
end
end
RunService.Heartbeat:Connect(updateTilt)
This may not be exactly what you want, but hopefully it helps put you in the right direction. (Let me know if it doesn’t, though)
Thank you for your response! It works exactly as expected! I wasn’t understanding CFrame.Angles; I thought that multiplying with that was like multiplying using the static Z axis in the world coordinate system, so I tried multiplying by an angle about the look vector of the physics box (which is the Z coordinate like you suspected) thinking that would transform the local space value I was looking for to world space. But it looks like I had the wrong impression. Thank you again!
Well, for your reference, (and for others reference) multiplying/dividing any CFrame with another CFrame would be treated as local space instead of world space. If you wanted to move something into world space, you would add/subtract the CFrame with a Vector3.
The use of CFrame.fromAxisAngle is for “rotating a CFrame from a unit Vector3 and a rotation in radians”.
So, when you were using it within your other attempt, you were actually rotating it in the direction of where your LookAt, which would be angle X, hence why your scooter was resulting in the “back of the scooter being lifted up”.
Aside from that, I’m glad my assistance did help you with your scooter physics, and I wish you good luck on the project. (When you’re done, maybe you could showcase it to us for feedback?)