2
\$\begingroup\$

I'm just starting with physics, so I'm not always sure about what I'm doing. It's a 2D project but I'm using 3D physical objects like SphereCollider etc..

What I have:

Objects floating in space and affecting each other through gravity:

protected virtual IEnumerator OnTriggerStay(Collider other) {
    yield return new WaitForFixedUpdate();

    if(other.attachedRigidbody) {
        Vector3 offsetVector = this.transform.position - other.transform.position;
        float distance = offsetVector.magnitude;
        float gravityForce = (other.rigidbody.mass * mass) / Mathf.Pow(distance, 2);
        // Clamp gravity.
        if(gravityForce > 1.0F) {
            gravityForce = 1.0F;
        }
        other.attachedRigidbody.constantForce.force = offsetVector.normalized * gravityForce;
    }
}

There are controllable objects on which the player can click and drag a line away from the object in order to give it a force (shoot) in the opposite direction.

What I want to achieve:

The player should see a rough prediction of the way while aiming. That means that the way-prediction needs to take in account the current velocity, the force which would be applied when the player release the mouse button and the gravity of the surrounding objects.

What I have tried so far:

For testing purposes I just save the computed/predicted positions in an array and draw those positions in OnDrawGizmos().

I wrote a method which returns the gravity influence for a certain position called computeGravityForPosition(Vector3 position).

And thats how I try to calculate the positions:

private void drawWayPrediction() {
    Vector3 pos = this.transform.position;
    // The offsetVector for the shooting action.
    Vector3 forceVector = pos - Camera.main.ScreenToWorldPoint(Input.mousePosition);
    forceVector.z = 0.0F;

    // The predicted momentum scaled up to increase the strength.
    Vector3 force = (forceVector.normalized * forceVector.magnitude);

    // 1. I guess that this is wrong, but don't know how to do it properly.
    momentum = this.rigidbody.velocity + force;

    for(int i = 0; i < predictionPoints.Length; i++) {
        float t = i * Time.fixedDeltaTime;
        momentum += computeGravityForPosition(pos);
        pos += momentum * t * t;
        predictionPoints[i] = pos;
    }
}

At the beginning, when the objects just slowly approaching each other it looks okay. After the first shot, the prediction is completely wrong. I guess it is because of 1. in the code. Just adding the force to the velocity is probably horrible wrong.

Thank you very much for your time.

EDIT:

I removed seemingly unnessecary parts.

I still think that the main problem lays in 1. in the code. I just don't know how to mix up the current movement of the object (from which I only have the current velocity as far as I know the physics engine of unity) with the new created force:

Vector3 forceVector = pos - Camera.main.ScreenToWorldPoint(Input.mousePosition); Vector3 force = (forceVector.normalized * forceVector.magnitude);

\$\endgroup\$
  • \$\begingroup\$ If you are using a physics engine, keep another world instance on the side, set it up, run that engine for several ticks and display these positions. \$\endgroup\$ – wolfdawn Feb 25 '14 at 8:41
  • \$\begingroup\$ The idea is not that bad, but it would be even better if I would just know what the physics engine is doing when calling AddForce(). Maybe in ForceMode.Impuls. How is it using the current velocity and the applied force to get a new velocity? Then my problems would be solved. \$\endgroup\$ – Wipster Feb 25 '14 at 8:51
  • \$\begingroup\$ Unfortunately it's (most likely) doing a lot of stuff internally - that's it's job. Those add force etc methods probably append the vector to a list to be executed next time the update/step method is called \$\endgroup\$ – ThorinII Feb 25 '14 at 9:43
  • \$\begingroup\$ Nevertheless, at some point the code will be executed. If my physics knowledge would be sufficient I could just do the same and get the positions for some discrete points in time which would representate my way prediction. \$\endgroup\$ – Wipster Feb 25 '14 at 16:55
2
\$\begingroup\$

Since you are using an existing framework that handles the physics it should be relatively simple to maintain a clone (or a saved state) of the world and actually run the simulation for a few tics instead of rewriting the code from scratch.

The reason you wish to use a framework or an engine to complete tasks that were resolved fully by other people that have invested thousands of hours or sometimes hundreds of man-years into that project is that you can save a lot of time and do not have to repeat this process cause they made an interface so simple that it's practically effortless to reuse the fruits of their labor in the creation of your project. Learning how it works is against the principles that make programming a productive labor. The whole idea is that it could be used as a black box in the sense that you don't need to know how it works. When you turn on the washing machine, do you need to know how it's engine converts electricity into a force that is agitating the clothes inside warm soapy water in order to get your clothes clean? Probably not. Imagine how many clothes would go dirty if every houseperson would have to fully understand how their washing machine worked to get their clothes clean? All they need to understand is the interface. If you do figure out how it works precisely and can rewrite it more effectively, why use it in the first place? That in essence is how GPUs came to replace CPUs. People learn some in-depth and then reinvent the wheel in a new and improved way. Unless that is what you are set out to do, don't spend your precious time on this.

\$\endgroup\$
  • \$\begingroup\$ Well, what should I say. You're right. You should outbid the engine you're using. To this point I have no idea what's the impact of holding a complete cloned instance of the physical world to performance. Also I like to think in the approach if KISS - Keep it smart and simple. For me a second instance doesn't seem smart or simple. Imagine you'd like to extend the washing machine in a way that it can predict the cleanness of the clothes. It would be good to know how it works to do that. Even if you could buy a second one and just check how clean it will get with the first. \$\endgroup\$ – Wipster Feb 25 '14 at 18:57
  • \$\begingroup\$ I suppose you are right but wouldn't knowing to predict the engine invalidate the need to have the engine? You might not need another clone, it is possible you only need to maintain a saved state of the current instance. If you think about it my way, predicting the engine in this case (since the engine itself is a simulation) is simply cloning the engine in your own code and running the cloned engine for a few tics. In the case of the washing machine it may seem wasteful since you are actually buying more hardware instead of simulating the process. \$\endgroup\$ – wolfdawn Feb 25 '14 at 19:34

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.