Best way to make a part's rotation match its velocity & position?

It should update as the velocity/position changes as well (so ideally looking for something that doesn’t just set the part’s rotation/cf manually every time the part position changes).

So something like this:

while wait() do
	bodyGyro.CFrame = cf(part.Position,part.Position + part.Velocity) * rot -- rot is an offset rotation
end

That code you have currently should work fine, except you need to replace cf with CFrame.new, and assuming part, rot, and bodygyro are predefined.

I’m looking for a better way to do it than that.

This should be helpful:

function CFrameFromTopBack(at, top, back) 
    local right = top:Cross(back) 
    return CFrame.new(
        at.x, at.y, at.z, 
        right.x, top.x, back.x, 
        right.y, top.y, back.y, 
        right.z, top.z, back.z) 
end

Back obviously just = the opposite of the direction it’s going, that is, the negative of Velocity.

Now you need some other piece of information about which way the “top” or “right” is facing. If you only use instantaneous values, then there’s no way to know what that value should be. You need the part’s linear acceleration in order to know which “way it’s curving in”. To do that, difference the velocity during each timestep.

local lastVelocity = part.Velocity
while true do
    local thisVelocity = part.Velocity
    local acceleration = thisVelocity - lastVelocity
    lastVelocity = thisVelocity

    bodyGyro.CFrame = 
        CFrameFromTopBack(
            Vector3.new(), 
            -thisVelocity:Cross(acceleration).unit, 
            -thisVelocity.unit) --> **EDIT** -- Forgot the .unit here the first time

    wait()
end

I’m not sure on the negatives off the top of my head without thinking too hard, just swap the two minus signs in/out until it’s pointing in the way you want, each combination of +/- will generate one of the four orientations “around” it’s facing velocity / acceleration path.

5 Likes

Even with your edit I still don’t think it works :confused:
But also what would be the advantage of doing this (assuming it works) over what I have in the OP?

Because it’s wrong to think of your problem in terms of CFrame.new(at, lookAt) * rot. You don’t need an “additional” rotation on top of the lookAt, “lookAt” is simply the wrong way to solve the problem in the first place. You’re never going to get a clean solution for what “rot” should be because that solution would involve undoing part of the work that using the “lookAt” constructor did. In fact, 99% of the time when you’re using the “lookAt” constructor, you really should be using something like what I posted. It’s a shame that Roblox doesn’t have a clean “from axis” constructor for CFrames in the API.

I got the example working. You’re right, it didn’t work before, I had to be a lot more careful handling the cases where acceleration / velocity = 0.

Script is under StarterCharacterScripts.

1 Like

I think the game is copylocked, also rot is just an offset rotation I multiply the CFrame by if the part’s front isn’t the front I actually want to face it’s velocity vector.

Edit:
I think I understand a bit more what your script is doing, but why would crossing the velocity with the acceleration be different than crossing the velocity with the old velocity? (and why is it more accurate)

Sorry unlocked it.

And, derp, you’re right, there’s no reason to add the acceleration step… it’s just needless complexity. Got tunnel visioned in on that after it was my first thought. So actually, don’t look at it even though it’s unlocked.

Just crossing the current and previous velocity if they’re different and setting the gyro’s rotation to be exactly equal to the current rotation when the velocity hasn’t changed should do what you want.

Is there any way to achieve this while using built in Roblox constraints? Or do you have to manually update it through a script?

No, constraints only solve the instantaneous state of the game at a given moment. You want to set current state = difference over a period of time here, so constraints won’t be able to help you.

3 Likes