Rotate BodyGyro in local CFrame

I’m working on creating a Mario Kart themed game, and I’m working on programming the hovercar, so you can drive around on sideways or upside-down grounds.

It’s working well enough, although I can’t get the car to turn on its local axis.

I’ve tried a few things, looked for similar posts on the DevForum, looked at CFrame and Vector3 on the Developer Hub, and even looked on a few other websites too. I’ve done all I can think of to do this, but I’ve never done anything specifically like this before so I have no examples to help me.

As said in the title, the car is set up with Body Movers. I have a single script called ‘Engine’ that runs the whole thing. In the car’s seat is a BodyGyro and BodyVelocity. My problem is with the BodyGyro, since it uses a global CFrame to function.



---- Body Mover Goals (section of setting physic variables)
local xv = velocity.Velocity.X
local yv = velocity.Velocity.Y
local zv = velocity.Velocity.Z
local xg = base.Orientation.X
local yg = base.Orientation.Y
local zg = base.Orientation.Z

local hoverTurn = function() -- This is the function for turning the car
    yg = yg + turn -- This turns it on the global axis, when I want the local axis.
    turn = turn*0.9

while wait() do
    if not script.HoverWheels.Value then
        --(Code for normal car)
        -- Float
    	-- Accewhilellerate
    	-- Turn
    	hoverTurn() -- Here's the turn function
    	-- Gravity
    	-- Apply
    	velocity.Velocity =, yv, zv)
    	gyro.CFrame = * CFrame.Angles(math.rad(xg), math.rad(yg), math.rad(zg)) -- Apply physics for BodyGyro

I ran into a similar problem when making my hoverbike adapt to the ground’s surface normal. Check this out if you haven’t already!

1 Like

This looks like it would probably work, but since that post is solving a different problem, and providing examples for your code, could you help explain where what lines go and all? It’s getting very confusing dealing with 3 problems right now in this game.

It could also be that I’m newer to Roblox Lua than you are.

1 Like

Okay! So the code snippet given by sircfenner there lets you construct a CFrame given a forward vector (in this case the camera’s LookVector), an upwards pointing vector (the ground surface normal, which you can get from raycasts) and a right-pointing vector, which you just get by crossing the look and up vectors as shown there.

Here’s an example:

local camera = game.Workspace.CurrentCamera
local ray =,-cartChassis.CFrame.UpVector*32) -- Create a ray from the kart chassis that points downwards relative to the cart to check for ground. Shorter raycasts use less resources.
local hit,position,upVector,material = game.Workspace:FindPartOnRay(ray)
if upVector then -- Make sure there is a normal, and thus also ground.
    local lookVector = camera.CFrame.LookVector
    local rightVector = lookVector:Cross(upVector)
    local gyroGoal =
        0, 0, 0
        rightVector.x, upVector.x, -lookVector.x,
        rightVector.y, upVector.y, -lookVector.y,
        rightVector.z, upVector.z, -lookVector.z
    ) -- Credit to sircfenner for this!
    cartChassis.Gyro.CFrame = gyroGoal

Of course, you can substitute the camera’s LookVector for the mouse’s pointing vector instead. If you want a better explanation, just say the word.

1 Like

Just make a raycast under the seat or whatever your car base is and get the CFrame normal which will be the BodyGyro.CFrame. I think that should work.

1 Like

@Auhrii and @ADUPS, thanks for the help, but I must not have made the title specific enough. What I need help with is making the car turn (as if with a steering wheel) on the car’s local axis instead of the game’s.

The info you have already given me was good though, I used it and it is a lot better than what i had already!

Sadly, while using it I have encountered another problem other than the inability to turn the car. Now, when the car hits a wedge, it stops and does not turn to go up. I have tested in run mode with having the car above a wedge, then fall onto it, and it does change to the ground’s surface. So, at least we know it works and I typed it correctly.

So now I have to problems (which are pretty relative, if I figure out one I could probably do the other in a similar way) which I would like help with. More specifically, I need help with turning and moving the car on its local axis using a BodyGyro and BodyVelocity.

Here’s the updated hoverFloat function:

function hoverFloat()
local hoverFloat = function()
	local ray =, -base.CFrame.UpVector*32)
	local hit, position, upvector, material = workspace:FindPartOnRay(ray)
	if upvector then
		local lookvector = base.CFrame.LookVector
		local rightvector = lookvector:Cross(upvector)
		local gyroGoal =
			0, 0, 0,
			rightvector.X, upvector.X, -lookvector.X,
			rightvector.Y, upvector.Y, -lookvector.Y,
			rightvector.Z, upvector.Z, -lookvector.Z
		gyro.CFrame = gyroGoal
1 Like

Ah, I see! There are functions you can use to convert a world space CFrame into an object space CFrame and vice-versa, as luck would have it! Check here, under Functions - specifically you’re probably after CFrame:ToObjectSpace and CFrame:ToWorldSpace (the latter to convert your object-aligned rotation to world CFrame for the BodyGyro):

I’m a little pressed for time right now, but if you need anything further, don’t hesitate to ask!


Thanks! Those will probably work. I started trying to use them earlier, but I’m still finding problems I can hopefully solve on my own.

Thanks for verifying I’ve found the right thing.

1 Like