Rotate an object locally using body angular velocity

Im trying to make a game where you drive a submarine using a key pad infront of the player, im using body angular velocity to rotate the submarine, but the problem is that the submarine rotates globally.

1 Like

Yeah you can kind of do that.

Something like

local object_ang_vel = Vector3.new(pitch_dir, 0, -roll_dir).Unit
if object_ang_vel.X ~= object_ang_vel.X then object_ang_vel = Vector3.new() end
local world_ang_vel = sub.PrimaryPart.CFrame:VectorToWorldSpace(object_ang_vel)
ang_vel.AngularVelocity = world_ang_vel * ROTATE_MULT

The angular velocity is a vector that gets converted from the subs object space to world space using CFrame.VectorToWorldSpace.

It’s got a few issues though. If you don’t update it perfectly in sync with the physics engine, it’s going to apply almost the right torque but not quite. This is especially problematic if you’ve got high angular velocities or very high torques. It causes it to not really control right and sometimes go out of control. At low values it totally works tho.

Fortunately you can use the new Constraint types instead of the old, deprecated BodyMovers to do exactly what you want. Just insert an AngularVelocity object

image

… and set RelativeTo to Attachment0.

My brain is too small to understand the script you put in, is there a more simplified version of this script?

3 Likes

A bit. Let me try to explain it. Here’s a simplified version:

local object_ang_vel = Vector3.new(pitch, yaw, roll)
local world_ang_vel = sub.PrimaryPart.CFrame:VectorToWorldSpace(object_ang_vel)
ang_vel.AngularVelocity = world_ang_vel

object_ang_vel is the angular velocity you want the ship to have relative to itself, i.e. in its own object-space coordinates. You must convert that to world-space coordinates because that’s how BodyAngularVelocity works. This is done by calling VectorToWorldSpace, which is a method that converts the vector that’s passed in as a parameter - from the object-space of CFrame that the method is called on - to world space. The CFrame that VectorToWorldSpace is called on is the CFrame of the submarine.

Hope this helps a bit.

But really, you shouldn’t be using a BodyAngularVelocity for this. If you instead use an AngularVelocity like I described, you don’t have to convert anything. You just do

local object_ang_vel = Vector3.new(pitch, yaw, roll)
ang_vel.AngularVelocity = object_ang_vel 

I tired using just Angular Velocity but another problem arose, after a little bit my submarine would just randomly stop rotating

1 Like

Sounds like a different issue, AngularVelocity definitely works.