Arc trajectory bug fixing, unit tests and MapMagic tangents

Wednesday morning and Saturday work.

Investigating MapMagic — Wednesday’s Unity Asset Store Daily Deal.  Looks like a super procedural generator — both Editor and runtime.  It outputs to a Unity Terrain but the forum suggests it could go otherwise.  I’ve always wondered about a single-player mode that places interesting things at points in an otherwise procedurally generated world.

Decided to buy it.  Lost a few hours to fiddling with it.  Man!  Messing with procedural generation and terrains is a surprising amount of fun!  Kind’a tempted to drop the asset straight into SnwScf project and hack-up a single-player mode.  Not now!  😉

Noticed an oddity: A rolling snowball hitting a snowman hits assertion failure:

SnowballShot !spawned but being destroyed. Not merely done twice in same frame, now:8504, spawnedChangedFrameNumber:8502

Not a problem but indicative of some mistake / mistaken understanding.  Have to come back to this since…

Darn, while capturing screen-shots for this post, I’ve just noticed the aim-assist going completely wrong!?  What looks like a straight shot is actually doing a lob, arcing waaaay over the top of the target.  Great 😐

Screenshot 2016-05-25 09.59.39.png

“Excuse me old bean, I don’t mean to criticize but I’m down here.”

Oddly it really is fine most of the time — I can only seem to prompt this when I’m trying for a screenshot!?  Riiiiiight.  Hopefully it’s something related to pausing the Unity Editor but I can’t really trust that without investigating.

Sigh, I thought that functionality was all sorted.  Guess I need more integration tests … ok, admission time:  By that I mean /some/ integration tests on this area 😦  They broke when I upgraded Unity most recently and I haven’t invested the time to resolve what happened.  Shame on me.  That is one of the downsides of my integration tests — they feel rather too brittle and aren’t runnable without jumping to the integration test scene.  OK, probably the better answer is that this area should be unit tested rather than as well as integration tested.)

So, I did warn this was going to basically be my dev notes.  Often they’re high-level discussions but, “when the going gets maths, the notes get mathsy”.  Erm?  Fair warning: Here be details!

Let’s get some values in here:

Shooter transform:
  pos: 11.05, 0.75, -0.23
  ori: 4.22, 90, 0

Target transform:
  pos: 16.11, 0.64, 0.53
  ori: 355.36, 155.00, -0.00

Targeting logging:
  (targetPos:(16.1, 1.6, 0.5), rbl.velocity:(0.0, 0.0, 0.0), transformToAffect.pos:(11.1, 1.5, -0.7), bulletSpeed:9.857765, shooterVelocity:(0.0, 0.0, 0.0), shotObj.aimingShouldConsiderGravity:True, maxTTL:2)
  => timeToImpact:0.5230598, launchVector:(4.8, 8.5, 1.2)

Obviously launchVector y component 8.5 is causing the lob over the target’s head.  Either enable more detailed logging or debugger.  Going with latter.

targetPos = "(16.1, 1.6, 0.5)"
bulletPos = "(11.1, 1.5, -0.7)"
Follows the "stationary target" code path.
Follows the "gravity-compensating projectile lob" code path and calls my ArcTrajectoryUtils.getLaunchVector() code.
planeVectorToTarget = "(5.0, 1.3)", range = 5.15528f, height = 0.0974731445f
then does getLaunchAngle(range, height, projectileInitialSpeed, gravity), i.e.
getLaunchAngle(x = 5.15528f, y = 0.0974731445f, u = 9.8219f, g = -9.81f) -- this might be the part that needs working, perhaps use as unit test?
for +/-, minus = -58.2228546f so used plus = 77.86665f.
Result from getLaunchAngle() angle = 1.04258835f.  Hm, that's radians = ~60 degrees elevation!
Just to carry this through, it then calls convert3SpaceScalarsToVector(vectorToTarget = "(5.0, 0.1, 1.3)", projectileInitialSpeed = 9.8219f, angle.Value = 1.04258835f)
Eventual launchVector = "(4.8, 8.5, 1.2)"

So, looks like there’s an error in getLaunchAngle(), perhaps its use of +/-.  Unit test time.  Also it’d be nice to get a code path for working situation — is it that the ‘minus’ case always works  when used and the ‘plus’ case always fails when used?

The formula it’s using is from this gamedev.net post.  It’s working well most of the time.  Hmm.

Added unit test for all this code (ArcTrajectoryUtils).  Also added unit tests for general ProjectileAimingUtils.  For the latter, I also wrote an IEqualityComparer<Vector3> so I could use NUnit’s constraint-based “EqualTo().Using()” testing approach with an epsilon value (i.e. the allowed proximity).  (I find it odd that C# doesn’t allow inline implementation of interfaces — had to add an actual concrete implementation to my VectorUtils!?)  Anyway, it allows this:

assert.That(v1, Is.EqualTo(v2).Using(VectorUtils.buildVector3Within(epsilon)));

Covered the area in unit tests.

Ahha!  Found the problem — I’d slightly mistranslated the equation!  Bracket in the wrong place was giving the wrong result in some cases!  Fixed and committed!

Since it’s a bank holiday weekend here in the UK, I’m calling Saturday an early night to pick up for something more fun than bug fixing tomorrow — maybe more fire?

p.s. since I was lost in the depths bug fixing (and parenting) all #ScreenShotSaturday, I tweeted this and was kind’a pleased it got as many Likes as most of my SSS pics!  I get the strong impression all gamedevs wish they could do proper software engineering with things like testing, etc 😉