I think i’ve achieved the way to do it but whenevr I equip the tool the tank just breaks and starts flying and rotates the whole tank to the mouse location instead of just the turret. I figured its because of the welds but if i delete the welds the whole tank stops working. What do i do?
Explorer:
All the TankParts inside the turret is welded to the primpart and i’ve tried using attachments and a hinge but it still just rotates the whole tank instead of just the turret.
yeah, now I see the problem. You have ManualWelds on every part, (don’t use them, they are deprecated, use Weld/Motor6D instead), and you also add Motor6Ds to every part in your script, but they can’t get Active because of the initial welds.
Here’s what you need to do
remove all the manual welds from the tank model (you can select them fast by typing in explorer c:weld (searches by class name)) (make sure all parts are anchored so they don’t fall on start)
think of Motor6Ds or Welds as joints that connect 2 parts together (the difference is Motor6D can be used in animations). When you add them, you should only modify the CFrame of these connected parts through the joints, otherwise it will break.
So anyways, if you want to rotate your turret and all its child parts, you need to
connect all turret’s children with motor6D/weld to 1 main turret part that will be rotated (in your case that would be the “PrimPart”
this is how your code in the “Framework” script should look like:
-- Welds everything to main part
for _, BasePart in pairs(script.Parent.Parent.BodyKit:GetDescendants()) do
if BasePart:IsA("BasePart") and BasePart.Name ~= "InvisParts" then
BasePart.CanCollide = false
BasePart.Massless = true
local Weld = Instance.new("Motor6D")
Weld.Parent = BasePart
if BasePart.Parent.Name == "Turret" and BasePart.Name ~= "PrimPart" then
Weld.Part0 = BasePart.Parent.PrimPart
else
Weld.Part0 = script.Parent.Parent.MainPart
end
Weld.Part1 = BasePart
Weld.C0 = Weld.Part0.CFrame:Inverse() * BasePart.CFrame
BasePart.Anchored = false
end
end
connect the PrimPart to the main tank part. This is the joint that you’re going to modify. Your mistake was that you modified the part’s CFrame directly. Instead you should modify the joint’s C0 property. Here’s how your code in “LocalScript” should look like
the only remaining thing would be to make the mouse position be relative instead of absolute, because the C0 is a relative CFrame of your part. You can check out this thread for it: Making a motor6d point in direction of mouse
Hello. I’ve tried doing this as best as i can and maybe i did something wrong but it doesnt seem to work. Whenever i test play the tracks fall apart and the turret also falls apart even though I anchored it.
Here is the updated version of th rbx file. tankhelp.rbxl (674.5 KB)
Ok i got you, here’s the project that is working for me: tankhelp_fix.rbxl (673.2 KB)
Here I removed the manualWelds only from BodyKit parts, because your tank driving script was dependent on the other welds, so I kept them. Also there was an issue with unanchoring parts before adding the motor6Ds which was causing them to fall down, so I moved it to the end
--Welds everything to main part
for _, BasePart in pairs(script.Parent.Parent.BodyKit:GetDescendants()) do
if BasePart:IsA("BasePart") and BasePart.Name ~= "InvisParts" then
BasePart.CanCollide = false
BasePart.Massless = true
local Weld = Instance.new("Motor6D")
Weld.Parent = BasePart
if BasePart.Parent.Name == "Turret" and BasePart.Name ~= "PrimPart" then
Weld.Part0 = BasePart.Parent.PrimPart
else
Weld.Part0 = script.Parent.Parent.MainPart
end
Weld.Part1 = BasePart
Weld.C0 = Weld.Part0.CFrame:Inverse() * BasePart.CFrame
BasePart.Anchored = false
end
end
If you’re not planning to use animations on them, you can replace the motor6Ds with weld.
Is there a way to disable rotation up and down so it only rotates like an actual tank would? Also the turret doesn’t seem to point to the mouse cursor.
Hello. I attempted to make it so the turret only moves side to side because rn its moving up and down which isnt realistic but I couldn’t quite figure out how to do that.
I’ve also moved the turret rotation script into the serverscript so it rotates on all clients.
And also is it possible to have the turret actually aim to the position of the cursor? cuz its about 90 degrees to the left side when i point forward.
and if you want it to only move on X axis, you should just change the Y position to be the same as the turret’s instead of the mouse. Here’s how your code should be:
local body = script.Tank.Value.BodyKit
local tool = script.Parent
local event = game.ReplicatedStorage.TankTurretRotation
local TurretUnion = script.Tank.Value.BodyKit.Turret.PrimaryPart
local function worldCFrameToC0ObjectSpace(motor6DJoint, worldCFrame)
local part1CF = motor6DJoint.Part1.CFrame
local c1Store = motor6DJoint.C1
local c0Store = motor6DJoint.C0
local relativeToPart1 =c0Store*c1Store:Inverse()*part1CF:Inverse()*worldCFrame*c1Store
relativeToPart1 -= relativeToPart1.Position
local goalC0CFrame = relativeToPart1+c0Store.Position--New orientation but keep old C0 joint position
return goalC0CFrame
end
event.OnServerEvent:Connect(function(plr, mousePosition)
local lookPos = Vector3.new(mousePosition.X, TurretUnion.CFrame.Position.Y, mousePosition.Z)
local goalCF = CFrame.lookAt(TurretUnion.CFrame.Position, lookPos)
TurretUnion.Motor6D.C0 = worldCFrameToC0ObjectSpace(TurretUnion.Motor6D, goalCF)
end)
Oh my god this is awesome thank you so much . I’ve been trying to make this work for 2 weeks now and finally you’ve helped me. This is so helpful thank you very much.
Whilst we’re here is it also possible to make the barrel part of the turret go up down? And if you cant/dont want to then thats perfectly fine you’ve already helped so much. Thank you
No problem Barrel up and down can be done exactly the same way as the turret, the only difference would be to change the Y axis instead of X like in turret’s case. I’m sure you can figure it out.
For shooting, you can try google-ing or searching it on youtube, there are lots of videos & roblox forum topics explaining how it is done.
If you’ll have questions with them, you can just make a new topic like you made this one
here’s a good video I found on turret rotation and shooting, you can check it out. It also uses hingeConstraints for rotation, so you can try that way for rotation as well
Hello. Thanks for this video. It was quite helpful.
I have 1 more request that i can’t quite figure out on my own and i figured you’d know why.
So the turret being locked is great but whenever i go down hill for example it stays level and doesnt like follow the tank if that makes sense.
-- Function to calculate C0 from the world CFrame
local function worldCFrameToC0ObjectSpace(motor6DJoint, worldCFrame)
local part1CF = motor6DJoint.Part1.CFrame
local c1Store = motor6DJoint.C1
local c0Store = motor6DJoint.C0
local relativeToPart1 = c0Store * c1Store:Inverse() * part1CF:Inverse() * worldCFrame * c1Store
relativeToPart1 -= relativeToPart1.Position
local goalC0CFrame = relativeToPart1 + c0Store.Position
return goalC0CFrame
end
local rotationSpeed = 0.05
event.OnServerEvent:Connect(function(plr, mousePosition)
local turretPos = TurretUnion.CFrame.Position
local lookPos = Vector3.new(mousePosition.X, turretPos.Y, mousePosition.Z) -- Adjust Y to maintain current height
local goalCF = CFrame.lookAt(turretPos, lookPos, Vector3.new(0, 1, 0)) -- Ensure up vector is vertical
local currentCF = TurretUnion.Motor6D.C0
local newCF = worldCFrameToC0ObjectSpace(TurretUnion.Motor6D, goalCF)
TurretUnion.Motor6D.C0 = currentCF:Lerp(newCF, rotationSpeed)
end)
oh, you’re correct, my bad. You should actually change it to only affect Y component after converting it to relative cframe. Here’s the fix:
event.OnServerEvent:Connect(function(plr, mousePosition)
local goalCF = CFrame.lookAt(TurretUnion.CFrame.Position, mousePosition)
goalCF = worldCFrameToC0ObjectSpace(TurretUnion.Motor6D, goalCF)
local _, y, _ = goalCF:ToOrientation() -- Get the X, Y, Z rotation components
goalCF = CFrame.new(goalCF.Position) * CFrame.Angles(0, y, 0)
TurretUnion.Motor6D.C0 = TurretUnion.Motor6D.C0:Lerp(goalCF, rotationSpeed)
end)
Hello. Found another small issue that i also dont know how to fix. Sorry for asking so much
I’ve made a rotationspeed so its like an actual tank but wheever the players FPS is set to 240 for example the speed is insanely fast and vice versa.
How do i fix this?
-- Function to calculate C0 from the world CFrame
local function worldCFrameToC0ObjectSpace(motor6DJoint, worldCFrame)
local part1CF = motor6DJoint.Part1.CFrame
local c1Store = motor6DJoint.C1
local c0Store = motor6DJoint.C0
local relativeToPart1 = c0Store * c1Store:Inverse() * part1CF:Inverse() * worldCFrame * c1Store
relativeToPart1 = relativeToPart1 - relativeToPart1.Position
local goalC0CFrame = relativeToPart1 + c0Store.Position
return goalC0CFrame
end
local rotationSpeed = 0.02 -- Adjust the rotation speed as needed
event.OnServerEvent:Connect(function(plr, mousePosition)
local turretPosition = TurretUnion.CFrame.Position
local lookAtDirection = (mousePosition - turretPosition).unit -- Direction to look at
-- Calculate the goal orientation
local goalLookAtCF = CFrame.lookAt(Vector3.new(), Vector3.new(lookAtDirection.X, 0, lookAtDirection.Z))
-- Convert to local CFrame relative to Motor6D
local goalCF = worldCFrameToC0ObjectSpace(TurretUnion.Motor6D, goalLookAtCF)
-- Extract Y rotation to maintain turret's current Y rotation
local _, y, _ = goalCF:ToOrientation()
goalCF = CFrame.new(goalCF.Position) * CFrame.Angles(0, y, 0)
-- Gradually rotate towards the goal
TurretUnion.Motor6D.C0 = TurretUnion.Motor6D.C0:Lerp(goalCF, rotationSpeed)
end)