Creating Projectiles

Hey there. I’m working on a fighting game, and I wanted a feature where you can press a key to throw a projectile, which would be a knife, in my case. I don’t want it to fall by gravity or ricochet off parts, I would just like to know what I could use to make it move straight forward. CFrame, BodyVelocity, etc.

5 Likes

If you don’t want the projectile to be effected by physics in any way, then math is your best bet in my opinion.

I would recommend either using TweenService( scroll down to the bottom of this developer hub page for a example of moving a part with TweenService ), or raw Linear Interpolation ( it gives you more options when you do the math yourself ).

Here is a nice tutorial to get you to understand linear interpolation if you haven’t already learned it in school. Lerping is useful over TweenService, because it gives you the option to apply calculates drop to your projectile if you wish.

2 Likes

I would strongly advise against the tween service, because the method wont account for anything that would pass the trajectory mid travel. Your best bet is actually a Body Velocity, but raw interpolation (Using stepped) can work as well. It’s a bit more complicated though.

3 Likes

Using both linear interpolation and TweenService would require you to perform the shot calculation before hand, and both would most likely require a endpoint. He specifically stated in the OP that he didn’t want it to collide with other objects, which is why I suggested these options.

BodyVelocity would definitely work, but is more resource consuming, especially if collisions aren’t something you are implementing. If he does change his mind about collisions though, using velocity in some sorts is a great idea.

2 Likes

Linear interpolation doesnt need an endpoint (with stepped) doesn’t need an endpoint. And theoretically planning an endpoint for an object can go pretty badly. Casting a ray to an object that’s moved after you’ve thrown it (like a player) limits the range to that one point. It’s chaotic. Tween service sets a destination and puts the projectile there, stopping it. Even if collisions are off that wont change the distance it can travel.

2 Likes

You would not want to set the endpoint to a to a limited distance, as you would get projectiles stopping in weird places, which is obviously not desirable, lol. You would set the endpoint to a distance far beyond the mouse hit position, by using the mouse to camera direction to calculate the endpoint.

It is true as you said though that lerping can be used either frame by frame, or by defining a endpoint beforehand, and working off of that. It’s about personal preference.

2 Likes

I gotchu,
Make a BodyForce:

local knifePart = workspace.Knife
local bodyForce = instance.new("BodyForce",knifePart)
bodyForce.Force = Vector3.new(0 ,bodyForce.Parent:GetMass() * workspace.Gravity, 0)

This will make it that it doesn’t get affect by gravity, as the Body Force uses the world X, Y and Z-axes it doesn’t get messed up when you rotate the part around.
If you got multiple BaseParts welded to the main part, in a model then make the other BaseParts massless, but don’t do it with the main part.

4 Likes

I think I did something wrong, it’s not working. Does the knife need to be anchored or anything like that? I thought it was going straight down due to the script but it was just because the knife was unanchored

No you may not anchor the knife else it will have no use.
Can you show me the script you have right now?

1 Like

It is the same as what you told me to type.

local knife2 = script.Parent
local bodyForce = Instance.new("BodyForce",knife2)
bodyForce.Force = Vector3.new(0 ,bodyForce.Parent:GetMass() * workspace.Gravity, 0)

You gotta put in the script after you created the knife, else it won’t work lmfao.

local bodyForce = Instance.new("BodyForce",knife2)
bodyForce.Force = Vector3.new(0 ,bodyForce.Parent:GetMass() * workspace.Gravity, 0)
2 Likes

? I did put in the script. I’m confused :face_with_raised_eyebrow:

Wait could you send the whole script/the script which creates the knifes, because communicating like this would have any input you need to fix it.

1 Like

A throwing knife would be pretty simple. I’ve done a lot of projectiles.

Client Code
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local KnifeThrow = ReplicatedStorage.Remotes.KnifeThrow

local player = game:GetService("Players").LocalPlayer
local mouse = player:GetMouse()

UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if gameProcessed then
		return
	end

	if input.KeyCode == Enum.KeyCode.R then
		KnifeThrow:FireServer(mouse.Hit.p) -- this is the position of where the mouse hit. (In Vector3 form.)
	end
end)
Server Code
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local KnifeThrow = ReplicatedStorage.Remotes.KnifeThrow

local debounces = {}

KnifeThrow.OnServerEvent:Connect(function(player, mousePos)
	if debounces[player.Name] and os.clock() - debounces[player.Name] < 5 then -- 5 would be the cooldown in seconds
		return
	end

	debounces[player.Name] = os.clock()
	local character = player.Character
	local knife = pathToKnife:Clone()

	knife.CFrame -- set the CFrame here.
	
	local knifeBV = Instance.new("BodyVelocity")
	knifeBV.MaxForce = Vector3.new(1e6,1e6,1e6) -- don't use math.huge for MaxForce.
	knifeBV.Velocity = CFrame.new(knife.Position, mousePos).LookVector * 60 -- 60 is the speed
	knifeBV.Parent = knife

	knife.Parent = workspace
	
end)
16 Likes

It says that pathToKnife is an unknown global.

Because you put the actual path to the knife. If the knife is in Workspace, then you’d do,

local knife = workspace.Knife:Clone()
1 Like

Now you gotta debris the knife and make it damage on hit.

3 Likes