TurretController - CFrame based Joint Instance mover

Oh my god. You will NOT believe how much time you saved me…

I can’t express how much I’m thankful for this
Thank you thank you thank you :pray:

1 Like

Is there any tutorial I can watch on how to use this. I am trying to create a turret using this module but I am having a hard time understanding what to do. This seems perfect for what I need it for

Hello again! I’m wanting to implement a lot of turrets handled individually by different players, and was wondering the best way to do this. I’ve came up with these options, and was looking for some guidance as to which I should go with:

  1. Server does calculations and tells client the data needed to rotate the turrets. (How would I get just the calculations on the server?)
  2. Server handles everything from calculations to rotating in a RunService loop.
  3. Client handles everything (may be exploitable).

Why does this keep happening? It always seems to happen with my pylon joints…

https://gyazo.com/143944ba5c98d9cb5b683b3569879d64
Always happens when im not using 180,-180 Yaw and limited Pitch

I just dont get it…

Seems to be a recursive CFrame loop just like doing:

part.CFrame *= part.CFrame

Usually caused by the Motor6D setup, try to make sure the Part0 is the base and Part1 belongs to the turret.

1 Like

As far as I can tell its correct, I even tried to Frankenstein it by putting the dummies head into the rig and reconnecting the rigs and motors still didnt work particularly well. Are the parts too big or something? or is there an issue with meshparts being used?

Or could this be an issue?

local PylonEvent = game.ReplicatedStorage.TSFWeapons.ServerEvents:WaitForChild("Pylon")
local WeaponTransfer = game.ReplicatedStorage.TSFWeapons.ServerEvents:WaitForChild("WeaponTransfer")
local TC = require(game.ReplicatedStorage.TurretController)

local timeStep

function initialiseMotor(pylon)
	local motor = pylon:FindFirstChild("Motor6DJoints").Pivot.Value
	local Constraints = {
		["YawLeft"] = 180,
		["YawRight"] = 180,
		["ElevationAngle"] = 90,
		["DepressionAngle"] = 90
	}
	
	local MotorControl = TC.new(motor,Constraints)
	return MotorControl
end

function turretAim(motor,target,pylon)
	local gimbalMotor = pylon:FindFirstChild("Pivot",true).Value
	local gimbalMotorOffset = gimbalMotor.C0
	task.spawn(function()
		--print(player,pylon,motor,target)

		repeat
			motor:PIDLookAt(target,timeStep)
			task.wait()
		until pylon:GetAttribute("Auto") == false
		gimbalMotor.C0 = gimbalMotorOffset
	end)
	
end

RS.Heartbeat:Connect(function(step)
	timeStep = step
end)

PylonEvent.OnServerEvent:Connect(function(player,hardpoint,Type)
	Player[player.Name] = {LTracks,RTracks,Motors}
	print("Recieved Message")
	print(hardpoint)
	print(Type)
	if Type == "Gun" then
		if hardpoint == "LP" then
			local pylon = player.Character:FindFirstChild("GunPylonL")
			local animator = pylon.AnimationController
			print(pylon:GetAttribute("Deployed"))
			if pylon:GetAttribute("Deployed") == false then
				print("Deployed")
				Player[player.Name][1]["Deploy"] = animator:LoadAnimation(animator.DeployLeft)
				Player[player.Name][1]["Deploy"]:Play()
				task.wait(Player[player.Name][1]["Deploy"].Length - 0.05)
				Player[player.Name][1]["Deploy"]:AdjustSpeed(0)
				pylon:SetAttribute("Deployed",true)
			elseif pylon:GetAttribute("Deployed") == true and pylon:GetAttribute("Auto") == false then
				print("Deployed Rear")
				Player[player.Name][1]["Deploy"]:Stop()
				Player[player.Name][3]["PivotL"] = initialiseMotor(pylon)
				Player[player.Name][1]["Rear"] = animator:LoadAnimation(animator.DeployRear)
				Player[player.Name][1]["Rear"]:Play()
				
				--task.wait(track.Length)
				--track:Stop()
				--pylon:SetAttribute("Deployed",false)
				pylon:SetAttribute("Auto",true)
				--aimAtTarget(player,pylon,nil,workspace.Target.Position)
				turretAim(Player[player.Name][3]["PivotL"],workspace.Target.Position,pylon)
			else
				print("Retracted")
				Player[player.Name][1]["Rear"] = animator:LoadAnimation(animator.DeployRear)
				Player[player.Name][1]["Rear"]:Play(0.100000001, 1, -1)
				task.wait(Player[player.Name][1]["Rear"].Length)
				Player[player.Name][1]["Rear"]:Stop()
				pylon:SetAttribute("Deployed",false)
				pylon:SetAttribute("Auto",false)
			end
--- other parts cut as unnecessary
end

im using this for my tank turret and sometimes the turret is slightly off and when on a ramp is off by a lot
do you have any idea how to fix this?

video:

code:

local gunbaseConstraints = {
	["YawLeft"] = 180,
	["YawRight"] = 180,
	["ElevationAngle"] = 0,
	["DepressionAngle"] = 0
}

gunConstraints = {
    ["YawLeft"] = 25,
    ["YawRight"] = 25,
    ["ElevationAngle"] = 0,
    ["DepressionAngle"] = 0
},

motor6d positions
image
attachment on the right is the BaseAttachment for the GunBase (connected to the GunBase Part)
attachment on the left is the TurretAttachment fro the GunBase (connected to the part below (the turretBase)
the motor line (using rig edit lite) is directly above each other


attachment on the right is the TurretAttachment for the Gun (connected to the Gun part)
attachment on the left is the BaseAttachment for the Gun (connected to the Gunbase)
the motor is on the BaseAttachment (the orange circle)

im using PIDLookAt(mouse.Hit.Position, dt) in the HeartBeat function on the server

i switched to the normal LookAt function and it fixed it but i was using PIDLookAt so i could control the speed of the movement so im still wondering how to control that without using PID

edit: after reading through the setup again and messing around with settings i figured it out

How can i reset players rotation with this, im making a gun system like this game Isle, 9 - Roblox
but i cant reset players rotation after he uneqiups the gun.
Can someone help me?

im trying to make the barrel of my tank not move to the mouse instantly and it works for 3 of the tanks but this one for some reason doesnt work

i printed what the angularDistance is and it saids zero even though when i printed the currentRotation.LookVector and goalRotationCFrame.LookVector they were different and no way VectorUtil would return 0 for the distance

image

the code has been unchanged from the original module, again this works with all my other tanks except this one. exact same attachment orientations. exact same barrel orientation and front face

any way to fix this?

edit: found the solution, there is a bug where if the par tthat is moving has a different orientation that isnt 0,0,0 it wont rotate right

save the motor c0 when you equip and before you use the LookAt function then use the saved motor c0 and reset it when you unequip

example:

local originalRightArmC0
local originalLeftArmC0

tool.Equipped:Connect(function()
    local plr = game.Players.LocalPlayer
    local char = plr.Character or plr.CharacterAdded:wait()
    originalRightArmC0 = char.Torso["Right Shoulder"].C0
    originalLeftArmC0 = char.Torso["Left Shoulder"].C0
end)

tool.Unequipped:Connect(function()
    local plr = game.Players.LocalPlayer
    local char = plr.Character or plr.CharacterAdded:wait()
    char.Torso["Left Shoulder"].C0 = originalLeftArmC0
    char.Torso["Right Shoulder"].C0 = originalRightArmC0
end)

Hey, so im a little confused, first of all i’ve got no idea what PID is, but from what i can tell its something with more options than the default module, but is there no way to change how quickly it turns without PID? And is there no way to only have it enabled for certain controllers?

Is there some kind of :Destroy() feature on the module?

1 Like

a clean up function such as :Destroy() is not necessary as there are no instances being created by the module.

You can simply let the garbage collector do its work.

Oh, gotcha. Thanks for replying.

1 Like

I like this module, but is it possible to make parts above UpperTorso follow my mouse as well? (Animation priority: Action2)

Edit: When I mentioned the animation priority I realized idle priority only works, I am sorry.

Sorry for bumping, but is it possible to move a turret on both client side and server side smoothly? I tried the module and it worked great, except one thing I’m struggling at the moment is how I can move a turret on both sides without interrupting each other, causing the turret to stutter.

The reason I want to make it work on both sides is because the client responds faster while updating the turret movement on server side.

Here’s the video. Notice how the turret stutters when I move the turret around (if that’s not clear enough, check the 2nd video below).

I tried changing methods to update the server side like reducing event step, sending client C0, yet none of them fixed and even made it worse as shown in the video below.

So I would like to know if your module is capable of updating on both sides. If it’s not possible, that’s okay. I’ll keep figuring it out.

Clone the motor6d locally

1 Like

I’ve never thought of that solution before. Now I’ve learnt something new. Thanks a lot!

Here’s the result.

3 Likes

you made my game possible luv u bro

1 Like