Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Best way to rotate objects around a moving point?

So, I've been trying to figure this out for a bit, but I've decided to ask for help.

I have a tank I've made, and I want a second player to be able to control the cannon on the top. Firing it isn't the issue, it's moving it.

I want to rotate all the parts in the model "TankCannon" around a union called "GunAxis", picture attached at the bottom. The first problem is rotating all those parts around a constantly moving part, and the second problem is rotating the top without an effect on the rest of the vehicle.

Thank you for any help you can give.

Center blue part is the "GunAxis" http://prntscr.com/l5grq1

1 answer

So I really only have an example, I'm not the math guy, but you can use radians (aka radius) that deals with measurements of a circle. You can use CFrame.Angles to return a rotation with 3 axis (axes) in radians. So if Pi is half a rotation in radians, then 2*Pi = full circle (360) etc. Hopefully this can help you some...

local Point = CFrame.new(0,10,0) -- The point the object will rotate around
local Offset = CFrame.new(0,0,10) -- the offset of the part (distance from it)

local Object = Instance.new("Part",workspace)
Object.Anchored = true

while true do

    -- Each iteration, we're making the Object's CFrame equal to the Point's CFrame, multiplied by the rotational CFrame, then again multiplied by the offset.

    -- "math.rad" simply converts it's numeric argument to radians.

    for i = 1,360 do
        Object.CFrame = Point * CFrame.Angles(0,math.rad(i),0) * Offset
        wait()
    end
end

Apologies for the long post, but this is from BlueTaslem regarding rotation around a single axis part (not world axis)...

That means in order to turn the part, we'll need to be using CFrame.Angles, probably CFrame.new(0, spin, 0) for some spin. So the question is how to determine spin?

We can determine a direction to the target like so:

	local direction = target - brick.Position

This has an x and a z (we don't care about the y since that's what we're rotating around) that we need to turn into an angle. When you need to convert normal coordinates into angles, you'll almost always use math.atan2:

	local spin =  math.atan2(direction.x, direction.z) + math.pi

I cannot explain exactly why that is the right formula, it's just what works. I would have expected it to just be (z, x) but that doesn't work for some reason -- ROBLOX must have a weird way they've made the matrices work out in CFrames.

Then, the part just needs to be turned using that:

1	brick.CFrame = CFrame.new(brick.Position) * CFrame.Angles(0, spin, 0)

Relative Spinning:

brick.CFrame * CFrame.Angles(0, spin, 0) won't work; since * CFrame.Angles spins by an amount, it's only correct when brick starts facing the "0" direction -- thus CFrame.new(brick.Position).

This is a bit of a problem for making it more general, so we should fix that.

There are two ways to go about this.

Calculate the angle difference and multiply by that Calculate x and z in object space. While both work for the simple case, 2 will work much better when we generalize.

It's pretty simple to accomplish that. Just compute direction in object space:

	local direction = brick.CFrame:pointToObjectSpace( target )

Since this is a relative angle, we do in fact want to use this now:

1	local spin =  math.atan2(direction.x, direction.z) + math.pi -- (same as before)
2	brick.CFrame = brick.CFrame * CFrame.Angles(0, spin, 0) -- (similar to before)

Done!

And in fact, now this works no matter how brick is rotated -- we are no longer restricted to just rotating around the (world's) y axis! It's now around the top surface of brick!

1 comment

0

Something else I’ve seen, is using hinges and bodyforce...I’m still researching myself.

This discussion is preserved as it was. New answers, comments, and votes are closed.