I have this turret that’s made of several parts. A base, a swivel connected to the base by a servo where it rotates on the yaw axis, an arm connected to the swivel, and a barrel connected by a servo to the arm.
The video shows the swivel facing the wrong direction when the base is rotated.
local targetObject = script.Parent.testLookAt
while wait() do
local baseTargetPos = targetObject.Position - script.Parent.suzan.Position
local barrelTargetPos = targetObject.Position - script.Parent.barrelPivotReference.Position
local baseAngle = math.deg(math.atan2(baseTargetPos.X,baseTargetPos.Z)) * -1
local barrelAngle = math.deg(math.atan2(barrelTargetPos.Y,barrelTargetPos.Z))
script.Parent.suzan.hingeSwivel.TargetAngle = baseAngle
script.Parent.armHoldingBarrel.hingeSwivel.TargetAngle = barrelAngle
end
The calculation for the barrel angle is taking into account the sign of the z component of the target displacement, so this will make it rotate its zenith over 90 degrees while the base rotates its azimuth to face it.
For a general fix, I would get the displacement of the target relative to the the base’s CFrame and offset by the barrel’s pivot position, most easily using the CFrame:PositionToObjectSpace() method (so you could place it on an incline or something).
Then to get the horizontal component to input into the barrel angle equation, I would just find it by using the Pythagorean formula for the local x and z components.
Reference diagram:
-- I assume the base is oriented so its local y direction is up and its local z direction is forward
local baseCF = -- world cframe of the base
local barrelPivotDisp = barrelPivotPos - baseCF.Position -- here barrelPivot is the world position of the barrel pivot
local targetPos = targetObject.Position
local v1 = baseCF:PositionToObjectSpace(targetPos) -- equiv to :VectorToObjectSpace but factoring in Cf's position
local v2 = baseCF:PositionToObjectSpace(targetPos - barrelPivotDisp)
-- these may need some swign swaps depending on how the hinges are configured
local baseAngle = math.deg(math.atan2(v1.X,v1.Z)) * -1
local barrelAngle = math.deg(math.atan2(v2.Y, math.sqrt(v2.X * v2.X + v2.Z * v2.Z)))
I plugged in the code and it’s doing this snapping rotation. I don’t have a lot of experience with Vector math, so I have no idea what could be causing this, but if I had to guess, I think it would be changing PositionToObjectSpace to PointToObjectSpace because PositionToObjectSpace would return an error. So I tried both VectorToObjectSpace (2.6 MB) and PointToObjectSpace (2.1 MB).
local targetObject = script.Parent.testLookAt
local base = script.Parent.base
local suzan = script.Parent.suzan
local barrel = script.Parent.barrel
local arm = script.Parent.armHoldingBarrel
local barrelPivot = script.Parent.barrelPivotReference
while task.wait() do
--[[local baseTargetPos = targetObject.Position - suzan.Position
local barrelTargetPos = targetObject.Position - barrelPivot.Position
local baseAngle = math.deg(math.atan2(baseTargetPos.X,baseTargetPos.Z)) * -1
local barrelAngle = math.deg(math.atan2(barrelTargetPos.Y,barrelTargetPos.Z))
suzan.hingeSwivel.TargetAngle = baseAngle
arm.hingeSwivel.TargetAngle = barrelAngle]] --OLD CODE
--//AIMING//--
-- I assume the base is oriented so its local y direction is up and its local z direction is forward
local baseCF = base.CFrame --//this previously wasn't defined before//--
local barrelPivotDisp = barrelPivot.Position - baseCF.Position -- here barrelPivot is the world position of the barrel pivot
local targetPos = targetObject.Position
--//changed to PointToObjectSpace because point to object space returned an error//--
local v1 = baseCF:PointToObjectSpace(targetPos) -- equiv to :VectorToObjectSpace but factoring in Cf's position
local v2 = baseCF:PointToObjectSpace(targetPos - barrelPivotDisp)
-- these may need some swign swaps depending on how the hinges are configured
local baseAngle = math.deg(math.atan2(v1.X,v1.Z)) * -1
local barrelAngle = math.deg(math.atan2(v2.Y, math.sqrt(v2.X * v2.X + v2.Z * v2.Z)))
suzan.hingeSwivel.TargetAngle = baseAngle
arm.hingeSwivel.TargetAngle = barrelAngle
end
Oh my bad, CFrame:PointToObjectSpace() is the correct method, and I incorrectly though it was called :PositiionToObjectSpace()
As for the issue. I’m noticing the parts are cylinders, so that will mess up the vectors when they are translated into local space, since the local y vector for cylinders is one the the curved faces and the local x vector is the flat face. So, I think you may need to switch the x and y axes in the calculation and then play around with the signs on the axes until you get the correct mechanism:
local baseAngle = math.deg(math.atan2(v1.Y,v1.Z)) -- may need to change the sign one or both axes
local barrelAngle = math.deg(math.atan2(v2.X, math.sqrt(v2.Y * v2.Y + v2.Z * v2.Z))) -- may need to change the sign on the x axes
Btw, the model you linked is not available to get. If you want, you can upload a .rbxm file in a reply and I can take a look at it.
Oh my goodness! Thank you! It works flawlessly! video of it working (3.2 MB)
local targetObject = script.Parent.testLookAt
local base = script.Parent.base
local suzan = script.Parent.suzan
local barrel = script.Parent.barrel
local arm = script.Parent.armHoldingBarrel
local barrelPivot = script.Parent.barrelPivotReference
while task.wait() do
--//AIMING//--
-- I assume the base is oriented so its local y direction is up and its local z direction is forward
local baseCF = base.CFrame --//this previously wasn't defined before//--
local barrelPivotDisp = barrelPivot.Position - baseCF.Position -- here barrelPivot is the world position of the barrel pivot
local targetPos = targetObject.Position
--//changed to PointToObjectSpace//--
local v1 = baseCF:PointToObjectSpace(targetPos) -- equiv to :VectorToObjectSpace but factoring in Cf's position
local v2 = baseCF:PointToObjectSpace(targetPos - barrelPivotDisp)
-- these may need some swign swaps depending on how the hinges are configured
local baseAngle = math.deg(math.atan2(v1.Z,v1.Y)) -- may need to change the sign one or both axes
local barrelAngle = math.deg(math.atan2(v2.X, math.sqrt(v2.Z * v2.Z + v2.Y * v2.Y)))*-1 -- may need to change the sign on the x axes
suzan.hingeSwivel.TargetAngle = baseAngle
arm.hingeSwivel.TargetAngle = barrelAngle
end