I'm trying to remake an old flash game using Unity. The main mechanic of the game is to make the basketball pass over the mouse.
Here's a video of the game: https://www.youtube.com/watch?v=6sArMC1l_Sc
I've been trying to get the hang of this mechanic for two whole days and I still haven't been able to reproduce it. This is what I've been able to make so far. (forgive me for the colors, my screen gives weird colors when recording it)
As you will see, I managed to calculate the trajectory of the ball, and calculate the speed to follow that trajectory. What bothers me is that the vertex of the drawn parabola is not placed on top of the mouse, but it is displaced to the left. The further left the mouse is from the ball, the more this delta between the vertex and the mouse is pronounced.
I think this is happening because I calculate the initial velocity U
using only the angle α
and the maximum height the ball will reach hmax
. I have not found a formula that allows me to "force" the (x,y)
point of the mouse as the vertex of the parabola and gives me a way to calculate the velocity I need to apply to the ball for it to reach that (x,y)
a its highest peak.
I have written a list the parameters and formulas for the SUVAT equations I have found throughout my research on the internet, so I'll list them right below.
/*
* SUVAT EQUATIONS
* S | horizontal distance traveled
* U | initial velocity
* Ux | initial horizontal velocity
* Uy | initial vertical velocity
* V | final velocity
* A | standard acceleration due to gravity on the surface of the earth (≈ 9.807 m/s^2)
* T | travel time
* h | initial height
* hmax | maximum height
* α | release angle relative to horizontal
*
*
* When h = 0:
*
* Ux = U * cos(α)
* Uy = U * sin(α)
* T = 2 * Uy / A
* hmax = (v^2 sin^2(α))/(2 * A)
* hmax = Uy^2 / (2 * A)
* S = (v^2 sin(2 α))/A (old)
* S = 2 * Ux * Uy / A
*
* S = Ux * T
* Ux = S/T
* Uy = (hmax/T + (1/2)) * A * T
* T = (2 v sin(α))/A
*
* When h != 0:
*
* Ux = U * cos(α)
* Uy = U * sin(α)
* t = (Uy + sqrt(Uy^2 + 2 * A * h)) / A
* S = Ux * [Uy + sqrt(Uy^2 + 2 * A * h)] / A
* hmax = (h + Uy²) / (2 * A)
* Uy = sqrt( (hmax - h) / (2*A))
* U = sqrt(V - 2A * hmax)
*/
Here's a recap of the equations I am using to have this result:
Angle Calculation
private float GetAngleInDegreesBetweenMouseAndObject2()
{
_mouseWorldPosition = GetMousePositionFrom3DWorld();
_mouseWorldPosition.z = transform.position.z;
_distanceBetweenObjectAndMouse = Vector3.Distance(transform.position, _mouseWorldPosition);
_mouseDirection = _mouseWorldPosition - transform.position;
var angle = Vector2.SignedAngle(Vector2.left, _mouseDirection);
Debug.Log($"angle: {angle}");
return angle;
}
private Vector3 GetMousePositionFrom3DWorld()
{
// I have drawn a 2D plane in order to be able to get an accurate mouse position, with its Z axis being the same all the way.
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (_launchArcPlane.Raycast(ray, out float distance))
{
return ray.GetPoint(distance);
}
return transform.position;
}
Maximum Height Calculation
private float GetMaximumHeightForObject()
{
return _mouseWorldPosition.y - transform.position.y;
}
Initial Velocity Calculation
private void CalculateInitialVelocityUsingFinalVelocityMaximumHeightAndAngle()
{
_initialVelocity = Mathf.Sqrt(2 * _gravity * _maximumHeight) / Mathf.Sin(_angleInRadians);
}
Initial Velocity Vector Calculation
private void CalculateVelocityVectorUsingInitialVelocityAndAngle()
{
_initialVelocityVector = new Vector3(_initialVelocity * Mathf.Cos(_angleInDegrees * Mathf.Deg2Rad), _initialVelocity * Mathf.Sin(_angleInDegrees * Mathf.Deg2Rad), 0);
}
Setting Velocity To Ball On Click
private void SetVelocityAndGravityForObject()
{
_hasShot = true;
_RigidBody.useGravity = true;
_RigidBody.velocity = _initialVelocityVector;
}
Rest Of The Code
Here's the rest of the code ^^ In case anyone needs any more information in order to get further into this. Beware though, it has some unused functions from the trial an error of different equations I have found throughout the week-end: https://gist.github.com/Juansero29/f3f5a0a7e6c68588dd97ea1fe5d9b59e
I'm an application developer, and I'm interested in the world of games, but I had never tried to achieve a physical mechanic like this, and it's giving me a lot of headaches ^^ (I can't read no more SUVAT equations this week-end lol). Any help from fellow physicians or game develops would be very much appreciated
Edit: Here's the result after using DMGregory's help! Thanks a lot!