A Mouse-Controlled Turret

Hey, so I’ve been trying to figure out some way to create a mouse-controlled turret using hinge constraints or CFrame, however I have no idea how to create one despite trying to research. I couldn’t find anything on the devforum or a tutorial that could help me out. The turret that I’d image would look like this:

Any help is appreciated, thank you.

1 Like

Parts with constraints are good if you want to make a mechanical model of something in the game. Things like doors, chests with lids, Ferris wheels. Here’s examples…
Door example
Ferris wheel example

Otherwise, you’ll want to implement the constraints as part of your algorithm code. Here’s an example I wrote of a turret with a periscope effect. Just paste this into a new workspace and run. Player attaches to the turret for 10 seconds and then leaves. If you want it to go longer, extend the wait at the bottom of the script or remove the leaveTurret() call.

Oh… make this a Local script located in StarterPlayer->StarterPlayerScripts.

local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:wait()
local humanoid = character:WaitForChild("Humanoid")
local RunService = game:GetService("RunService")

-- This is you turret part
local turret = Instance.new("Part")
turret.Position = Vector3.new(1, 5, -15)
turret.Size = Vector3.new(0.5, 0.5, 10)
turret.Anchored = true
turret.Parent = game.Workspace

-- Whether or not to position camera so it is sighting down the barrel
local sightDownBarrel = false

function UpdateCamera()
	local lookVector = workspace.CurrentCamera.CFrame.LookVector
	
	-- Apply angle constraints.. in this cas max +/- 20 degrees in vertical
	local maxY = math.atan(math.rad(20))
	lookVector = Vector3.new(lookVector.X, math.clamp(lookVector.Y, -maxY, maxY), lookVector.Z)
	
	local lookPoint = turret.Position + lookVector * 100000
	turret.CFrame = CFrame.lookAt(turret.Position, lookPoint)
	
	if sightDownBarrel then
		-- position camera at one end of part, looking down the barrel...
		local cameraPos = turret.CFrame:PointToWorldSpace(Vector3.new(0, turret.Size.Y / 2 + 1, turret.size.Z / 2))
		workspace.CurrentCamera.CFrame = CFrame.lookAt(cameraPos, lookPoint)
	end
end

function enterTurret()
	-- freeze character
	humanoid.WalkSpeed = 0
	humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
	
	sightDownBarrel = true
	RunService:BindToRenderStep("Turret", Enum.RenderPriority.Camera.Value + 1, UpdateCamera)
end

function leaveTurret()
	RunService:UnbindFromRenderStep("Turret")
	humanoid.WalkSpeed = 16
	humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, true)
end

enterTurret()
wait(10)
leaveTurret()
2 Likes

Is there a way to limit it’s speed or make it server-sided?

robloxapp-20210827-2338232.wmv (1.1 MB)
I thought it would be worth uploading video of the above script.

To limit speed, you’d want to switch from mouse tracking, to having distinct control zones for the mouse (zones for up, down, left, right) and move the turret using a fixed angular velocity. This is how the Roblox touch interface implements a virtual thumbstick for moving the player.

Server-side doesn’t make sense because movement inputs would have to be relayed making it laggy for the client (a problem if they’re aiming at something moving). It is also likely the Roblox engine would set network ownership of the parts to the client as an optimization anyway (unless you programmatically set them back).

The other server-side option is to build a working turret using constraints. This would be a mechanical prop players could interact with, but it would not have things like alternate camera views when you grabbed it. Think more like a prop that a player could touch and manipulate using in-game physics. You might, for example weld the control surface to their hand when they touch it so they could turn it.

1 Like