XCode6 and the mystery of the missing rect

Since “upgrading” to XCode6 I’ve had issues with storyboard based UI’s that used to work, but now suddenly starts acting really weird – table cells that scale to double size of the containing table, and buttons that don’t react to input because their parent (non clipping) views are cut in half.

Everything looks fine and dandy in XCode, but breaks horribly when running the app on both iOS7 and 8 and both on real devices and in the simulator.

In two cases I tracked the problem down to missing or incorrectly updated view rects – if you open the storyboard in a text editor (or rename it to .xml and open it in XCode or, even better, AppCode) and locate the view that’s causing problems, there’s a good chance you’ll see a rect with incorrect dimensions or simply won’t see any rects at all.

The structure should be:

...
 <view key="view" contentMode="scaleToFill" id="xMb-eO-e2t">
 <rect key="frame" x="0.0" y="0.0" width="320" height="504"/>
 <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
 <subviews>
...

I.e. a <rect> before the <autoresizemask>.

Correcting or inserting the rect fixes the problems and should be ok as long as you don’t do something silly like, say, edit the storyboard in XCode6’s storyboard editor.

But it’s ok. I understand that Apple, with its limited resources, can’t fix every single little insignificant corner-case in XCode when they need to focus their energy on inventing important new and productive programming languages. //sarcasm…

May I just humbly suggest that they got their priorities ass-backwards?

#MadeWithUnity in 7 days

7 Days

IMG_06727 days after I got up in the middle of the night and – for no particular reason – decided to add my own peculiar contribution to a very long list of color-match puzzle games for mobile devices, I finished and uploaded the release build of Qube Crush 3D.

That’s 7 days (and nights) from initial spark to a completed F2P game with 50 levels of brain bending puzzles uploaded to the App Store.

Just to prove to myself that it wasn’t a fluke or a happy accident, and since I had a week or two to burn while waiting for the AppStore review process to complete, I decided to do another game in the mean time.

This was to be a 2 player arena battle game and the result is Magic Micro Battle Arena, which I completed in just 5 days – mostly because it has no IAPs or Ads and no highscores, so less integration work and no horrible IAP testing. Ironically, it also got approved faster because Qube Crush got rejected due to an issue with my AdColony integration.

IMG_0611So two fully functional playable games completed in two weeks. These are not Gears of War or Doom 8, and their feature lists has been cut to the bones, but anyone with an idea of just how much time the crud of project setup, tool chain woes, app-store nightmares and 3rd party integration (not to mention play-testing) usually takes, should realize what an amazingly short time-to-market that is.

The rapid development probably means I missed a bug here or there, and I could certainly have polished both of these two games for another couple of weeks, or months even, but before I do, I’d like to know that there is at least someone out there who wants to play it ;).

Because my investment is so limited, I can try whatever crazy ideas I come up with, and if it fails, I can move on without bleeding to death.

Unity Rocks!

And that’s really why I’m writing this blog post. Because of how this is all possible. Obviously, I *am* a pretty awesome developer (hah! 🙂 ) but, truth be told, I owe most of my productivity to the game-dev tools we have at our disposal today, and at the heart of those is (in my case at least) Unity3d.

I can’t say enough good things about Unity – sure, it has its bugs and quirks and annoying issues, but at the end of the day it’s just so insanely productive that I hardly notice.

I run a 4-screen setup with Unity and Blender on a big cinema display, photoshop on my Cintiq and Mono on my laptop with either my phone or iPad hooked up for testing – with Unity’s rapid automatic import there is no sense of context switching, it’s as if it’s one big application build up of state-of-the-art parts (minus Mono which is anything but).

IMG_0674Testing and trying out stuff in Unity is so quick and easy that in two weeks, I have not once had to start the debugger. Mind you, if launching the debugger from Mono wasn’t such a nightmare, I’d probably been able to finish the games even without cancelling my weekends 🙂

So here’s to the guys at Unity: YOU ROCK!

(But please find a replacement for Mono. For those of us who’d rather chop off our left arm than install Windows, Mono is still (if only barely) the preferable option, but I’d really like to see a Unity/JetBrains C# IDE with bullet proof indexing, a nice coder friendly editor and proper refactoring that does not break script-to-game-object bindings).

If you have an iOS device you can get the apps on the AppStore – Qube Crush is free* and Micro Arena is $1 (if you ask nicely I may have a promo-code for you 🙂 )

https://itunes.apple.com/us/app/magic-micro-battle-arena/id908075215?mt=8

https://itunes.apple.com/us/app/qube-crush-3d/id905380169?mt=8

If you don’t have an iOS device, wait for an Android update, or check out a video of Qube Crush here:

https://everyplay.com/videos/7850308

*) Yes, I know what I’ve previously said about “free apps”, I still think it’s a fundamentally bad idea, but the sad fact of the matter seems to be that as an unknown IP or small game developer you are left with a choice between “free” and, well, nothing else at all… So much for not being part of the problem, though.

C# and it’s broken scope rules

I just got bit by a real fluke in C#.

I’m sure one of Hejlsbergs soldiers will dig deep into the spec and locate some addendum to a side-paragraph that explains it as perfectly reasonable behaviour, but before you do that, I’d like you to inspect the code and, without running or compiling it, tell me what you would expect would happen:

 public void WeirdCSharp()
 {
   int i=1;
   DateTime dt2 = new DateTime();
   switch(i)
   {
     case 0:
       DateTime dt = new DateTime();
       SomeFunction( () => { Debug.Log (dt2); Debug.Log (dt);} );
       break;
     case 1:
       SomeFunction( () => { Debug.Log (dt2); } );
       break;
   }
 }
 public void SomeFunction(VoidEvent d) { d(); }

I expected this to print out dt2.

Not so. In fact, it will throw a run-time error of enigmatic proportions:

ArgumentException: Value does not fall within the expected range.

Never mind that the error makes about as much sense as tea without biscuits, but it is in fact thrown in case 1 when SomeFunction is called – not because there is anything wrong with this line, but because (I assume) the dt variable from the case above is un-initialized but gets captured in the call block due to the messed up switch-level scope.

You can fix it by introducing local scope in the case (add curly brackets). Ironically, I’ve made a general habit of this because C# has weird scope rules in switch statements, but missed it this once.

So yes, there’s a simple workaround, but obviously, C# should never have had scope at the switch level – it made some amount of sense in C when you could fall through from one case to the next, but since C# does not allow this, there is absolutely no point in maintaining this arcane design.

And thus, no reason for this issue to exist.

Smart Watch, Dumb Phone?

So, it seems Apple is finally ready to launch the iWatch – I am probably in the market for one, if for no other reason than the geek factor of it, though I can’t help but think that these things keep doing it ass-backwards.

How is it a “Smart” watch if it is nothing but a dumb accessory to the “Smart” phone. For it to be “Smart” it has to be the other way around. The watch has to be the phone, and the phone has to be the accessory, otherwise it’s just one more gadget I need to remember.

Done right, the Smart Watch is a communication hub with just enough functionality for me to be able to leave the increasingly large, clumsy, battery eating brick of a phone at home.

It should:

  1. Tell the time (wee 🙂 )
  2. Do phone calls
  3. Play music
  4. Check/browse e-mail
  5. Follow twitter and other social media updates
  6. Show my calendar
  7. Maybe even basic GPS / location tracking
  8. Possibly simple home automation
  9. (Oh, and the health thing, for those who find that useful 🙂 )

It does not require a massive CPU or GPU or a big screen but it has to have 3G and WiFi. When I want to play a game, browse the internet, write emails and need the screen real-estate, horsepower, or a semi-proper keyboard, I can turn my watch into a hotspot and connect my (3G-less) “phone” to it.

In fact, I’d probably just connect my laptop or my iPad to the watch and ditch the phone entirely. I don’t really need the phone – it’s a silly device – too small to be useful and too big to drag around all the time.

Unity GameCenter Support

I’ve spend the last couple of days implementing GameCenter support in a Unity game and found more than a few pitfalls all of which goes back to a seriously broken Unity API.

So, if you are planning on using the Social API in Unity3D, here’s a couple of landmines you may not want to step on (I’m sure there are others, but these are the ones that I wasted time on) – oh, and just for the record

1) I love Unity – it’s an awesome platform. It’s just their GameCenter implementation of the Social API that could do with a bit of love 🙂

2) These issues were found in Unity 4.5 (but Google suggests they have been there forever, so I would not count on them being fixed anytime soon)

Loading scores

The first thing that bit me is that ILeaderBoard.LoadScores only supports a single request at a time. If you try to call it multiple times, only the last invocation will receive a callback (several times, whatever good that will do you). I implemented the following helper to work around the issue:

  struct LoadScoreRequest
  {
    public string            _id;
    public string[]          _userIds;
    public BoardLoadedEvent  _callback;
  }

  public delegate void BoardLoadedEvent(ILeaderboard board, HighScore[] highScore);
  
  private bool _friendsLoaded;
  private bool _loadScoreRequestPending;
  private List<LoadScoreRequest> _loadScoreRequests = new List<LoadScoreRequest>();

  public void CreateAndLoadLeaderBoard(string id, string[]userids, BoardLoadedEvent ondone)
  {
    lock(_loadScoreRequests)
    {
      _loadScoreRequests.Add( new LoadScoreRequest() { _id=id, _userIds = userids, _callback = ondone }  );
      SendNextScoreRequest();
    }
  }

  private void SendNextScoreRequest()
  {
    LoadScoreRequest req;
    lock(_loadScoreRequests)
    {
      if(!_friendsLoaded)
        return;

      if(_loadScoreRequestPending)
        return;

      if(_loadScoreRequests.Count==0)
        return;

      _loadScoreRequestPending = true;
      req = _loadScoreRequests[0];
      _loadScoreRequests.RemoveAt(0);
    }

    if(req._userIds==null)
    {
      req._userIds = new string[Social.localUser.friends.Length];
      int i=0;
      foreach(IUserProfile friend in Social.localUser.friends)
      {
        req._userIds[i++] = friend.id;
      }
    }
    
    ILeaderboard board = Social.CreateLeaderboard();
    board.id = req._id;
    board.SetUserFilter(req._userIds);

    board.LoadScores( (bool scoresloaded) =>
    {
      req._callback(board);
      lock(_loadScoreRequests)
      {
        _loadScoreRequestPending = false;
        SendNextScoreRequest();
      }
    });
  }

Basically, it queues up all requests until the GameCenter authentication has been completed and the friends list has been loaded. It then starts loading the leaderboards one at a time, making sure each board gets returned to the proper callback.

The authentication code is not shown above, but it’s straight forward and simply sets the _friendsLoaded member to “true” after loading the friends list and then calls SendNextScoreRequest in case any requests got queued up while authenticating.

Saving scores

IScore.ReportScore does not work.

At least, I could not get it to work. Use Social.ReportScore() instead as it seems to work as advertised, and has the added advantage that you don’t need to carry around the ILeaderboard reference. Why the broken method is even in the public API I can only guess at.

Error handling

Basically, there isn’t any.

At least, you can forget about checking the boolean “success” parameter provided in the various callbacks. I’ve never seen this have a value other than “true” despite a myriad of issues, none of which I’d personally characterise as a “success”.

Instead, check that the data you expected is available – for example, that the user- or highscore-lists are not empty.

UPDATE & WARNING:

Be really careful with Social.LoadAchievementDescriptions – it will load the associated images for all achievements and keep them in memory. They will not be released again.

In my case it amounted to 12 images of 1024×1024 pixels which, with some overhead of unknown origin, amounted to 96MB each time the game refreshed the achievements list.

There’s a similar problem with loading user profiles – their profile images are also kept in memory and are not released when you let go of the profile itself.

Throw to hit

Most people probably don’t consider the intricacies of computer-game enemies shooting at them. In many cases rightfully so, since it’s mostly a very simple feature. The game code to send a fast moving projectile towards you rarely involves more than a subtraction of two points to get a direction, and multiplying with whatever speed bullets happen to travel at in the given game. If it’s fast enough, it’ll hit you. Other times, bullets are instant hit and the game simply checks for intersection with a line segment – no chance of escaping that one either.

In the game I’m currently working on, however, most of the enemies don’t shoot bullets; they throw water balloons. Just as in real life, timing and aiming a throw is quite a bit more involved than firing a bullet, and while most of us learn this as kids by trial and error, a game usually solves it with a bit of math.

It really isn’t much more complicated than the two scenarios I just described, but it does involve matching a polynomial with a linear interpolation, so if both of those sound alien to you, and you happen to be faced with this problem, read on :).

The Stage

Before we look at the math, here’s a quick overview of the problem we’re faced with:

Throwing B at P

Throwing B at P

Let’s say we’re the enemy and we’re at location B0, throwing at the player who is currently at P0. What we want is to find the velocity F that our projectile B must travel with so that it will impact with P when the gravity (g) pulls the projectile to the ground. N is the current velocity of the player.

The path of the projectile is given by the second order polynomial

B = B0 + F*t + G*t²

The path of the player is given by the linear equation

P = P0 + N*t

Assuming, of course, that he does not change direction or speed – which is kind of the whole point of the game 🙂

Before we try to solve this, note that the G vector is special in that it only affects one axis. This simplifies matters a great deal since our second-order polynomial then only exist for this axis, and hence, we can separate the motion in the X/Z plane from that of the Y axis. Or more specifically, we can ignore X/Z and pick a velocity in Y that creates a nice curve and gives us a time of impact, and then adjust our projectile speed in X/Z to match the players location at the calculated time.

So let’s look at the equation for Y:

B0.y + F.y*t + G.y*t² = P0.y + N.y*t

For some rather game-specific reasons, I don’t care if the player moves in Y, so my N.y is always 0. It should be straight forward to change the code to take this into account, you just need to carry the N.y term along. Anyway, in my case, I can simplify to:

G.y*t² + F.y*t + (B0.y -P0.y)  = 0

Which is the 2nd order polynomial we need to solve to determine our time of impact, t. If this doesn’t ring any bells, just google it, there’s a text-book solution for this, and chances are you’ve solved a million of these in school and just forgotten about it ;). Below I’ll just go through the code.

Code

This is what a prettified version of my implementation looks like:

Vector3 P0 = player.transform.position;
Vector3 B0 = enemy.transform.position + initialOffset;
Vector3 F  = (P0-B0);
float l = F.magnitude;
          
if(l>1)
{
  F.y = l*.5f;
            
  Vector3 G = new Vector3(0,-9.81f/2,0);
  Vector3 N = player.transform.forward * player.runningSpeed;
            
  float t = SolvePoly(G.y, F.y, B0.y-P0.y);
  if(!float.isNaN(t))
  {
    F.z = (P0.z-B0.z) / t + N.z;   
    F.x = (P0.x-B0.x) / t + N.x;   
    WaterBalloon b = (WaterBalloon)Instantiate(_waterBalloon);   
    b.transform.position = B0;   
    b.rigidbody.velocity = F;
  }          
}

In short, this starts by picking a Y velocity that is proportional to the distance to the target. This creates a higher arc for targets that are further away. With F.y set, I can solve the second order polynomial for Y and derive the time of impact “t”, which I then use to calculate the remaining two components of F.

F is now my initial velocity which I can assign directly to my (non kinematic) rigidbody in Unity. If, for some reason, you are using a kinematic projectile, you’ll need to move it yourself in the FixedUpdate method. Something along the lines of

transform.position += _velocity * Time.fixedDeltaTime;
_velocity += _gravity * Time.fixedDeltaTime;

should do the trick.

Comments

There’s a couple of details in this code that are maybe not immediately obvious:

Line 2: I add an initial offset to the enemy location to get the projectile start location. This is simply because the enemy is supposed to throw the balloon, not kick it – I.e. I want it leaving his hands, not his feet 🙂

Line 8: I set the Y velocity to half the distance between the enemy and the player. This is a more or less arbitrary choice – the smaller the number, the flatter the curve. Note that this value alone determines time-to-impact, so if you keep it constant, short throws will take just as long to hit as long throws.

Line 10: If you look closer at the definition of G you’ll notice that gravity is defined to be only half of earths normal gravity of 9.81. The reason for this is that the polynomial is describing the curve of the projectile which is the integral of its velocity, not the velocity itself. If you differentiate to get the velocity of the curve:

p = p0 + v*t + k*t² =>

p’ = v + 2*k*dt

…and insert g/2 for k, you will see that the change in velocity caused by gravity correctly becomes g*dt.

Line 11: I calculate the players velocity using his forward direction and a speed – if the target is a non-kinematic rigidbody you could probably use the velocity directly, but mine isn’t.

Line 13: As you probably know, a second order polynomial has two solutions – I, however, only calculate one of them. If you plot the curve, the reason will be obvious: The polynomial will cross zero twice between thrower and target. Once going up, and once coming down – we want the one coming down which is obviously the larger t and because of the nature of our particular set of coefficients, this is always the solution described by s1 below:

private float SolvePoly(float a,float b,float c)
{
   float sqrtd = Mathf.Sqrt(b*b - 4*a*c);
   float s1 = (-b - sqrtd)/(2*a);
   return s1;
}

Line 14: It is worth noting that this *can* fail. If the chosen Y velocity is not sufficiently large to bring the projectile to the same height as the target location, the second order polynomial will have no solutions, and sqrt will return NaN, hence the check for NaN. You *could* check for this in SolvePoly before doing the sqrt, but in my case it’s such a rare occasion that I’m not too concerned with the performance penalty. I’m happy as long as it does not create any visual artifacts.

Lines 16-17: These two equations are easily derived from the original equations for projectile position B and players position P, like this

B0 + F*t + G*t² = P0 + N*t =>

And then solve for F, noting that G is zero in the cases of X and Z which are the ones we are currently interested in.

 F*t = P0 – B0 + N*t =>

F  = (P0 – B0) / t + N

Why you should NOT advertise on LinkedIn!

I got a “promotional offer” from LinkedIn the other day: 300SEK of free advertising.

I’ve been wanting to promote TempusCura for a while, and figured LinkedIn would be a good place to do so, so as a test I created a campaign, provided my CreditCard details (because as always, free promotions are not really free, there was an administration fee of SEK 35:-.), and set it to run immediately.

I deliberately set the burn-rate high at 300SEK/day because I wanted to test if there was a noticeable difference in downloads or web-site traffic, and opted for impressions rather than clicks to get the widest exposure. As I said, it was a test.

I then went on to do other stuff…

This morning, and by complete accident, I ended up looking at the Campaign page of LinkedIn again, and to my horror saw that my little test had burned not 300, but 3.000SEK in two days. Unlike Facebook and Google, the amount you pay for the campaign is not limited (at least not by default) – if I had not seen this today, it would easily have been 30K by the time I was invoiced. Not cool!

So what did I get for my money?

213.000 impressions.

Wow!

Well, wow-not, much as expected, web adverts are not worth the price of the paper they’re not printed on… 213.000 impressions resulted in 20 clicks – probably from existing customers, friends or family.

It’s hard not to laugh. That’s SEK 150:- per click to advertise an app that I sell for SEK 7:-

I don’t know why there are so many ads on web-sites? I mean, I can certainly see it from the point of view of those who get paid, but for the advertisers? Seriously?

My advice: Draw your ad on the back of a piece of toilet paper, wipe, flush, and save a lot of money.