Bomb Trajectory for a "Water Canon" (Maths)

Hey there!
I have the following problem:

  • I have a Particlesystem that shoots waterparticles with the local vel = 10
  • There is a target that is not necessarily at the same height as the canon

The Gif should explain what it should be doing, even though there is no variance in the height.

30879-inclinedthrow.gif

So I started with this formula:

30882-c14d095c7d480ca398e25c01a53ed7be.png

This formula calculates the needed angle with a given distance ,velocity and height, it looks like so in C#

private float FindAngleToShoot(float vel, float distance, float height) {

		float g = Physics.gravity.y;

		return Mathf.Atan(Mathf.Pow(vel, 2) + Mathf.Sqrt(Mathf.Pow(vel, 4) - g * (g * Mathf.Pow(distance, 2) + 2 * height * Mathf.Pow(vel, 2))) / g * distance);

}

I don’t really know why this does not work, but it did not change the angle properly.

I started to google again and found another formula, in C# like so:

private float FindAngleToShoot2(float v, float s) {
		float g = Physics.gravity.y;

		return Mathf.Sin(2*(Mathf.Pow(v,2) * g) / Mathf.Pow(s,2)) * Mathf.Rad2Deg;

}

Now I was able to see the angle changing its value, but it changed not properly.
It is hard to describe what actually happens, but it was “flattering” around when I moved the canon forward and backward. At some point the water really hit the fire.

So I thought about an appropiate approach and thought you guys could help me.

  1. find the distance to target
  2. be able to decide to have a high angle approach or a low angle approach
  3. setting the angle and velocity of the water

Shouldn’t that be all?

And I am going to attach the whole “water” class that should do all the maths.

public class Water: MonoBehaviour {

	public Transform target;
	private Vector3 targetPos;

	public float speed = 12; //Speed of the localVelocity of the particle System

	void Start() {
		targetPos = target.position;
	}

	void Update() {

		transform.localEulerAngles = new Vector3(FindAngleToShoot2(speed, Vector3.Distance(transform.position, targetPos)), 0, 0);

	}

	//approach 1
	private float FindAngleToShoot(float vel, float distance, float height) {

		float g = Physics.gravity.y;

		return Mathf.Atan(Mathf.Pow(vel, 2) + Mathf.Sqrt(Mathf.Pow(vel, 4) - g * (g * Mathf.Pow(distance, 2) + 2 * height * Mathf.Pow(vel, 2))) / g * distance);

	}

	//approach 2
	private float FindAngleToShoot2(float v, float s) {
		float g = Physics.gravity.y;

		return Mathf.Sin(2 * (Mathf.Pow(v, 2) * g) / Mathf.Pow(s, 2)) * Mathf.Rad2Deg;
	}

Sorry for the oversized post :confused:

I really appreciate any kind of help!

Felix

This is actually more of a physics problem than a programming problem. Using a fixed velocity makes this much easier, though. The formula you picked out makes sense for these conditions. As you already wrote, the way to solve the problem is indeed to gather the information needed (so height and distance) and then calculate the angle with your formula. Then have the cannon shoot the water at the angle (and the fixed velocity). But there are a few other things to consider:

In code, the formula should look like this:

a = Mathf.Atan((vel^2 - Mathf.Sqrt(vel^4 - g*(g * distance^2 + 2 *y * vel^2))/(g*distance))

Now as you see in the formula, there are two possible solutions, because you’ll have to process a quadratic equation somewhere on the way to get to that formula. As you already noted, the two solutions are a high and a low angle (usually). The thing is, the further we get, the further the angle will converge towards 45° until it can’t reach the target anymore with the set velocity. So one thing you should do is set a maximum distance for your cannon, or else the maths will start to get a bit messy. The other thing is: Does it ever make sense to use a greater angle? The disadvantage is that it takes a relatively long time for the water to reach the target, so if the target moves, that’s not what you want. The advantage, though, is, that you can avoid hitting things you might otherwise hit with a low angle. If that’s not something you need to consider though, the low angle is what you want to go with. The formula I wrote up should return the low angle (not 100% sure but pretty sure).
To recap: Get the distance and height difference, throw them into the formula and adjust the water firing angle accordingly.
Do you want your cannon to have limits for its rotation? If so, you need to set those, too. In that case, if the target is below the cannon and very close it might make sense to fire at a high angle. But if you need help with that, write a comment.