How would I go about making a tracking missile / part?

How am I not being helpful? I am just trying to share my two cents on how to approach such problem. Everyone here is trying to help.

You’re grubbing for an answer check. All of your replies are about reading a basic article that really won’t help the poster. It’s good they read it, but if you want to be remotely helpful point them in the direction. Maybe you may know a little more than the basic CF methods, but just saying “oh use cframes” isn’t a valuable two cents.

2 Likes

Oooh, something that’s an interesting subject!

It’s always fun to make tracking projectiles, and honestly I like how they work out! Although @KultDeeri’s suggestion may work out, it’s not good performance wise as you’re calling numerous amounts of Tweens which results in a lot of network to be taken in

The way how I usually create my projectiles, are mostly physics based as that’s probably the simplest you can get with them & they’re easy to workaround with once you get to know how they work! As @TheZanderius stated, Physics I wouldn’t say the best, but definitely are a great example to show how to create a Tracking Missile/Part! Keep in mind though that there are a few things that we’ll need to use in order to accomplish this, such as:

  • Learning how the Constraint Objects work, like LinearVelocity & AngularVelocity

  • Understanding a bit of Lua Programming to know how to constantly update where our Target is going using RunService, and CFrames

  • Using a simplified .Touched Event (For this example) to activate collisions when to make the Missile explode

But don’t worry, once we finish we should have a good result of illegal use of explosives & get sent to jail making our Rocket lock onto a specific target, then the rest should be easy from there!

Step 1: Creating our Instances

Now, our first step is creating our Instances here :thinking: What we want to have are 2 things here:

  • A Target that we want to lock onto (You can easily get one through the Rig Builder inside the Model tab)
  • The Missile that’ll end all warfare

Dave: “I’m not ready to die!”

After we have those set up, we’ll have to add the following Instances to our Missile here:

  • LinearVelocity to assign the velocity for the Part to properly move
  • AngularVelocity to prevent the Part’s Rotation from constantly orientating
  • Attachment to hook onto our LinearVelocity that I’ll explain later
  • Our Script that’ll handle all the magic :sparkles:
  • (Optional) Add a Sound that’ll play upon impact, and when ended destroys the Missile

If we’ve done all these correctly, then it should look like this!

image

Now, before we move onto Step 2 here…We have to actually assign our LinearVelocity instance to our Attachment that we just created, as it requires 1 Attachment to hook onto cause otherwise our Part will just straight up fall in the V O I D

Make sure to click your LinearVelocity object, check on its Properties, and click our Attachment object! (Do the same with your AngularVelocity as well, otherwise your Missile will move like a pendulum)

Set both of the MaxForce & MaxTorque properties of the Velocity Objects to math.huge:
image - LinearVelocity
image - AngularVelocity

image

And if we’re done it and these properties show up, we can now move onto Step 2!

Step 2: The Scripting :eyes:

Now here’s where things are gonna get very interesting, the scripting aspect is the most important part here as we want to accomplish 3 main things here:

  • Checking for hit collisions via .Touched
  • Constantly looping so that the Missile changes direction when the Target moves
  • Completely ruin Dave’s life (Aka exploding him)

Now, we’re only gonna use 1 service which is our RunService that allows us to keep track with ROBLOX’s frame-by-frame loops, instead of rather just using our standardized “while true do” wait()/task.wait() globals

local RS = game:GetService("RunService")

We’ll also want to go ahead and create a couple of custom properties for our part, so that we’re able to reference them easier later on within our script:

local MaxSpeed = 25 -- This is how fast the Velocity of the Part should go
local Exploded = false -- We will use this later within our RunService loop
local MainTarget = workspace:WaitForChild("Dummy") -- Dave is not going to see the light of day ever again

local Part = script.Parent -- Just a simple shortcut to reference our Missile here
local PartConnection -- This will be explained later on

Now onto our hit collision here; We want to make sure that we’re only checking for Models that should have Humanoid objects within them, so what the first thing we’d want to do is create a local function that we’ll connect with a .Touched Event here:

local function Touched(Hit)

end 

:information_source: - The first parameter of a .Touched Event is the Hit Part that collided with it :wink: (Examples being the Right Arm of a Character, or a Car Tire from the Model of an Old Ford)
:warning: - This can throw back errors if not handled properly, such as no frequent checks

Now, since we want to check for the Target Model (As .Touched gives only the Hit Part back), we will have to reference the Hit Part’s Parent to be able to obtain it that way:

local Target = Hit.Parent

if not Target then return end

And if say, there isn’t an exact Parent within the Part then we can go ahead and return our function which prevents it from running any more line of code :L

Next, we’ll check for the Humanoid of the Model:

local Hum = Target:FindFirstChildOfClass("Humanoid")

if Hum ~= nil then
    PartConnection:Disconnect()
		
	Exploded = true

    for _, Part in pairs(Target:GetDescendants()) do
		if Part:IsA("BasePart") then
			Part:BreakJoints()
		end
	end
		
	local Explosion = Instance.new("Explosion")
	Explosion.Position = Part.Position
	Explosion.Parent = workspace
		
    Part.Explode:Play()
	Part.Anchored = true
	Part.Transparency = 1
		
	Part.Explode.Ended:Wait()
		
	Part:Destroy()
end

Now, this may look like a lot BUT we’ll go ahead and slowly discuss what each thing does here:

  • if Hum ~= nil is just simply checking if the Humanoid we’re looking for inside our Model, is valid & able to be obtained

  • PartConnection:Disconnect() is kinda like a debounce, except when you call this it only fires once and can never be used again (You can read more about it here if you’re interested)

  • We’re setting Exploded = true to indicate that our Missile has exploded

  • for _, Part in pairs, now here we’re obtaining every singular object within our Target using the GetDescendants() method, and we can loop through every individual part to check if it’s a valid BasePart object to be able to call BreakJoints() on it (Or in simple terms, Model go bye bye)

  • We’re also creating an Explosion to add an effect to said “Missile”, to make it look more cool :sunglasses:

  • Part.Explode is referring to our Missile, so we’re obtaining our Explode Sound and Playing that

  • Part.Anchored & Part.Transparency are both properties

  • We also call Part.Explode.Ended:Wait() to yield until the Sound has ended, and then we can fully remove our Part

And lastly, we have to connect our Event

PartConnection = Part.Touched:Connect(Touched)

Overall, our Touched function should look like this now:

local Part = script.Parent

local PartConnection
local function Touched(Hit)
	local Target = Hit.Parent
	
	if not Target then return end
	
	local Hum = Target:FindFirstChildOfClass("Humanoid")
	
	if Hum ~= nil then
		PartConnection:Disconnect()
		
		Exploded = true
		
		for _, Part in pairs(Target:GetDescendants()) do
			if Part:IsA("BasePart") then
				Part:BreakJoints()
			end
		end
		
		local Explosion = Instance.new("Explosion")
		Explosion.Position = Part.Position
		Explosion.Parent = workspace
		
		Part.Explode:Play()
		Part.Anchored = true
		Part.Transparency = 1
		
		Part.Explode.Ended:Wait()
		
		Part:Destroy()
	end
end

PartConnection = Part.Touched:Connect(Touched)

It’s looking good so far! But wait, how are gonna constantly update it? Well, remember that Exploded variable we made a while back? We’re gonna use that within a while true do loop, except replace the “loop” with our own variable “Exploded” instead :smirk:

while not Exploded do
	Part.CFrame = CFrame.new(Part.Position, MainTarget.HumanoidRootPart.Position)
	Part.LinearVelocity.VectorVelocity = Part.CFrame.LookVector * MaxSpeed
	RS.Stepped:Wait()
end

Now, since at the start we defined local Exploded = false, we want to include the not operator (Which is basically the opposite, so not Exploded == true)

A couple things more here that shouldn’t be too hard to explain:

  • Part.CFrame is changing its CFrame (Orientational & Positional Values) so that it’s able to properly look at our Target, whilst keeping its position as well! The main idea here, is that in our example we’re going 2 parameters for this constructor here:

    • The first parameter is our Position we want our Missile to be, possibly in the center like Vector3.new(0, 0, 0) or even up in the sky! (Vector3.new(0, 500, 0)

    • The second parameter is the Position the Part should look at, now this one is important as the Part will face forward (You can add a Decal to your Part and see what Front Face your Missile is at), but it’ll still stay at our Position from our first parameter here

  • Part.LinearVelocity.VectorVelocity = Part.CFrame.LookVector would move our Part in the current direction it’s facing

    • :information_source: - Keep in mind! LookVector will always have a max of 1 in this scenario for each axis, so if we want to increase our speed we’ll have to multiply by our MaxSpeed variable (Which is 25)
  • Each RunService Event is different on how it runs, RS.Stepped:Wait() would fire for each frame prior to the Physics Simulation, so that’s what we’ll use for this example

Hopefully though, our full result should look like this:

local RS = game:GetService("RunService")

local MaxSpeed = 25
local Exploded = false
local MainTarget = workspace:WaitForChild("Dummy")

local Part = script.Parent

local PartConnection
local function Touched(Hit)
	local Target = Hit.Parent
	
	if not Target then return end
	
	local Hum = Target:FindFirstChildOfClass("Humanoid")
	
	if Hum ~= nil then
		PartConnection:Disconnect()
		
		Exploded = true
		
		for _, Part in pairs(Target:GetDescendants()) do
			if Part:IsA("BasePart") then
				Part:BreakJoints()
			end
		end
		
		local Explosion = Instance.new("Explosion")
		Explosion.Position = Part.Position
		Explosion.Parent = workspace
		
		Part.Explode:Play()
		Part.Anchored = true
		Part.Transparency = 1
		
		Part.Explode.Ended:Wait()
		
		Part:Destroy()
	end
end

PartConnection = Part.Touched:Connect(Touched)

while not Exploded do
	Part.CFrame = CFrame.new(Part.Position, MainTarget.HumanoidRootPart.Position)
	Part.LinearVelocity.VectorVelocity = Part.CFrame.LookVector * MaxSpeed
	RS.Stepped:Wait()
end

And now, it’s time to move onto the exciting part! The Testing :eyes:

Step 3: The Testing

Now, we have our Script alongside our Instances ready to fire up! If you’ve done everything correctly, then our Missile should move & target Dave; our test dummy!

We’ll do 2 tests: One without moving Dave, and one with moving Dave

Here’s Test #1:

As you can see here, our Missile has completely obliterated poor Dave & all his Body Parts have scattered everywhere so Test #1 was a success!

Now, let’s try Test #2 with moving Dave! (Spoiler Alert: Dave FREAKING DIES)

But as you can see from these 2 tests, both were successful! And it should hopefully give you a better insight on how to creating tracking parts!

If you do have any questions, please feel free to ask if you need to! :slightly_smiling_face:

12 Likes

oh my god it looks like you spent 10 hours on that tysm

I do have a question, what if the target is a part, rather than a humanoid. For example, a flying aircraft. The original intention was to make this for a rocket launcher made for shooting down planes / vehicles.

You can still do that! Just as long as you reference a BasePart Instance within the 2nd parameter of CFrame.new() to be that specific Part, and there are honestly so much ways you can sanity check within your Touched function; here are a couple of examples that I can provide:

  • if Part.Anchored == true then
  • if Part.Name == "TargetPartHere then
  • if Part:FindFirstChild("ImportantObjectHere") then
  • if Part:GetAttribute("SpecificAttributeHere") == true then

Just do what works best for you :wink: (And for Dave’s sake as well cause he risked his life just for this)

also, if the target is in the air, it doesnt work… do you know how to fix that?

Did you set the properties of each Instance correctly? And did you make sure to follow every line of code? It completely works fine for me when I test it in Studio:

NOW TOM IS DEAD.

1 Like

ill check that out… Maybe I set the properties wrong

I did fixed my tween problem. Switched it to Bodyvelocity. Since I don’t know how to use the new ones, I just went with the deprecated instances, but it shouldn’t do a difference.

Use RayCast to help you get a way better detection over Touched Event.

isn’t raycast for like beams or something?

Quick recap:

  • LinearVelocity Properties

    • Attachment0 should be equal to your Attachment that is within your Missile
    • MaxForce should be equal to math.huge
  • AngularVelocity Properties

    • Attachment0 should be equal to your Attachment that is within your Missile
    • MaxTorque should be equal to math.huge
  • Both should be parented inside your Missile, alongside the Attachment as well

@KultDeeri Even if it doesn’t, it’s more recommended to switch to the latter in case BodyVelocity officially gets removed from the API (It’s currently within the deprecated state as of now)

Not exactly, you can use it to send a ray from the Position of the Missile, then the lookvector for the distance of the ray. But if you aren’t looking for that. You can as well use spatial querys [Overlap Params], to help you instead.

Do you know why the attachments are needed for?

Here’s my version of the script, though @JackscarIitt uses AngularVelocity, which I don’t know what it does. Mine uses just LinearVelocity and Spatial Query instead.

Whatever works best for you, good luck on your game as well. :slight_smile:

Speed = 50

local Target = game.Workspace.Dummy.HumanoidRootPart
local Missile = game.Workspace.Follow

local LV = Instance.new("LinearVelocity", Missile)
LV.Attachment0 = Missile.Attachment
LV.MaxForce = math.huge

local OP = OverlapParams.new()
OP.FilterDescendantsInstances = {}
OP.FilterType = Enum.RaycastFilterType.Blacklist

game:GetService("RunService").Heartbeat:Connect(function()
	Missile.CFrame = CFrame.new(Missile.Position, Target.Position)
	LV.VectorVelocity = Missile.CFrame.LookVector * Speed
	
	task.spawn(function()
		local Hit = game.Workspace:GetPartsInPart(Missile, OP)
		
		if #Hit == 0 then return end
		for i,Touch in (Hit) do
			if Touch:IsA("BasePart") then
				local Humanoid = Touch.Parent:FindFirstChildOfClass("Humanoid")
				if Humanoid then
					Humanoid:TakeDamage(50)
					Missile:Destroy() -- Destroy when touch?
				end
			end
		end
	end)
end)

they both seem to work the same/similarly because I dont notice a difference, thx

Here is my personal assumption, and I’m unsure if this is actually what the case is true or not but this is just me speaking out opinions:

Attachments were added to LinearVelocity & AngularVelocity because they’re now considered a type of Constraint that ROBLOX changed ever since they subsided the Legacy BodyMovers (BodyAngularVelocity, BodyGyro, etc), and it was for quite a while as well (March 22nd, 2022 to be exact), but unfortunately I highly doubt they’ll plan on improving them as more people tend to prefer using Constraint type objects, such as (WeldConstraints & Motor6Ds) as they’re far better than the old BodyMovers

1 Like

really creative, funny, and detailed explanation tho, that really cleared things up. Thanks, gl on any future projects. RIP Dave

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.