Turret Rotation Problems

Aiming Issues
Making a turret that aims at where the players cursor is; however, I just realized that it doesnt aim properly when not facing directly in the +/- z direction.

The turret runs on hinges (servo). Rotate is for side to side rotations (y axis) while pitch is to look up and down. The pitch hinge part is attached to the rotate hinge constraint.

Could figure this out eventually, but I tend to overthink these things and waste alot of time, so help is appreciated.

-- Runs in loop
function aimTurret()
    if not activeSentry then return end
    local RootPart = activeSentry.TurretBase
    
    local pitch = activeSentry.Base.HingePitch.HingeConstraint
    local rotate = activeSentry.Base.HingeRotate.HingeConstraint
    
    local Pos = Mouse.Hit.Position -- Will need to include console and mobile support aswell
    
    local origin = Vector2.new(RootPart.Position.X,RootPart.Position.Z)
    local target = Vector2.new(Pos.X, Pos.Z)
    
    local beta = math.deg(math.atan((target.X - origin.X) / (target.Y - origin.Y)))
    rotate.TargetAngle = beta
    
    local mag = (Pos - RootPart.Position).Magnitude
    local y = Pos.Y - RootPart.Position.Y
    
    beta = math.deg(math.asin(y/mag))
    pitch.TargetAngle = beta
end

I have checked out other “solutions” but they all only seem to work in a single dimension.

Camera Issues
Also if this gets solved I got two more questions regarding the Turret Systems Camera. In short the camera is controlled by a part (I did not setup this method), and so I rotate the the part around based on where the mouse is aiming. I don’t want to attach the part to the hinge though, as the hinge lags behind and is also updated slower intentionally.

The Base is the center point of the turret and the camerafocus is the part that the camera is looking from. Currently the code sets the camerafocus part behind the turret at the right x/z angle however, Im a bit confused as to how I should handle the y axis. I don’t want the camera to just be stuck at a specific height (how its set up atm). The camera should be slightly above the turret no matter where its aiming. Technically getting the orthogonal angle of the unit vector I create If I use Vector3 instead of Vector2 should get me in the right direction but im just not managing to set it up properly. Honestly reading this confuses me more so hopefully this picture somewhat helps.

--Vector 2 method (No Change in Y Axis)
game:GetService("RunService"):BindToRenderStep("RotateCamera", Enum.RenderPriority.Character.Value, function()
            if activeSentry then
                local Pos = Mouse.Hit.Position
                local origin = Vector2.new(Base.Position.X,Base.Position.Z)
                local target = Vector2.new(Pos.X, Pos.Z)
                local unit = (target-origin).Unit

                local CamPos = Vector3.new(Base.Position.X - (unit.X * 12), Base.Position.Y, (Base.Position.Z - (unit.Y * 12)))

                CameraFocus.Position = CamPos
            end
        end)

Lastly I need to clamp the cameraFocus parts position. If the turret was only facing directly down a specific axis then it would not be hard but im struggling to find the rights points given the turret starting at an angled position. Turret should be able to aim ± 60 Deg left to right and ± 45 up and down from its original orientation.

1 Like

For number one if the turret has a rotating base the angle needs to be subtracted by the base.

This can be done with CFrame to object space like the function below:

https://devforum.roblox.com/t/tank-turret-faces-correctly-until-i-rotate-and-it-somehow-inverts/1785604/3?u=dthecoolest

For the second one you can get the turrets local .UpVector to get the y axis relative to the turret and adjust from there. Something like turret.Position+turret.CFrame.UpVector*10 then get the y value from that vector

For the third clamping one just get the angles, then use math.clamp to clamp the angles, the reapply the angles.

Second and third should deserve its own post though.

For the camera attach, you could just use a weld constraint attached to the turret at a pre set offset, then change the cameras lookvector where the origin is that object.

For the angle clamp, you have to use the dot product to keep the turret in the range.


2 Likes

So your solution for one worked perfectly. :+1:
As for 2 the only issue is that the turret intentionally moves slower than the camera. Then again using what you said, Ill just generate a cframe using the unit vector and the turrets base position for the look direction and get the upvector from there.
Will get to problem 3 after that, but then again, not sure how angles will help. The camerafocus block is just position based. The camera position is placed at that point and the look direction is above the turret base.

Alright, so for part 2 this is what I got now. For the most part it seems to work fine, but when I switch to aiming at nearby walls from either the ground or far off in the distance, the camera zooms in excessively. Since its a unit vector, I thought only the angle really matters in this case.

Edit. Occurs for any sudden jumps in magnitude between the target and origin, when again it should be dependent on the angle and not the distance.

local target = Mouse.Hit.Position

local origin = Base.Position
local unit = (target-origin).Unit

local cframePos = origin - unit
local cframe = CFrame.new(cframePos, Base.Position)
local upVector = cframe.UpVector

local CamPos = (origin - (unit * 12)) + (upVector * 8)

CameraFocus.Position = CamPos

On a bit of a time constraint so sorry but here’s a micro bump.

First part is answered though.

Set this up for the camera clamp atm.
This runs right before the above code in the render step bound function.
The only issue is that after moving the camera into the clamp border itll lag a bit and then set me to the opposite side.

local x, y, z = Camera.CFrame:ToOrientation()
local clampX = math.clamp(math.deg(x), -45, 45)
local clampY = math.clamp(math.deg(y), orientation-45, orientation+45)
                
Camera.CFrame = CFrame.new(Camera.CFrame.Position) * CFrame.fromOrientation(math.rad(clampX), math.rad(clampY), z)

I am sorry for bumping this topic.

I found solution for turret rotating in 1 axis thanks to this model give me idea for solution. Anyways I just found out align orientation make everything easy and with hinge constraint without lag at all and heavy computation on script. With align orientation and hinge constraint, you can make AI turret that rotate to target position WITHOUT complicated math stuff, so how it work? ActuatorType must be None and align orientation will handle rotation in 1 axis. As long align orientation rigid enabled is false.

If you still doesn’t understand then I recommended (studying / reconstructing) this model how it work.

EDIT : Align orientation rotation CAN be lag depend Responsiveness and MaxTorque.