Please read the link they had just sent to you.
On initiation process:
- Instance a new align position and orientation. I don’t have time to fully explain how to use them so search up a tutorial
- Create a heartbeat or renderstep binding function
- Every frame, change the target position of the align position to the position of the missile, and the cframe to a new cframe of your pos looking at the missile, i think you can skip this step if you just set this stuff to follow another attachment
You’ve said that twice now. You didnt even point him or her in the direction, you just linked an article on CFrames. Don’t clog up the thread if you aren’t going to contribute anything useful.
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.
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 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 ourLinearVelocity
that I’ll explain later - Our
Script
that’ll handle all the magic - (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!
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
:
- LinearVelocity
- AngularVelocity
And if we’re done it and these properties show up, we can now move onto Step 2!
Step 2: The Scripting
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
- The first parameter of a .Touched
Event is the Hit Part that collided with it (Examples being the Right Arm of a Character, or a Car Tire from the Model of an Old Ford)
- 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 theGetDescendants()
method, and we can loop through every individual part to check if it’s a validBasePart
object to be able to callBreakJoints()
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
-
Part.Explode
is referring to our Missile, so we’re obtaining ourExplode
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
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 itsCFrame
(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-
- 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 ourMaxSpeed
variable (Which is 25)
-
- Keep in mind!
-
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
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!
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 (And for Dave’s sake as well cause he risked his life just for this)
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.
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 tomath.huge
-
-
AngularVelocity Properties
-
Attachment0
should be equal to your Attachment that is within your Missile -
MaxTorque
should be equal tomath.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.
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