2
\$\begingroup\$

I'm trying to create a simple beer pong game in Unity. The basic idea is this - when it's your turn to shoot, you use your mouse to pick a point on the table that you want the ball to hit and bounce off of.

Then you press the left mouse button, and while it's pressed, move it up and down to determine the degree of the arc of the shot (the ball should hit the same previously chosen spot on the table no matter which degree is chosen).

The arc should be visible as well. It would look something like this: enter image description here

So my questions are:

  1. Given a target point and a launch angle, how do I calculate the trajectory?
  2. Given the same, how do I calculate the force to apply to the ball?
  3. What is the best way to display the trajectory in Unity? My first idea is manually placing a bunch of particles (which is how I did it in the screenshot), but I'm not sure if that's the best choice performance-wise.
\$\endgroup\$
  • \$\begingroup\$ Sounds like a fun game. What do you have so far? \$\endgroup\$ – Evorlor May 18 '15 at 0:02
  • \$\begingroup\$ @Evorlor not much. The ball physics are the first thing I'm trying to do, but without much luck. \$\endgroup\$ – ivan May 18 '15 at 10:34
  • \$\begingroup\$ Can we play the game when it's ready? :P \$\endgroup\$ – Kevin Aug 21 '16 at 19:58
2
\$\begingroup\$

This is fun! The trajectory is just a bunch of mathfz and a line renderer. Check out this post for more information on that which details how to calculate the trajectory. Line renderers are definitely your best bet for visualization. Even on mobile, 5-10 line renderers would be no problem. The alternative would be to hard-code the visualization with a (code-created) mesh or directly rendering to the screen, both of which are not fun.

As for physics, I bet you can use Unity's PhysX out of the box. You'll have to play with the initial force to apply but the direction should be about the direction the camera is facing. All you have to do is multiply by some factor to get it working well.

float X = 10;
PongBall.rigidbody.AddForce(Camera.main.transform.forward * X, ForceMode.VelocityChange);
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks. But the post you linked doesn't really help me. He uses predefined starting velocity and applies it to the projectile. What I need is a bit different. Yeah, Unity's out of the box physics will do just fine, but I'm not sure how to calculate the force I need to apply to the ball. \$\endgroup\$ – ivan May 18 '15 at 10:39
  • \$\begingroup\$ With a pre-defined velocity, you can actually use ForceMode.VelocityChange. That makes a lot more sense for trajectory calculation. With the above code, your starting velocity is 'Camera.main.transform.forward * X'. \$\endgroup\$ – JPtheK9 May 18 '15 at 17:20
  • \$\begingroup\$ Yes, but with a predetermined velocity, I can't leave both the starting angle and the target up to the player. And I want the player to be able to determine the starting angle AND the target because it makes more sense for a beer pong game. \$\endgroup\$ – ivan May 18 '15 at 17:54
  • \$\begingroup\$ No, the velocity is not predetermined. Camera.main.transform.forward is the direction the camera is facing and it was used for the sake of example. It's 100% variable. Just use an FPS controller or something. Btw, don't think of angles. Think of directions with a magnitude of 1 (like slopes on a graph) because that's how the ball thinks when it travels through space. \$\endgroup\$ – JPtheK9 May 18 '15 at 18:11
0
\$\begingroup\$

So I started writing some code for you. Then when I tested it, it didn't have the desired result. Here is the code so far. If anyone know what is wrong with it, do tell :-)

/// <summary>
/// Adds the velocity to simulate throwing a ball
/// </summary>
/// <param name="angle">The angle of the throw along the z axis</param>
/// <param name="direction">The degrees of the throw to the left or right</param>
/// <param name="power">The power of the throw</param>
private void ThrowBall(float angle, float direction, float power)
{
    angle = Mathf.Max(Mathf.Min(0, angle), 90);  //Make sure angle is between 0 and 90
    direction = Mathf.Max(Mathf.Min(-45, direction), 45);  //Make sure direction is between -45 and 45
    power = Mathf.Max(1, power);  //Make sure there is a power of at least 1
    angle *= Mathf.Deg2Rad;  //Convert angle to radians
    float xForce = Mathf.Cos(angle) * Mathf.Sin(direction);  //Get the force to apply to the x axis to throw the ball to the left or right
    float yForce = Mathf.Sin(angle);  //Get the force to apply to the y axis based on the angle
    float zForce = Mathf.Cos(angle) * Mathf.Cos(direction);  //Get the force to apply to the z axis based on the angle
    Vector3 force = new Vector3(xForce, yForce, zForce).normalized;  //Get the force in a Vector3 and normalize it so that the angle does not affect the power
    GetComponent<Rigidbody>().AddForce(force * power);  //Get the Rigidbody Component and apply the force to it based on the angle and power
}

It works if throwing in a straight line, but when adding a left/right directional force, it raises faster than it moves forward. I am very interested in finding an answer to this. I am going to keep looking, and I will update the code as I find out more information.

As for the trail, I would just add particles behind it.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.