Projectile shot calculations

It should be a low angle though? There’s barely a difference in the Y. This is from a linear trajectory’s perspective.

1 Like

XRotation might not matter much in my mortar, as it would be easier for the player to aim manually. But YRotation would be essential to get a sense of where the projectile was going to land.
I watched a part of the video, I didn’t understand anything lol, I don’t speak English it gets worse
So how could I get the Y rotation?

I probably explained it wrong, I’m sorry,
from what @BurningEuphoria said, maybe you thought I wanted a straight shot, with no gravity etc
idk, I don’t understand anything about angles

I’d take note of how to get the XRotation just in case you’re looking at making the mortar aim itself eventually.

To get YRotation, all you need is some simple trig:

local YRotation = math.acos(mortar.CFrame.LookVector:Dot((endPos - startPos).unit))

It’s also worth mentioning that both my answers give the angle in radians - if you want the angle in degrees, use math.deg():

local YRotation = math.deg(angle in radians)

This rotation is how much you have to rotate the mortar from where it currently is to make it face the target. It’s not the rotation from where the mortar would be facing if YRotation started at 0.

2 Likes

image

This angle is very small, the target is considerably far away.

Code:

local dh = target.Position.Y - muzzle.Position.Y
local dx = ((target.Position - target.Position) * Vector3.new(1, 0, 1)).Magnitude
local XRotation = (math.acos(((g * (dx^2) / (200^2)) - dh) / math.sqrt((dh^2) + (dx^2))) + math.atan(dx/dh))/2
local YRotation = math.acos(script.Parent.Parent:GetModelCFrame().LookVector:Dot((target.Position - muzzle.Position).unit))
print(XRotation)
print(YRotation)

edit: both initial angles of the mortar were at 0

Another method:

Using the angle of the mortar and the speed, we can easily calculate the velocity by this:

function fire(angle, distancearc, g)
local vx = math.sin(angle)
local vy = math.cos(angle)

local speed = 3 -- let's say three for now.

while distancearc > 0 do
  distancearc -= 1
  part.Position.X += vx * speed
  part.Position.Y += vy * speed
  
  vx -= (1-g)*vx*2
  vy -= (1-g)*vy*2
  wait(0.14)
end
end

when 0 < g < 1.

This function, given a said angle, will fire the part in that angle, applying the force g.

The math isn’t VERY accurate, but it’s an example to give you an idea of what you would do in this case.

1 Like

image

fire(script.Parent.Parent.MantletBase.Rotator.TargetAngle,(target.Position - muzzle.Position).Magnitude,workspace.Gravity)

I don’t know if I’m using the correct form

Yes, I get this error a-lot. This error happens when you attempt to set Position.X a value. Instead of this, try creating a new Vector3.new value and setting the part.Position to it.

Honestly, I wasn’t even taking that script seriously because I had thought you already had your answer.

1 Like

Let me explain it to you:

This website here demonstrates finding the math.cos and math.sin of an angle.

as you can see, the math.sin() represents the y increase if you moved in a 2-dimensional direction of theta (the angle) and the same for math.cos. Now, notice of the radius of that circle is ALWAYS 1. Since we know that 1 times any number is always going to be that number, if we just multiply the vx and vy values by speed you’ll increase the size of that circle, and move farther.

These are just simple trigonomic functions. Understanding math.sin() and math.cos() is crucial to any spatial related programming.

Now, all we have to do to implement gravity, is over time, change that angle of movement. There are two ways you can do this, first, the method I used by just subtracting of off the vx and vy, or two, subtracting of the ORIGINAL angle, and from there finding the math.cos() and math.sin() of that angle.

Example:

if (math.pi/2) < angle and angle < (3*math.pi/2) then
  angle += math.pi /180 -- one degree
else if (math.pi/2) > angle or (3*math.pi.2) < angle then
  angle -= math.pi/180 -- one degree
end

What this script does, is checks if the current moving angle is greater than 90 degrees and less than 270 degrees (moving down), then it adds a degree to the movement of the angle. Else, if it’s less than 90 degrees, OR greater than 270 degrees, it subtracts a degree from the angle.

1 Like

The projectile (in this case the Part) when I shoot, it appears, possibly it is setting an unwanted position

function fire(angle, distancearc, g)
	local vx = math.sin(angle)
	local vy = math.cos(angle)
	local part = Instance.new("Part")
	part.Anchored = true
	part.Size = Vector3.new(5,5,5)

	local speed = 3 -- let's say three for now.

	while distancearc > 0 do
		distancearc -= 1
		part.Position += Vector3.new(vx * speed,0,0)
		part.Position += Vector3.new(0,vy * speed,0)

		vx -= (1-g)*vx*2
		vy -= (1-g)*vy*2
		print(part.Position)
		wait(0.14)
	end
end

I’ll take a look at that when I’m done. thank you very much for the explanation

This code wasn’t mean’t to handle 3 dimensional gravitation pull.

I suggest creating your own formula like this one, but for your script, since I don’t know how your script is setup.

Oh, this is going to be impossible for me, because I don’t know anything about it :smiling_face_with_tear:
Thank you anyway

function fire(angle, distancearc, g)
	local vx = math.sin(angle)
	local vy = math.cos(angle)
	local part = Instance.new("Part")
	part.Anchored = true
	part.Size = Vector3.new(5,5,5)

	local speed = 3 -- let's say three for now.

	while distancearc > 0 do
		distancearc -= 1
		part.Position += Vector3.new(vx,vy,0)

                if (math.pi/2) < angle and angle < (3*math.pi/2) then
                  angle += math.pi /180 -- one degree
                else if (math.pi/2) > angle or (3*math.pi.2) < angle then
                  angle -= math.pi/180 -- one degree
                end

		vx -= math.cos(angle) * speed
		vy -= math.sin(angle) * speed

		wait(0.14)
	end
end

Consider using this instead :slight_smile:

1 Like

is this in a 2d space?
I don’t know, if it is, I tested it and it was a little wrong xd

yes, this is for 2d.

I can’t currently think of way to do the same thing but for 3d but i’m pretty sure it’s the same thing.

And yes it’ll be a little wrong because it won’t be moving on the z-axis :confused:

2 Likes

oh ok, last thing. What is this calculation called? I’ll try to move to 3D as my “great skills”, and I’ll see your explanation in Reply above.

and small mistake here I think:
image
math.pi.2

Ooh goodie a question I can answer.

A very easy function I used is here

function getPredictedPosition(targetPosition: Vector3, targetVelocity: Vector3, projectileSpeed: Number, shooterPosition: Vector3, shooterVelocity: Vector3, gravity: Number)
	local distance = (targetPosition - shooterPosition).Magnitude

	local p = targetPosition - shooterPosition
	local v = targetVelocity - shooterVelocity
	local a = Vector3.new() -- Placeholder

	local timeTaken = (distance / projectileSpeed)
	
	if gravity > 0 then
		local timeTaken = projectileSpeed/gravity+math.sqrt(2*distance/gravity+projectileSpeed^2/gravity^2)
	end

	local goalX = targetPosition.X + v.X*timeTaken + 0.5 * a.X * timeTaken^2
	local goalY = targetPosition.Y + v.Y*timeTaken + 0.5 * a.Y * timeTaken^2
	local goalZ = targetPosition.Z + v.Z*timeTaken + 0.5 * a.Z * timeTaken^2
	
	return Vector3.new(goalX, goalY, goalZ)
end

I used this when creating archers for my line warefare rts.

This video has a good explanation.

Really you can use the SUVAT equations or Calculus to solve this. (I prefer the calculus so that I don’t have to memorise 100 different formulas lol)

If you only want to get the angle. Then simply you can solve for 2d the hieght of the target relative to the shooter and the distance would be x. Then you can simple use atan2(X and Z) to find the “floor” angle

7 Likes

omg, that’s it, thanks!

thanks also to:

@Den_vers
@RatiusRat
@BurningEuphoria
Thank you for taking the time to help me!

1 Like

Hey uh… is that your code? Or did you happen to take the source code from some Unity gamedev page?