# Angled projectile

Hey everyone

I have been trying to create an Artillery model, for that I was browsing the devforum to see if there was any code/resource on projectile motion.

I found the following:

``````local i = 0

local x0 = launch.Position
local g = Vector3.new(0, -game.Workspace.Gravity, 0)

local v0 = (enemy.Position - x0 - 0.5*g*t*t)/t

game:GetService("RunService").Heartbeat:Connect(function(step)

if not (i >= 1) then
i = i + step
projectile.CFrame = CFrame.new(0.5*g*i*i + v0*i + x0)
end

end)
``````

This is what it does currently

It works well and all, but the projectile isnâ€™t launched at angle; which is what I have been trying to solve.
Are there any physics/maths related resources you guys can recommend for me to learn from?

5 Likes

The reason itâ€™s not angling is that youâ€™re initializing the projectileâ€™s CFrame as just one vector 3, i.e only a position, so it just sets the rotation to 0,0,0.

Thereâ€™s a bunch of different ways to set up CFramesâ€™ rotations, and frankly some of them are fairly complicated, and I canâ€™t explain them.

Your best bet would be to check the wiki page. Scroll down to the part about â€ślook vectorsâ€ť, more specifically â€śFinding a LookAt Vectorâ€ť.

Usually iâ€™d suggest the (now deprecated?) method of initializing a CFrame with CFrame.new(<part position vector 3>, <part target vector 3 position>) but AFAIK that method tends to not work well at high angles (towards the sky), which is precisely where your artillery operates.

This is a bit of a handful to learn, 3d transformations (i.e movement + rotation) are pretty complicated and confusing to learn, so donâ€™t feel bad if it seems alien to you.

I actually initialised the projectile with the CFrame of the launch site and the video is what it resulted in

``````local launch     = workspace.Artillery.ShootFromHere
projectile.CFrame     = launch.CFrame
``````

So Iâ€™m guessing Iâ€™ll have to adjust the formula to take account the initial angle

Well if ShootFromHere is a part, then indeed the projectile should have identical orientation to said part.

If thatâ€™s not the case, youâ€™ve coded something incorrect, weâ€™d be seeing a whole lot more weird behaviour across many games if the CFrame equivalence broke.

In the code you sent at the start, you, in your â€śforâ€ť loop, kept setting the CFrame to a NEW cframe. If you want to â€śmoveâ€ť a CFrame you want to either add the new CFrame to the old CFrame, or multiply the two.

NEW CFrames have no rotation/orientation data unless you explicitly set it with one of the many constructor methods.

Note that:
CFrame1 + CFrame2 = move the CFrame in the world coordinates,

CFrame1 * CFrame 2 = move the CFrame â€śCFrame2â€ť units with relation to CFrame 1, i.e

CFrame1 * CFrame.new(0,0,-5) â€”> move CFrame1 five units forward, with respect to itâ€™s own direction (rather than the global Z axis)

I figured it out after alot of trial and error. If anyone wants to launch a projectile from an Angle then use the following code.

Also make sure to define â€ślaunchâ€ť and â€śenemyâ€ť, in my case both were parts. launchâ€™s FrontFace should face the enemy target, and itâ€™s X orientation should be adjusted if you need to launch it at a higher/lower angle.

``````local speed = (launch.Position - enemy.Position).Magnitude / (90 - launch.Orientation.X)
local t = 1 * speed
local i = 0

local x0 = launch.Position + launch.CFrame.LookVector
local g = Vector3.new(0, -workspace.Gravity,0)

local v0 = (enemy.Position - x0 - 0.5*g*t*t)/t

game:GetService("RunService").Heartbeat:Connect(function(step)

if not (i >= t) then

i = i + step
projectile.CFrame = CFrame.new(0.5*g*i*i + v0*i + x0)

end

end)
``````

Here is the place file if anyone needs it
artierlly test.rbxl (19.3 KB)