Since ROBLOX updated the constraints (especially for Hinges), I’ve been pretty confused on how to do them.
I’m working on this tank model:
So far, I was able to make its turret move around with a turret I use in one of my other games, 2 Player Military Tycoon.
This is how it functions:
https://gyazo.com/ba7a556b1e8dc7282d838ec2ea28422a
https://gyazo.com/f4aaa94abfb85718837fea2a74623490
However, as you can see, there’s a few issues with the turret’s movement:
- The turret seems to be higher than it should be, giving it a weird look. This might be a problem with the modeling of the tank itself.
- The movement of the turret is wonky; the turret itself and the main gun appear to move around off center, making it look unsymmetrical.
I got the turret to work via using the basic ROBLOX constraints plugin in studio; I did not use any scripting for this, but I’d bet this would perform much better with some sort of programming involved. How would I do this?
Relevant scripts for this model
Regen Button
model = script.Parent.Parent
backup = model:clone()
enabled = true
function regenerate()
model:Destroy()
wait(1)
model = backup:clone()
local PrimaryInModel = model["M1Abrams"].Body
local PartsOfModel = model["M1Abrams"]:GetDescendants()
for k = 1,#PartsOfModel do
if PartsOfModel[k]:IsA("Part") or PartsOfModel[k]:IsA("WedgePart") or PartsOfModel[k]:IsA("MeshPart") then
if PartsOfModel[k].Name ~= "MainGun" and PartsOfModel[k].Name ~= "Turret" then
if not PartsOfModel[k]:FindFirstAncestor("Device") then
if PartsOfModel[k]:FindFirstAncestor("Gun") then
local weld = Instance.new("WeldConstraint")
weld.Part0 = PrimaryInModel
weld.Part1 = PartsOfModel[k]
weld.Parent = model["M1Abrams"].Turret
end
local weld = Instance.new("WeldConstraint")
weld.Part0 = PrimaryInModel
weld.Part1 = PartsOfModel[k]
weld.Parent = PrimaryInModel
end
end
end
end
model.Parent = game.Workspace
script.Disabled = true
wait(2)
script.Disabled = false
end
function onHit(hit)
if (hit.Parent:FindFirstChild("Humanoid") ~= nil) and enabled then
regenerate()
end
end
script.Parent.Touched:connect(onHit)
Local Turret Movement Script
local Vehicle = script:WaitForChild("Vehicle")
local Turret
repeat
wait()
Turret = Vehicle.Value
until
Turret
local Device = Turret:WaitForChild("Device")
local Seat = Device:WaitForChild("Seat")
local Fire = Seat:WaitForChild("Fire")
local Player = game.Players.LocalPlayer
local Mouse = Player:GetMouse()
local Character = Player.Character or Player.CharacterAdded:wait()
local Weapon = Device:WaitForChild("Weapon")
local GyroPart = Weapon:WaitForChild("Gyro")
local BodyGyro = GyroPart:WaitForChild("BodyGyro")
local Firing = false
Mouse.Icon = "rbxassetid://139669907"
Mouse.Button1Down:connect(function()
if not Firing then
Firing = true
Fire:InvokeServer("StartShooting")
end
end)
Mouse.Button1Up:connect(function()
if Firing then
Firing = false
Fire:InvokeServer("StopShooting")
end
end)
Mouse.Move:Connect(function()
if Vehicle.Value and Weapon:FindFirstChild("Gyro") then
Fire:InvokeServer("u_better_move",BodyGyro,Mouse.hit)
end
end)
Mouse.Icon = ""
Server Tank Movement Script
local Seat = script.Parent
local Device = Seat.Parent
local Fire = Seat:WaitForChild("Fire")
local LocalTurret = script:WaitForChild("LocalTurret")
local ExplosionSound = script:WaitForChild("Explosion")
local Weapon = Device:WaitForChild("Weapon")
local Gun1 = Weapon:WaitForChild("Gun1")
--local Gun2 = Weapon:WaitForChild("Gun2")
local Gun1Fire = Gun1:WaitForChild("Fire")
--local Gun2Fire = Gun2:WaitForChild("Fire")
local AntiAirTurret = Device.Parent
local ColorDescendantModels = {"Color";"Chassis"}
local AttackingDamage = 100
local TimeBetweenShots = .5
local MaxBulletDist = 1000
local Debounce = false
local Firing = false
Seat:GetPropertyChangedSignal("Occupant"):connect(function()
local Humanoid = Seat.Occupant
local Char = Humanoid and Humanoid.Parent
local Player = Char and game.Players:GetPlayerFromCharacter(Char)
if Player then
for _,Name in pairs(ColorDescendantModels)do
local FindDescendant = AntiAirTurret:FindFirstChild(Name,true)
for _,Part in pairs(FindDescendant and FindDescendant:GetChildren() or {})do
if Part:IsA("BasePart")then
Part.BrickColor = Player.TeamColor
end
end
end
local ClonedLocalTurret = LocalTurret:clone()
local VehicleValue = ClonedLocalTurret:WaitForChild("Vehicle")
VehicleValue.Value = AntiAirTurret
ClonedLocalTurret.Parent = Char
repeat
game["Run Service"].Heartbeat:wait()
until
not Seat.Occupant or (not Weapon:FindFirstChild("Gun1"))
VehicleValue.Value = nil
ClonedLocalTurret:Destroy()
end
end)
function AddKill(Player)
local Leaderstats = Player and Player:FindFirstChild("leaderstats")
local KOs = Leaderstats and Leaderstats:FindFirstChild("KOs")
if KOs then
KOs.Value = KOs.Value+1
end
end
function DoDamage(Player,Part,AttackingDamage)
local Char = Part and Part.Parent
local Humanoid = Char and Char:FindFirstChild("Humanoid")
local ArmourValue = Char and Char:FindFirstChild("ArmourValue")
local Armour = ArmourValue and ArmourValue.Value
local ArmourDamage = Armour and AttackingDamage or 0
if Armour then
ArmourDamage = math.clamp(math.ceil(ArmourDamage*.66),0,Armour)
ArmourValue.Value = Armour-ArmourDamage
end
if Humanoid and Humanoid ~= Seat.Occupant and Humanoid.Health > 0 and AttackingDamage then
local HumanoidDamage = AttackingDamage-ArmourDamage
Humanoid:TakeDamage(HumanoidDamage)
if Humanoid.Health <= 0 then
AddKill(Player)
end
end
end
function FireBullet(Shoot,Player)
if Shoot then
local FromPosition = Shoot.Position --+Shoot.Velocity*-Shoot.RotVelocity --(Shoot.CFrame*CFrame.new(0,0,-Shoot.Size.Z)).Position --Shoot.Position
local ToPosition = (Shoot.CFrame*CFrame.new(0,0,-MaxBulletDist)).Position
local Part,Position,Normal = game.Workspace:FindPartOnRay(Ray.new(FromPosition,(ToPosition-FromPosition).Unit*MaxBulletDist),AntiAirTurret)
local Dist = (Position-FromPosition).Magnitude
local Laser = Shoot:FindFirstChild("Laser") or Instance.new("Beam",Shoot) --Instance.new("Part",game.Workspace)
local Name = ((Player and Player).Name or "Unknown").."Shoot"
local A0 = Shoot:FindFirstChild("Shoot") or Instance.new("Attachment",Shoot)
local A1 = game.Workspace.Terrain:FindFirstChild(Name) or Instance.new("Attachment",game.Workspace.Terrain)
Laser.Name = "Laser"
A0.Name = "Shoot"
A1.Name = Name
A1.WorldPosition = Position or ToPosition
Laser.FaceCamera = true
Laser.Color = ColorSequence.new(Color3.fromRGB(239,184,56)) --Color3.fromRGB(239,184,56)
Laser.Width0 = .5
Laser.Width1 = .5
Laser.Attachment0 = A0
Laser.Attachment1 = A1
Laser.Enabled = true
if Part then
Part:BreakJoints()
local Explosion = Instance.new("Explosion")
Explosion.ExplosionType = "NoCraters"
Explosion.Position = Position
Explosion.BlastRadius = 8
Explosion.BlastPressure = 125000
Explosion.Parent = game.Workspace
local Cloned = ExplosionSound:clone()
Cloned.Parent = Part
Cloned.PlayOnRemove = true
Cloned:Destroy()
local PartP = Part.Parent
local PartPP = PartP and PartP.Parent
local HitParts = PartPP and PartPP:FindFirstChild("Parts")
local Engine = HitParts and HitParts:FindFirstChild("Engine")
local BodyGyro = Engine and Engine:FindFirstChild("BodyGyro")
if BodyGyro then
BodyGyro:Destroy()
end
DoDamage(Player,Part,AttackingDamage)
end
return Laser
end
end
Fire.OnServerInvoke = function(Player,DoFunction, gyro, targ)
if DoFunction == "StartShooting" then
Firing = true
while Firing and not Debounce do
Debounce = true
local Laser1
local Laser2
if Weapon:FindFirstChild("Gun1")then --FindFirstChild is just in case they get destroyed.
Gun1Fire:Play()
Laser1 = FireBullet(Gun1,Player)
end
--if Weapon:FindFirstChild("Gun2")then
--Gun2Fire:Play()
-- Laser2 = FireBullet(Gun2,Player)
-- end
wait(.1)
if Laser1 then
Laser1.Enabled = false
end
if Laser2 then
Laser2.Enabled = false
end
wait(TimeBetweenShots)
Debounce = false
end
elseif DoFunction == "StopShooting" then
Firing = false
elseif DoFunction == "u_better_move" and gyro and targ then
gyro.CFrame = targ
print(gyro.CFrame)
print(targ)
end
end