One question about BodyGyros

I am making a gun turret which will fire bullets at any enemy aircraft that gets too close.
It works, but the body gyro rotates the entire aircraft which isn’t what I want. Help
Code:


Part = script.Parent
local model = script.Parent
local e = Instance.new('BodyGyro')

e.Parent = script.Parent
local engine = script.Parent
targets = workspace.japaneseTargets
local function destroyBullet(bullet)
	bullet:Destroy()
end
local function FireGuns(target)

	wait(1)
	local bullet = Instance.new("Part")
	bullet.Position = Part.Position
	bullet.CanCollide = false
	local v = Instance.new("BodyVelocity")
	bullet.Orientation = Part.Orientation
	bullet.Name = "JB"
	v.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
	v.Velocity = bullet.CFrame.LookVector * -500
	v.Parent = bullet
	bullet.Parent = workspace
	bullet.Size = Vector3.new(1,1,1)
	bullet.Material = "Neon"
	bullet.BrickColor = BrickColor.new("Bright red")
	delay(3,function() bullet:Destroy() end)
end
local function getTargets()
	for v,t in pairs(workspace:GetDescendants()) do
		local enemyPlane = t:FindFirstAncestor("USFighter")
		local enemyBomber = t:FindFirstAncestor("USBomber")
		local enemyHeavy = t:FindFirstAncestor("USHeavy")
		if enemyPlane then
			enemyPlane.Parent = targets
		end
		if enemyHeavy then
			enemyHeavy.Parent = targets
		end
		if enemyBomber then
			enemyBomber.Parent = targets
		end
	end
end
local function shoot(target)
	if (script.Parent.Position - target.hemalurgicSpike.Position).magnitude < 501 then
		FireGuns(target)
	end
end
local function attack(target)

	local origincframe = engine.BodyGyro.cframe
	local dir = (script.Parent.Position - target.hemalurgicSpike.Position).unit
	local spawnPos = script.Parent.Position
	local pos = spawnPos + dir 	
	engine:findFirstChild("BodyGyro").maxTorque = Vector3.new(10000,10000,10000)
	engine:findFirstChild("BodyGyro").cframe = CFrame.new(pos, pos+dir)
	shoot(target)

end

local function findNearestEnemy()
	local target = nil
	getTargets()
	for i,v in pairs(targets:GetChildren()) do
		if v:IsA("Model") then
			local previousDistance = 99999
			local distance = (script.Parent.Position - v.hemalurgicSpike.Position).magnitude
			if distance < previousDistance and v.Health.Value > 0 then
				previousDistance = distance
				target = v
			end
		end
	end
	return target
end
local function shootAtEnemyPlanes()
	wait(0.01)
	local target = findNearestEnemy()
	if target then
		attack(target)
	end
end
while true do
	wait(0.01)
	shootAtEnemyPlanes()
end






Well Im guessing the body gyro rotates the whole body including everything that is welded I guess so maybe try just rotating using a motor6d.

@rottendogDkR How do you use Motor6Ds? I’m sorry, I have never used one before.

Using Motor6Ds or welds are usually the same thing, except Motor6Ds are used in animations and welds are more for stationary objects. Both work well for what you’re attempting to do. Basically you’d weld a part to the plane for the gun. Then make a joint part in that same area and weld the actual gun to that joint. Using CFrame:ToOrientation() you’d do what you were already doing to get the rotation to fire the gun, and get the X,Y and Z rotation and apply that to the joints weld to rotate the gun without moving the plane.

I get that this is kinda confusing and probably worded poorly so if you need more elaboration I can assist further

1 Like

@hotpocket285 can I please have like an example for this? Right now I am trying to use orientation but unfortunately it always goes the wrong direction.
Code:

Part = script.Parent
local gun = script.Parent
targets = workspace.japaneseTargets
local function destroyBullet(bullet)
	bullet:Destroy()
end
local function FireGuns(target)
	wait(0.3)
	local bullet = Instance.new("Part")
	bullet.Position = gun.Position
	bullet.CanCollide = false
	local v = Instance.new("BodyVelocity")
	bullet.Orientation = gun.Orientation
	bullet.Name = "JB"
	v.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
	v.Velocity = bullet.CFrame.LookVector * -300
	v.Parent = bullet
	bullet.Parent = workspace
	bullet.Size = Vector3.new(1.5,1.5,1.5)
	bullet.Material = "Neon"
	bullet.BrickColor = BrickColor.new("Bright red")
	bullet.Touched:connect(function(part)
		local plane = part:FindFirstAncestor("JapBomber")
		if not plane then
			bullet:Destroy()
		end
		
	end)
	delay(3,function() bullet:Destroy() end)
end
local function getTargets()
	for v,t in pairs(workspace:GetDescendants()) do
		local enemyPlane = t:FindFirstAncestor("USFighter")
		local enemyBomber = t:FindFirstAncestor("USBomber")
		local enemyHeavy = t:FindFirstAncestor("USHeavy")
		if enemyPlane then
			enemyPlane.Parent = targets
		end
		if enemyHeavy then
			enemyHeavy.Parent = targets
		end
		if enemyBomber then
			enemyBomber.Parent = targets
		end
	end
end
local function shoot(target)
	if (script.Parent.Position - target.hemalurgicSpike.Position).magnitude < 501 then
		FireGuns(target)
	end
end
local function attack(target)
	local dir = (script.Parent.Position - target.MeshPart.Position).unit
	local spawnPos = script.Parent.Position
	local pos = spawnPos + dir 	
	gun.Orientation = pos + dir
	shoot(target)

end

local function findNearestEnemy()
	local target = nil
	getTargets()
	for i,v in pairs(targets:GetChildren()) do
		if v:IsA("Model") then
			local previousDistance = 99999
			local distance = (script.Parent.Position - v.hemalurgicSpike.Position).magnitude
			if distance < previousDistance and v.Health.Value > 0 then
				previousDistance = distance
				target = v
			end
		end
	end
	return target
end
local function shootAtEnemyPlanes()
	wait(0.01)
	local target = findNearestEnemy()
	if target then
		attack(target)
	end
end
while true do
	wait(0.01)
	shootAtEnemyPlanes()
end

So what you’re trying to do is get the turret to rotate to face the targets, correct? Is it an object or is it a moving vehicle? May I see what the turret you’re programming looks like? There may be an easier way to do this because I’m slightly confused of your current goal.

1 Like

@hotpocket285
I have a bomber plane and it has a part named “DefensiveGun” on it’s back. I want the gun to shoot at any incoming enemy aircraft. The gun is just an invisible 1x1x1 square. I want it to fire bullets at incoming planes without turning the entire aircraft

1 Like

You can leave your code the same and replace the weld with a hinge. A hinge should (in theory) let the turret rotate freely without moving the rest of the ship with it.

2 Likes

May I see a screen shot of the turret? Because depending on how it is I could explain a simple solution for this.

1 Like

Using a motor6d is pretty easy once you get to know how to use it. All you need to do is get the current lookvector and find the new lookvector you want to look at. Using this method(you can look through tons of topics on the forum);

local a = Vector3.new(0,0,1) -- first position
local b = Vector3.new(0,1,0) -- second position
local angle = math.acos(a:Dot(b)/(a.Magnitude*b.Magnitude))
-- after you will need to put it into a cframe
motor6d.C0 = motor6d.C0*CFrame.Angles(0,0,angle) -- choose whatever axis depending on where you want to change it.

@hotpocket285 The turret is the white cube.

@rottendogDkR
It just shoots forward.

Part = script.Parent
local gun = script.Parent
targets = workspace.japaneseTargets
local function destroyBullet(bullet)
	bullet:Destroy()
end
local function FireGuns(target)
	wait(0.3)
	local bullet = Instance.new("Part")
	bullet.Position = gun.Position
	bullet.CanCollide = false
	local v = Instance.new("BodyVelocity")
	bullet.Name = "JB"
	v.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
	v.Velocity = bullet.CFrame.LookVector * -300
	v.Parent = bullet
	bullet.Parent = workspace
	bullet.Size = Vector3.new(1.5,1.5,1.5)
	bullet.Material = "Neon"
	bullet.BrickColor = BrickColor.new("Bright red")
	bullet.Touched:connect(function(part)
		local plane = part:FindFirstAncestor("JapBomber")
		if not plane then
			bullet:Destroy()
		end

	end)
	delay(3,function() bullet:Destroy() end)
end
local function getTargets()
	for v,t in pairs(workspace:GetDescendants()) do
		local enemyPlane = t:FindFirstAncestor("USFighter")
		local enemyBomber = t:FindFirstAncestor("USBomber")
		local enemyHeavy = t:FindFirstAncestor("USHeavy")
		if enemyPlane then
			enemyPlane.Parent = targets
		end
		if enemyHeavy then
			enemyHeavy.Parent = targets
		end
		if enemyBomber then
			enemyBomber.Parent = targets
		end
	end
end
local function shoot(target)
	if (script.Parent.Position - target.hemalurgicSpike.Position).magnitude < 501 then
		FireGuns(target)
	end
end
local function attack(target)
	local dir = (script.Parent.Position - target.MeshPart.Position).unit
	local spawnPos = script.Parent.Position
	local pos = spawnPos + dir 	
	local a = Vector3.new(pos)
	local b = Vector3.new(dir)
	local angle = math.acos(a:Dot(b)/(a.Magnitude*b.Magnitude))
	-- after you will need to put it into a cframe
	script.Parent.Motor6D.C0 = script.Parent.Motor6D.C0*CFrame.Angles(0,0,angle)
	shoot(target)

end

local function findNearestEnemy()
	local target = nil
	getTargets()
	for i,v in pairs(targets:GetChildren()) do
		if v:IsA("Model") then
			local previousDistance = 99999
			local distance = (script.Parent.Position - v.hemalurgicSpike.Position).magnitude
			if distance < previousDistance and v.Health.Value > 0 then
				previousDistance = distance
				target = v
			end
		end
	end
	return target
end
local function shootAtEnemyPlanes()
	wait(0.01)
	local target = findNearestEnemy()
	if target then
		attack(target)
	end
end
while true do
	wait(0.01)
	shootAtEnemyPlanes()
end

This helps a lot actually. What I would do is clone the turret and name it something like “TurretJoint” then create a weld in the actual turret and set Part0 to the joint and Part1 to the turret. Then when you calculate your rotational angle that you’d normally put into the bodygyro. Take that CFrame and this:

local x,y,z = CFrame.new(pos, pos+dir):ToOrientation() -- Returns the entire rotational matrix of the CFrame in radians

[insertturretpartnamehere].Weld.C1 = CFrame.Angles(x,y,z)

Should rotate the turret exactly like a bodygyro but won’t alter your aircraft’s orientation as a whole. Of course you’d have to weld the Joint to the plane and remove the weld holding the turret to the plane as it’s welded to the joint now.

1 Like

@hotpocket285 I will test it when roblox is back up. :frowning:

Let me know how it goes, I’m free to address any other questions if my wording was confusing.

Best of luck my guy :+1:

1 Like

The first thing that you should do is make the the first thing a equal to the lookvector of your motor6d
like this;

local a = Motor6D.C0.Lookvector
local b = CFrame.new(pos,dir):ToObjectSpace(Motor6D.Part0.CFrame).LookVector

@hotpocket285 sorry about being annoying, but the thing says that weld is not a valid member of defensivegun which is annoying. Code:

Part = script.Parent
local gun = script.Parent
targets = workspace.japaneseTargets
local function destroyBullet(bullet)
	bullet:Destroy()
end
local function FireGuns(target)
	wait(1)
	local bullet = Instance.new("Part")
	bullet.Position = gun.Position
	bullet.CanCollide = false
	local v = Instance.new("BodyVelocity")
	bullet.Name = "JB"
	v.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
	v.Velocity = bullet.CFrame.LookVector * -300
	v.Parent = bullet
	bullet.Parent = workspace
	bullet.Size = Vector3.new(1.5,1.5,1.5)
	bullet.Material = "Neon"
	bullet.BrickColor = BrickColor.new("Bright red")
	bullet.Touched:connect(function(part)
		local plane = part:FindFirstAncestor("JapBomber")
		if not plane then
			bullet:Destroy()
		end

	end)
	delay(3,function() bullet:Destroy() end)
end
local function getTargets()
	for v,t in pairs(workspace:GetDescendants()) do
		local enemyPlane = t:FindFirstAncestor("USFighter")
		local enemyBomber = t:FindFirstAncestor("USBomber")
		local enemyHeavy = t:FindFirstAncestor("USHeavy")
		if enemyPlane then
			enemyPlane.Parent = targets
		end
		if enemyHeavy then
			enemyHeavy.Parent = targets
		end
		if enemyBomber then
			enemyBomber.Parent = targets
		end
	end
end
local function shoot(target)
	if (script.Parent.Position - target.hemalurgicSpike.Position).magnitude < 1001 then
		FireGuns(target)
	end
end

local function attack(target)
	local dir = (script.Parent.Position - target.MeshPart.Position).unit
	local spawnPos = script.Parent.Position
	local pos = spawnPos + dir 	
	local x,y,z = CFrame.new(pos, pos+dir):ToOrientation()
	script.Parent.Weld.C1 = CFrame.Angles(x,y,z)
	
	shoot(target)

end

local function findNearestEnemy()
	local target = nil
	getTargets()
	for i,v in pairs(targets:GetChildren()) do
		if v:IsA("Model") then
			local previousDistance = 99999
			local distance = (script.Parent.Position - v.hemalurgicSpike.Position).magnitude
			if distance < previousDistance and v.Health.Value > 0 then
				previousDistance = distance
				target = v
			end
		end
	end
	return target
end
local function shootAtEnemyPlanes()
	wait(0.01)
	local target = findNearestEnemy()
	if target then
		attack(target)
	end
end
while true do
	wait(0.01)
	shootAtEnemyPlanes()
end

You’re not annoying my guy, all good :+1:

Did you put a weld into the gun part? Or did you just write code around it? You should add a weld into the turret and weld it to a joint part.

2 Likes

Im guessing just using CFrame.lookat would work just fine by just keeping the welds position but only applying where you want to look at.

@hotpocket285.
LOL Idk why I didn’t respond last time.
So I still have the same issue.
I have become a much stronger scripter now.
I use qPerfectionWeld and edited it so it wouldn’t effect my turret.
Turret looks like this.
Screenshot 2022-08-01 194244
So I have some welds right now in each part of the turret.
I just changed the CFrame, but it twichtches the plane each time it shoots. :joy:

wait(3.1)
local plane = script.Parent.Parent
if plane.Parent == workspace.RedPlanes then
	targets = workspace.BluePlanes
	bull = game:GetService("ReplicatedStorage").Ammo.JB
end
if plane.Parent == workspace.BluePlanes then
	targets = workspace.BluePlanes
	bull = game:GetService("ReplicatedStorage").Ammo.AB
end


local function FireGuns(angle)
	for i,v in pairs(script.Parent:GetChildren()) do
		if v:IsA("BasePart") and v.Name == "BulletPos" then
			local bullet = bull:Clone()
			bullet.Orientation = v.Orientation
			bullet.Position = v.Position
			bullet.Parent = workspace
			wait(0.333)
		end
	end
end

local function findNearestEnemy()
	local MaxDistance = 99999
	local nearestEnemy = nil
	for i, enemy in pairs(targets:GetChildren()) do
		if enemy then
			local distance = (plane.PrimaryPart.Position - enemy.PrimaryPart.Position).magnitude
			if distance < MaxDistance and enemy.Health.Value > 0 and distance < 1500 then
				nearestEnemy = enemy
				MaxDistance = distance
			end
		end
	end
	return nearestEnemy
end

local function FindAngle(nearestEnemy)
	local origincframe = plane.Engine.BodyGyro.cframe
	local dir = (plane.PrimaryPart.Position - nearestEnemy.PrimaryPart.Position).unit
	local spawnPos = plane.PrimaryPart.Position
	local pos = spawnPos + dir 	
	script.Parent.GunJoint1.CFrame = CFrame.new(pos, pos+dir)
end

while wait() do
	local nearestEnemy = findNearestEnemy()
	if nearestEnemy and nearestEnemy.PrimaryPart.Position.Y > script.Parent.PrimaryPart.Position.Y then
		FindAngle(nearestEnemy)
		FireGuns()
	end
end

I know the problem it’s because every part in the turret is welded together, and turretjoint, “the black square” is welded to the plane.
When joint1’s cframe is changed, (joint1) is the circle
the whole plane’s cframe twitches,
Any idea how to fix this?
Yes, sorry about the bump but it’s still not fixed. :confused: