Author Archives: Matt

Unity iPhone vs. Apple’s Developer License: Time to Worry?

For those of us using Unity iPhone, Apple’s new developer licensing terms are cause for concern. Specifically section 3.3.1, which states:

3.3.1. Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs. Applications must be originally written in Objective-C, C, C++, or JavaScript as executed by the iPhone OS WebKit engine, and only code written in C, C++, and Objective-C may compile and directly link against the Documented APIs (e.g., Applications that link to Documented APIs through an intermediary translation or compatibility layer or tool are prohibited).

This has widely been interpreted as an attempt by Apple to prevent developers from cross-compiling Flash and/or Google Android games for iPhone. John Gruber has a good analysis of this which is somewhat sympathetic to Apple’s position. For unsympathetic opinions, simply swing a dead cat to hit a few. 🙂

(If Gruber is correct then I have to take issue with Apple’s thinking. If a company like Adobe tries to create their own platform on top of Apple’s, I believe Apple’s best defense is to keep adding popular features. That forces middleware companies to either support those features and become more Apple-like, or fall behind. But that’s a topic for another day.)

So should Unity iPhone developers be concerned? Yes, of course. Unity Technologies is urgently trying to get clarification from Apple on this. But until we know the score, there are many reasons to be hopeful for a favorable outcome.

1. Many of the top iPhone games are from companies like Popcap who release cross-platform casual games all the time. Many of these companies do not write their games from scratch for every platform. They target their own internal framework which itself supports multiple platforms. Apple is going to have a real problem if companies like Popcap and Telltale aren’t allowed to do this.

2. Unity Technologies is heavily invested in this issue. If in the end comes down to a matter of what language the game is scripted in, or some other technicality, they are probably going to find a way to get around it.

3. Disallowing middleware like Unity isn’t straightforward, particularly for games. If the final project is built in XCode, and follows the UI guidelines appropriate for that app’s category (e.g. utilities are generally expected to follow Apple guidelines and use the Cocoa controls; but games almost always use a custom user interface) then the product becomes indistinguishable from “native” code from the user’s point of view. It’s hard to imagine that Apple would reverse-engineer games in order to distinguish Unity iPhone games from others.

Of course, Apple has been willfully arbitrary before, so this argument doesn’t hold THAT much water, but it’s a point to consider.

4. People who use Unity are well-positioned to jump to another market if Apple locks this one down. It’s hard to overstate this point. Competing platforms like Android are going to have a field day with this, as it reinforces their message that Apple’s closed system is bad for developers. Google would welcome disenfranchised iPhone developers with open arms. And an Android edition of Unity is already in the works.

The burden is on Apple now to clarify or possibly revise the policy. Personally I think they are going to interpret it narrowly or possibly even retreat from it. It seems to me like a classic case of lawyers reflexively setting up something that in retrospect is difficult to enforce and hurts Apple more than it helps.

Here’s hoping the situation gets resolved quickly.

Isometric vs Perspective Camera

Recently I’ve been experimenting with using an isometric camera for Pawns for the iPhone.

Isometric views have always felt a little cheesy to me, for historical reasons. In the old days it was often used to fake 3D. Since things don’t get smaller as they move further away from an isometric viewpoint, you could use 2D sprites instead of drawing true 3D objects. This was useful when the graphics hardware was only good at drawing sprites. (For example, old arcade games like Q*Bert or Zaxxon painted their 3D graphics this way.)

The iPhone is of course perfectly capable of rendering true 3D. And with Unity I don’t gain any speed just by switching to a isometric view. Even so, the isometric view has a few advantages.

Firstly, the squares near the rear of the board are the same size as those in front, making it easier for the player to place arrows. Pieces in the back are also more visible this way.

I can also optimize the appearance of the 3D pieces. Under perspective it’s hard to make out the crosspiece on top of the king, for example, depending on the angle. In an isometric view the king’s rotation relative to the camera is always the same, whether it is on the left side of the board or the right. So each model only needs to look good from one angle.

This isn’t just a matter of aesthetics, or covering up my mediocre artistic skills. Pawns will not be fun on the iPhone unless each type of piece is instantly recognizable despite the small screen.

For that matter, with care I could improve the graphics by prerendering high-resolution chess models to make 2D sprites. This might improve their appearance- I’ve been having wrestling with lowering the polygon counts without having the pieces look too crappy. (A topic for a future blog entry, perhaps.)

Of course, if I go to billboarded sprites I can’t simply reposition the camera or lights whenever I feel like. And after seeing Pawns in perspective for so many years, I’m having a hard time getting used to the isometric look. Still, I’ll leave it this way for a while longer and see if it grows on me.

Black Cube Postmortem Available Once More

Back in 2002 I wrote a short postmortem analysis of my game Black Cube. For quite a while the uDevGames contest postmortems were unavailable at the iDevGames website, and even now some of the older ones are missing pictures or proper credits, but Black Cube’s at least has been restored.

Even the incomplete articles can be worth a look. I remember learning for the first time about SWIG and using Python as a game scripting language from the Kiki the Nanobot postmortem. And fans of the Freeverse game Kill Monty might get a kick out of the Kill Dr. Cote postmortem. At a minimum, anyone entering a game development contest in the future might want to read a bunch of these to see the ways each developer handled the time pressure, and how the successful ones were able to reach the finish line with something resembling a fun and complete game. (Some success factors I’ve noticed over the years: teams with well-defined divisions of labor; passion for their game; scope control; and plenty of play-testing and feedback from the community.)

Reducing UnityGUI Draw Calls

When trying to improve the performance of a Unity iPhone game, time spent reducing the number of draw calls is usually time well spent.

Unfortunately one of the big draw call “hogs” is UnityGUI. A useful guideline is to only use UnityGUI for game menus and option screens where framerate isn’t important. For in-game controls such as a HUD, developers resort to other methods. Alternatives include GUITextures, SpriteManager, or its commercial sibling SpriteManager 2.

However, other tricks are sometimes possible, and I found an especially easy way to speed up a ScrollView. My game Pawns has a scrolling list that allows the player to pick a puzzle:

Pawns puzzle picker

Pawns puzzle picker

I used UnityGUI for it, and since the game is not actually being played on this scene I was hoping it would be fast enough. However, the screen was unusably slow on my iPhone, and number of draw calls reported by Unity was 165! So a serious rewrite or redesign appeared to be needed.

The structure of my puzzle picker is a Gui.Window for the frame, containing a Gui.Scrollview. Inside of the scrolling view, I loop through the list of puzzles and paint the three elements that make up each line (a checkbox, text for the puzzle name, and a texture displaying the difficulty rating.) The code looks something like this:

scrollPosition = GUI.BeginScrollView (rScrollFrame, scrollPosition, rList, false, false);

for (int iPuzzle = Puzzles.GetFirstPuzzle(), numPuz = 1;
      iPuzzle >= 0;
      iPuzzle = Puzzles.GetNextPuzzle(iPuzzle), numPuz++)
{
    int difficulty = Puzzles.GetPuzzleDifficulty(iPuzzle)-1;
    if ( GUI.Button(rCheckbox, texSolved, checkboxStyle) ||
         GUI.Button(rBtn, Puzzles.GetPuzzleName(iPuzzle), puzzleButtonStyle) ||
         GUI.Button(rDifficulty, ratings[difficulty], puzzleButtonStyle) )
    {
        // Code to jump to the selected puzzle goes here...
    }

    // set up rectangles for the next line
    rBtn.y += lineHeight;
    rTexture.y += lineHeight;
    rDifficulty.y += lineHeight;
}
GUI.EndScrollView();

Each GUI element causes a draw call. (If you are using GUILayout instead of the GUI class, then double that.) The more puzzles in my list, the more draw calls.

For the total number to be as high as 165, even the lines which are currently scrolled off the screen are generating draw calls. On my screen if the player can’t see a line they can’t tap on it, and no code depends on them. In fact, I don’t need to draw them at all. If I was using GUILayout then I wouldn’t know the position of each element, but I’m using GUI, which requires me to position each element myself.

So it turns out it’s a simple matter to skip GUI elements that are not visible. You simply test the rectangle of each control before drawing it. In my case all scrolling is vertical, and the elements are arranged in lines, so I can skip entire lines by testing if either the top or bottom of each line is visible.

The code now looks something like this. Note the line marked *NEW*:

scrollPosition = GUI.BeginScrollView (rScrollFrame, scrollPosition, rList, false, false);

for (int iPuzzle = Puzzles.GetFirstPuzzle(), numPuz = 1;
      iPuzzle >= 0;
      iPuzzle = Puzzles.GetNextPuzzle(iPuzzle), numPuz++)
{
    // *NEW* don't actually draw the controls if this line's rectangle is not visible
    if ( rBtn.yMin >= scrollPosition.y && rBtn.yMax <= scrollPosition.y + rScrollFrame.height )
    {
        int difficulty = Puzzles.GetPuzzleDifficulty(iPuzzle)-1;
        if ( GUI.Button(rCheckbox, texSolved, checkboxStyle) ||
             GUI.Button(rBtn, Puzzles.GetPuzzleName(iPuzzle), puzzleButtonStyle) ||
             GUI.Button(rDifficulty, ratings[difficulty], puzzleButtonStyle) )
        {
            // Code to jump to the selected puzzle goes here...
        }
    }

    // set up rectangles for the next line
    rBtn.y += lineHeight;
    rTexture.y += lineHeight;
    rDifficulty.y += lineHeight;
}
GUI.EndScrollView();

This worked well; only 6 or 7 lines are ever visible at a time, so the draw calls now hovers around 27 no matter how puzzles are in the list. The screen is now usable on my iPhone, though I should probably cut the number of draw calls a little further.

Obviously not everyone will happen to be using ScrollViews so I'll mention a few general approaches to improve UnityGUI's performance:

  • Combine elements/textures. For example, if I painted each line with a single texture instead of three separate elements, that would cut the draw calls by two-thirds. I could go further and paint multiple lines, even entire pages in one texture.
  • Avoid GuiLayout. If you don't use GuiLayout at all, and your GUI script sets
    [code language="csharp"]useGUILayout = false;[/code] early, such as in the Awake method, then the number of UnityGUI draw calls will be cut in half.
  • Redesign. For my example I could have abandoned the scrolling interface and replaced it with page-up/page-down buttons.

I will probably need to try out alternatives such as GUITexture or SpriteManager to speed up my main game screen, so I may have more to say about them at a later date.