Alex Mason

Softwarrister, friend to animals, beloved by all

Dev log #5 – Making friends with Physics

I took a break from the physics to see what I could get from Unity’s Trail Renderer. The width is a curve, so I figured I would play with it to start, but I’ll leave it at constant width when I’m iterating on other features.

There are a lot of parameters! Time intuitively means how far back in the object’s path the trail shows, though min vertex distance could mean anything. weirdly, autodestruct means the gameobject itself expires when the motion stops, but if it’s a child object of something else it makes sense, like an arrow with a wind trail. Anyway, I thought the width would scale with the gameobject’s transform, but it doesn’t, leading to this ridiculous screen.

It looks like the color parameter doesn’t matter without a material.

I also realized my trail time should not be the same as my time between shots, and that I wanted to specify the space between shots as a multiple of the trail’s length, and the length as a multiple of the shot size, so I did some algebra and exposed those parameters via my shooter script.

In this experiment, we see a constant width trail with the same material as the shot, but without any “end cap vertices” or “corner vertices.”

I was satisfied with the following. A good trail length seems to be 3 shots long, with a good distance being 2 or 3 trails. The shots’ paths are more scattered here, because I was also experimenting with having physics run on Update instead of FixedUpdate. More on that in the next section.

Physics

Although the shots were bouncng reasonably well, there were still issues. The bounce direction does not correspond with the angle of reflection I was computing with raycasts, and the point of bounce is visibly distant from the capsule sprite/collider. Both are illustrated plainly here. The physics simulation has the shots bouncing straight back where they came from. I drew the approximate path I expect the shots to take in red, with the arrow representing the surface normal.

Seeing your shots bounce back up is a really irritating experience when you’re trying for good bank shots that bounce a dozen times or more. Plus, the distance from the surface to the bounce point is perhaps twice the size of the shot itself (minus the trail).

My first idea for a fix was to mess with the number of position iterations, the “Baumgarte” parameters, and the “Default Contact Offset” settings, but they didn’t help. I even tried switching physics from FixedUpdate to Update so it would run faster, but because the frame rate is variable, the offset of each shot at the frame of collision led to a different overlap, which led to a different bounce direction. I later found the setting for how often to run FixedUpdate, still to no avail.

To investigate further and see if my expectations held water, I added a “bounce line” to my aim line, by making a second raycast from where the aim line ends.

See if you can spot the mistake:

        Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        var aimToward = new Vector2(mouseWorldPos.x, mouseWorldPos.y);
        var launchPos = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y);
        direction = aimToward - launchPos;
        // Stop the first line segment at the first wall or block it touches.
        RaycastHit2D hitInfo0 = Physics2D.Raycast(launchPos, direction);
        // Draw the second line segment from the first collision to an expected bounce to the next collision.
        Vector2 newDirection = Vector2.Reflect(direction, hitInfo0.normal);
        RaycastHit2D hitInfo1 = Physics2D.Raycast(hitInfo0.normal, newDirection);
        aimLine.SetPositions(new[] {new Vector3(launchPos.x, launchPos.y), new Vector3(hitInfo0.point.x, hitInfo0.point.y), new Vector3(hitInfo1.point.x, hitInfo1.point.y)});

I ran into a few problems here, some of which elucidate my earlier problem when I was trying to compute the bounces myself, without the physics simulation.

Of course, the bad bounce direction here was my mistake, using the hit normal instead of the hit point for the second raycast’s origin. Someone should do type safety about that!

But after I fixed the mistake, sometimes the second line wouldn’t appear at all. I had hypothesized earlier that sometimes my raycast from a point of collision was hitting the inside of the collider in question.

I found this answer online, but there was no setting called “Raycasts Start In Colliders.” Later on I realized it’s now called “Queries start in colliders,” I guess because there are shapecasts too. I don’t understand why enough users want it to be on that it’s on by default, but turning it off felt so freeing.

Now I had proof that something was wrong. The shots were bouncing straight up when aimed like so:

I had to assume their collisions were producing bad surface normals. How could I make them behave more like the Raycasts?

Finally, I had an epiphany. I had tried making the shots smaller before, and it helped some, but I didn’t want them to look too tiny relative to the blocks. But I had never tried shrinking the collider on its own! The circle collider 2D has a radius, and its minimum is 0.0001. It’s hard to see with The frame rate of the screen recording, but I got a satisfactory result!

earlier dev log posts were meant to be stream of consciousness during the learning and development process, but The work of writing coherently in situ was taking away from development. I’ve moved my note taking elsewhere, so these posts now act more as summaries of my problems and solutions.

Next time: Generating Polygons

Cover Art: Neo stopping bullets, still from The Matrix, WarnerMedia