Help with limiting rotation of cframe of turret

So I have a turret and when the player clicks, it takes the players camera rotational cframe and applies it to the turret so the turret faces in the direction of the players camera. However the issue i have is i want it so if the players camera is facing upwards and they click, i dont want the turret to point directly upwards just face in the direction of the camera and not rotated in an upwards direction.

I have no idea how I would clamp this. I could get the lookvector of the camera, clamp the upwards vector, but then i dont know how to make a lookvector back to a rotational cframe to apply to the turret. Any ideas?

Maybe try to clamp the orientation of the turret

Do you mind explaining more in depth how to do this?

I am going to use a base part as an example,

local Part = Instance.new("Part")
Part.Anchored = true
Part.CanCollide = false
Part.Parent = workspace
coroutine.wrap(function()
    while task.wait() do
local ClampedYAxis = math.clamp(Part.Orientation.Y,-45,45)
Part.Orientation = Vector3.new(Part.Orientation.X,ClampedYAxis,Part.Orientation.Z)
end
end)()

This will basically limit it

No but I need to clamp a rotational vector of the camera as it does not have an orientation property. This is the problem i am stuck on.

Turret or camera? im confused on which one here

So In my OP I said that I get the rotational vector of the camera (by doing camera.CFrame - camera.CFrame.Position) and I want to clamp it so that it can’t point directly up only side to side. Then apply this CFrame to the turret.

I encountered this problem when making my turret system and ended up coming up with a hacky yet effective solution using a dummy attachment.

One way to get the “Orientation” of the camera is to create a dummy attachment, and then give it the same CFrame as the camera using the following code:

local dummyattachment = Your.Attachment.Here
local camera = workspace.CurrentCamera

-- align our attachment with the camera
dummyattachment.WorldCFrame = camera.CFrame
-- now that our attachment's orientation matches the camera's, lets apply the constraint to the dummy attachment and then set the camera's orientation to match the attachment's!
local constrainedY = math.clamp(dummyattachment.WorldOrientation.Y, -45, 45) -- apply constraint
dummyattachment.WorldOrientation = Vector3.new(dummyattachment.WorldOrientation.X, constrainedY, dummyattachment.WorldOrientation.Z)
-- now lets cframe the camera to match our newly constrained dummy attachment
camera.CFrame = dummyattachment.WorldCFrame

Now it’s important to note that even though in the code example I only constrained the Y axis, these constraints can be applied to any axis you want. It’s also important to use WorldCFrame and WorldOrientation, because an attachment’s CFrame and Orientation only reflect their offset from the part they are parented to.

You could alternatively use camera.CFrame:ToOrientation(), which will return an orientation X, Y, and Z variable for you to work with.

4 Likes

i think you can use Camera.CFrame:ToOrientation() to get the orientation

1 Like

Thank you so much! Using an attachment and editing its orientation property’s, Genius! But with the ToOrientation method, I have to apply the rotation to a weld which used cframe. So is there a way to turn a cframe to a orientation, then back to a cframe?

Edit: (off topic from cframes) how did you make the turret server to client? Did you send all information from local script to server to apply orientation changes to server? Or simply set the network owner of the turret to the player?

1 Like

Yep there is a method already called

CFrame.fromOrientation(x,y,z)

Where the angles are in radians, might be better with an attachment method like @yelowfat idea in order to avoid these angle conversions haha.

For the replication it’s complex, I do not believe you can use network owner as for CFrames they are not physics based, hence do not undergo physics replication.

My procedures:

  1. Clone Motor6D locally/weld

  2. Move turret clientally with local Motor6D Instance

  3. At the same time Fire server with the orientation x,y,z rotations

  4. Tween server Motor6D towards x,y,z

cloning the Motor6D locally is done in order to prevent server → client automatic replication ruining the smooth client rotation as seen here:

The result end effect, I believe the actual KB/s is around 2 KB/s which is well below the 50 KB/s roblox remote limit before it starts becoming laggy:

Yep! You can use CFrame.fromOrientation() like @dthecoolest said in their reply.

I ended coming up with a physics-based solution for my turret using more or less the following method:

  • all moving parts on the turret and unanchored and connected to each other using weldConstraints
  • this group of moving parts is moved around a pivot point using a BallSocketConstraint (with rigidity enabled, and all limits set to zero. I made the system before RigidConstraints came out, so I would go with those for new projects. The purpose of the constraint is to align the cframe of two attachments (one connected to the base of the turret, and one connect to the anchor of the moving parts. I chose to use attachments instead of anchoring the turret and using remove events because I found that physics replicated automatically when I set the turret’s NetworkOwnership to the player, and much more smoothly/naturally too, due to the way physics are interpolated.
  • This method requires no remote events, only the moving of an attachment. The server really only handles setting up networkOwnership and adding Controller scripts to the character.

Check out the testing place:
https://www.roblox.com/games/8029739842/Turret-System-Testing
the turrets are at the bottom of the map, you will have to walk off the spawn to get to them