Simulating a trajectory that takes collisions into account

Hi everyone,

I’m looking for a way to simulate (and later render) a shot trajectory that takes collisions into account. Imagine the trajectory arcs shown in Peggle or in pool games - you see how the shot is going to behave and interact with the world around it before you take it. This is relatively straightforward in an environment where you can create a clone of your physics world and step it X times every frame (or whenever you need to). However, I’ve yet to find a way to do something like this with the native box2d implementation of Unity - it seems like there is no way to create you own world object, much less step it on your own. Is there any way I can do this with Unity? If not, why?

Thanks! :slight_smile:

Edit - To clarify, I’m working with the new Box2d engine on a 2d game.

There’s nothing wrong with using your own physics code, I mean if it does what you want without looking bad or screwing up then it should be useable right? I spent some time yesterday figuring this out with linecasting and a line renderer to visualize it, and it turned out pretty good:

alt text

I noticed you meant in 2D after I took the time to figure it out, but the calculations will be pretty much identical just minus an axis. Currently the linecast is a single point so the projectile will appear to bounce from the center of the object, but I’m sure you can simulate a sphere somehow with a bit of math.

The concept is pretty simple, if you have constant values like initial velocity, position, and gravity you can predict the trajectory as long as you move the projectile with the same math. I have a vector for velocity, then a loop depend on an integer of steps like you were talking about, and every step of the loop, add gravity to the velocity as well as linecast ahead with the velocity to check for collisions. I use Vector3.reflect to mirror the velocity and dampen it with a value between 0 & 1 so it doesn’t bounce indefinitely. If it doesn’t hit anything, simply move the position by it’s velocity. The line is constantly redrawn and each step of the loop adds a vertex to the line renderer so you can animate the line’s progression by slowly incrementing the steps.

Here’s a snippet of how I’m predicting it:

void FixedUpdate () {
    if(predict){
        last_pos = muzzle.position;
        velocity = muzzle.forward * fire_velocity;
        line.SetVertexCount(1);
        line.SetPosition(0, last_pos);
        int i = 1;
        while(i < physics_steps){
            velocity += gravity * Time.fixedDeltaTime;
            RaycastHit hit;	
            if(Physics.Linecast(last_pos, (last_pos + (velocity * Time.fixedDeltaTime)), out hit)){
                velocity = Vector3.Reflect(velocity * bounce_damping, hit.normal);
                last_pos = hit.point;
            }
            line.SetVertexCount(i+1);
            line.SetPosition(i, last_pos);
            last_pos += velocity * Time.fixedDeltaTime;
            i++;
        }
    }
}

And here’s how I’m moving the projectile (instantiated at the muzzle position, and it’s velocity is set to the same as the prediction):

void Update () {
    play_speed = Time.deltaTime;
    velocity += gravity * play_speed;
    RaycastHit hit;
    last_pos = transform.position;
    if(Physics.Linecast(last_pos, (last_pos + (velocity * play_speed)), out hit)){
        velocity = Vector3.Reflect(velocity * bounce_damping, hit.normal);
        transform.position = hit.point;
    }
    transform.position += velocity * play_speed;
}

If you’d like to check out the project let me know and I’ll upload it somewhere

That’s a bit confusing because I was talking about a box2d plugin for Unity, not about the built-in box2d engine in 4.3. If you want to use a plugin I would recommend Farseer (Asset Store). In Farseer it’s possible to setup and control the world(s):

world = new World(new FVector2(Physics2D.gravity.x, Physics2D.gravity.y));

...

void FixedUpdate () 
{
    world.Step(Time.fixedDeltaTime);
}

Unfortunately you would need to map the farseer positions to your sprites manually.

Sorry for any misunderstandings.