So, I’m making a game that has “realistic” 2D physics. At the start, I give a spaceship an initial impulse force, then each loop of FixedUpdate() I am using the gravity equation GMm/R^2 to add the gravitational pull of the planets onto the ship. This all works fine, but what I want to be able to do is predict where the spaceship will be before I give it an initial impulse force, similar to something like Angry Birds. Problem is, this is a lot more complicated because it can’t be done with a simple parabola. Since the position of the spaceship changes when it is launched (as well as the direction of the planet’s gravitational force on the ship), the path of the ship has to be calculated in a loop.
I’ve been working on this for a few days now and I have something that is really close, but I can’t figure out why it is slightly off. If you notice in the video below, the white dots are the path that I predict the ship will travel beforehand, and then once the ship is launched, it deviates from that path (I’m trying to figure out why it does that). The big gray circles are “planets” btw (art is still a WIP clearly lmao).
paymze
What I have so far is simulating each loop of FixedUpdate() in advance. So, just calculating the gravitational force at a position, adjusting the position based on the velocity of the ship from the gravitational force, add a dot every so often, and repeat. To calculate the velocity of the ship at a certain position, I’m using the equation V = ((Fg * t) / m) + Vo, where Fg is the gravitational force from the planets, t is time, m is the mass of the ship, and Vo is the current (or starting) velocity of the ship. I found this equation from this link. It’s the only equation that got me as close as I am now.
I put my code for predicting the path of the ship below for reference as well:
// **** In script attached to the ship object
private void Update ( ) {
// While the ship is being launched, update the positions of the dots
if (IsLaunching) {
Vector2 p1 = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 p2 = Position;
Vector2 direction = (p2 - p1).normalized;
float distance = Utils.Limit(Vector2.Distance(p1, p2), 0, MAX_LAUNCH_DISTANCE);
// If the mouse position was moved, then recalculate the positions of the dots
if (p1 != lastMousePosition) {
// Get the current impulse force that would be applied to the ship if it was launched right now
Vector2 currForce = direction * (distance / MAX_LAUNCH_DISTANCE);
Vector2 currPosition = Position;
// Calculate the initial velocity of the ship based on the force
// Time can be ignored here because the ship will be launched with an impulse (instantanious) force
Vector2 v0 = currForce / Mass;
// Calculate the positions of each of the dots along the ships path
for (int i = 0; i < launchingParticles.Count; i++) {
// Run multiple iterations of this calculation, simulating each frame of FixedUpdate()
for (int j = 0; j < launchParticleDensity; j++) {
// Calculate the gravity force that the ship will experience at the current position
Vector2 gravityForce = levelManager.CalculateGravityForce(currPosition, Mass);
// Calculate the new velocity of the ship at the current position based on the gravitational force from the planets
// Equation from : https://stackoverflow.com/questions/55997293/change-velocity-of-rigidbody-using-addforce
// Tried this link but couldn't get the equation to work : https://schatzeder.medium.com/basic-trajectory-prediction-in-unity-8537b52e1b34
Vector2 v = ((gravityForce * Time.fixedDeltaTime) / Mass) + v0;
// Increment the current position that is being checked based on the velocity
// This is just a basic kinematics equation to solve for the change in position
currPosition += ((v + v0) / 2) * Time.fixedDeltaTime;
// Set the current velocity as the new starting velocity for the next iteration
v0 = v;
}
// Once a certain amount of iterations have been done, set the dot to the current position
launchingParticles[i].Position = currPosition;
}
}
// If the left mouse button is unpressed, disable launching
if (Input.GetMouseButtonUp(0)) {
// Unlock the ship and add a force that is proportional to the distance the player dragged the mouse
IsLocked = false;
IsLaunching = false;
rigidBody.AddForce(direction * (distance / MAX_LAUNCH_DISTANCE), ForceMode2D.Impulse);
}
// Update the last mouse position
lastMousePosition = p1;
}
}
// **** In script attached to ship object
protected void FixedUpdate ( ) {
// As long as the ship is not locked, calculate the force that should be applied to it
if (!IsLocked) {
rigidBody.AddForce(levelManager.CalculateGravityForce(this), ForceMode2D.Force);
// This is another way of calculating the force for the ship
// rigidBody.velocity += (levelManager.CalculateGravityForce(this) / Mass) * Time.fixedDeltaTime;
}
}
I know there must be something I am missing in my equation to calculate the velocity at each position, but I have no idea what that may be. Or the equations might just be totally wrong, I haven’t got a clue at this point. So, any help/suggestions would be very much appreciated :).