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
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.
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.
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)
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.
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.