Confusing Unity mobile player settings for versions

(Edited: 2015/12/15: mostly cosmetic/layout changes)

Background

Unity has its internal PlayerSettings properties for bundle versions, which is set to the built application packages, .apk for Android and .app or .ipa for iOS. Those version parameter names on target platforms are,

  • Android (AndroidManifest.xml)
    • android:versionName
    • android:versionCode
  • iOS (Info.plist)
    • CFBundleVersion
    • CFBundleShortVersionString

while those PlayerSettings properties in Unity are,

  • Unity (Scripting)
    • PlayerSettings.bundleVersion (iOS/Android)
    • PlayerSettings.Android.bundleVersionCode (Android)

The number of version parameters on a platform is 2 per platform (1 for external version string/name as a version text supposed to be exposed to users and market, and 1 for internal version number/code as a version number supposed to be maintained by developer and not necessarily be exposed to users), and 2 for Unity PlayerSettings(bundleVersion and bundleVersionCode).

So I expected there should be 1 to 1 mapping from Unity version properties to Platform version parameters, but it actually is not. Also, in the latest update of Unity(4.6.3, or 4.6.2p1 more precisely), the new PlayerSettings property has been introduced (PlayerSettings.shortBundleVersion), so that iOS developers can set 2 different version strings for iOS(CFBundleVersion and CFBundleShortVersionString), which has made this confused situation, worse(*1), unfortunately.

This article is written to explain this complex and confusing parameter mappings, and to suggest options to fix this problem.

*1) It made the situation better, if we only think about the effect of the change on iOS platform. It used to be only 1 PlayerSettings.bundleVersion property for 2 iOS version plist parameters(CFBundleVersion, and CFBundleShortVersionString) before the patch(4.6.2p1) so developers were forced to use the same version string for 2 different version parameters. And it has been solved in the patch, it is good. But what Unity team did bad was that they keep sharing the same 1 PlayerSettings.bundleVersion for 2 platforms(Android, iOS) for different purposes (android:versionName which is used for external/release/marketing version string, and CFBundleVersion , which is used for internal/build version string).

What are those versions, really?

Android

Per Android official web page, Versioning Your Applications, those 2 versions parameters, versionName and versionCode,  are explained as below.

  • android:versionName — A string value that represents the release version of the application code, as it should be shown to users.The value is a string so that you can describe the application version as a <major>.<minor>.<point> string, or as any other type of absolute or relative version identifier. As with android:versionCode, the system does not use this value for any internal purpose, other than to enable applications to display it to users. Publishing services may also extract the android:versionName value for display to users.
  • android:versionCode — An integer value that represents the version of the application code, relative to other versions.The value is an integer so that other applications can programmatically evaluate it, for example to check an upgrade or downgrade relationship. You can set the value to any integer you want, however you should make sure that each successive release of your application uses a greater value. The system does not enforce this behavior, but increasing the value with successive releases is normative. Typically, you would release the first version of your application with versionCode set to 1, then monotonically increase the value with each release, regardless whether the release constitutes a major or minor release. This means that theandroid:versionCode value does not necessarily have a strong resemblance to the application release version that is visible to the user (see android:versionName, below). Applications and publishing services should not display this version value to users.

iOS

Per Apple official web page, those 2 version parameters for iOS, CFBundleShortVersionString and CFBundleVersion, are explained as below.

CFBundleShortVersionString

CFBundleShortVersionString (String – iOS, OS X) specifies the release version number of the bundle, which identifies a released iteration of the app. The release version number is a string comprised of three period-separated integers. The first integer represents major revisions to the app, such as revisions that implement new features or major changes. The second integer denotes revisions that implement less prominent features. The third integer represents maintenance releases. The value for this key differs from the value for CFBundleVersion, which identifies an iteration (released or unreleased) of the app. This key can be localized by including it in your InfoPlist.strings files.

CFBundleVersion

CFBundleVersion (String – iOS, OS X) specifies the build version number of the bundle, which identifies an iteration (released or unreleased) of the bundle. The build version number should be a string comprised of three non-negative, period-separated integers with the first integer being greater than zero. The string should only contain numeric (09) and period (.) characters. Leading zeros are truncated from each integer and will be ignored (that is, 1.02.3 is equivalent to 1.2.3). This key is not localizable.

Unity

Per Unity official scripting API Reference page, those two (*2) version parameters for Android(bundleVersion and bundleVersionCode) and iOS(bundleVersion), are explained as below. *2) Unfortunately, the newly introduced player settings property shortBundleVersion is not yet documented.(as of 2015/03/05)

PlayerSettings.bundleVersion

Application bundle version shared between iOS & Android platforms.On iOS this should be used as the full incremental build version.

PlayerSettings.Android.bundleVersionCode

Android bundle version code.

How they appear in Unity World

Before the patch(5.0, 4.6.2 or earlier versions)

GUI(Player Settings on GUI)

Android

  • BundleVersion
  • Bundle Version Code

unity4.6.2-android

iOS

  • Bundle Version

unity4.6.2-ios

Asset (ProjectSettings/ProjectSettings.asset)

  • iPhoneBundleVersion
  • AndroidBundleVersionCode

unity4.6.2-psasset

Script

  • PlayerSettings.bundleVersion
  • PlayerSettings.Android.versionCode

Table 1: Versions mappings before the patch

Unity Player Setting(GUI)
Asset(yml)
Android Manifest
iOS Plist
Bundle Version iPhoneBundleVersion versionName CFBundleVersion & CFBundleShortVersionString
Bundle Version Code AndroidBundleVersionCode versionCode n/a

Figure 1: Versions mappings before the patch

unity-versions1

unity-versions-legend

After the patch(4.6.2p1 or later 4.x versions, not 5.0)

GUI(Player Settings on GUI)

Android

  • BundleVersion
  • Short Bundle Version(*)
  • Bundle Version Code

unity4.6.3-android

iOS

  • Bundle Version
  • Short Bundle Version

unity4.6.3-ios

Asset (ProjectSettings/ProjectSettings.asset)

  • iPhoneBundleVersion
  • iPhoneShortBundleVersion
  • AndroidBundleVersionCode

unity4.6.3-psasset

Script

  • PlayerSettings.bundleVersion
  • PlayerSettings.shortBundleVersion
  • PlayerSettings.Android.versionCode

Table 2: Versions mappings after the patch

Unity Player Setting(GUI)
Asset(yml)
Android Manifest
iOS Plist
Bundle Version iPhoneBundleVersion versionName CFBundleVersion
Short Bundle Version iPhoneShortBundleVersion n/a CFBundleShortVersionString
Bundle Version Code AndroidBundleVersionCode versionCode n/a

Figure 2: Versions mappings after the patch

unity-versions2

unity-versions-legend

So what’s wrong(What makes things complicated/confusing)?

  1. Bundle Version (as shown in the Unity GUI Player Settings Label)
    1. The Bundle Version, which is shared among 2 platforms, should mean either one of the internal(build)  or external(release/marketing) version of the build output file (unitypackage, apk, app, ipa, etc). But it means internal version for iPhone, and external version for Android, as shown in the Figure 2 above. This means one single version property is used for two different purposes depends on platform.
    2. Related to above, another additional version property, “Bundle Version Code” (Android only) represents internal version, and “Short Bundle Version” (iOS only) represents external version.
      They are both platform specific additional version property, but used as/represent  different purpose/meanings.
    3. In the project settings file(ProjectSettgings/ProjectSettings.asset), Bundle Version(shown in the GUI Player settings) is mapped to iPhoneBundleVersion. Even it is used for both Android and iPhone, it is prefixed with iPhone which is confusing. In the Scripting Object PlayerSettings, the property name is PlayerSettings.bundleVersion which does not have iPhone prefix tho.
  2. Short Bundle Version
    1. This one is a supplemental version property for iPhone, added by the patch(4.6.2p1), and should not be used in/referred from Android domain. But this player settings property appears in Android player settings(GUI) too.
    2. It is mapped to “iPhoneShortBundleVersion” in the project settings file, which is okay, but in the Scripting PlayerSettings property, it is named “PlayerSetting.shortBundleVersion“, not “PlayerSettings.iPhone.shortBundleVersion“. This is odd and not consistent with how “Bundle Version Code” for Android appears in “PlayerSettings.Android.versionCode“.

So what it should be like in 5.0 patch?

In the figure 2 above, Bundle Version property is used/shared among two(Android/iPhone) platforms, and for two different purposes(internal version and external versions), is the root of all this confusion. So it should be solved/fixed.

I understand that some bad points described in the previous section(esp. naming of the property) may be introduced/kept existing for compatibility purpose(with older Unity versions), but I still need to say that there is an unnecessary confusion introduced by the patch 4.6.2p1.

If Unity team really needs to separate one unique version property “Bundle Version” which was used for both “CFBundleVersion” and “CFBundleShortVersionString” in the iPhone Plist, to two separate version properties so that developer can have two different version strings for them, the original shared “Bundle Version” needs to be unshared with Android, or added property needs to be for internal version (CFBundleVersion, not CFBundleShortVersionString) as it is so in Android player setting.

If they did so, the confusing mixed usage(shared among two platforms, and used for two different purpose) of the “Bundle Version” could be avoided. Also, the patch is applied only to Unity 4.x(4.6.2p1 or later), not yet applied to 5.x (as of 2015/03/06), they can even entirely remove this confusion by abandoning backward compatibility for incoming 5.x patch.

Depends on how they feel the backward compatibility is important, I think Unity team can implement a better fix/patch for this problem as shown below.

Option 1-a. Two shared versions for both Android and iPhone platforms

Figure 3-a: Versions mappings with “two shared versions for both Android and iPhone platforms”

unity-versions4

Pros

  • Simple and clear
  • Just 2 version properties for 2 platforms
  • Backward compatibility with Unity 4.6.2 or before(except asset file and scripting)

Cons

  • Developer can not have different versions per platform(since they are shared among platforms)
  • Unity “Bundle Version” is not mapped to iOS “CFBundleVersion”

Option 1-b. Two shared versions for both Android and iPhone platforms

Figure 3-b: Versions mappings with “two shared versions for both Android and iPhone platforms”

unity-versions7

Pros

  • Simple and clear
  • Just 2 version properties for 2 platforms

Cons

  • Developer can not have different versions per platform(since they are shared among platforms)
  • Breaks backward compatibility

Option 2. Separate versions set per platform

Figure 4: Versions mappings with “Separate versions set per platform”

unity-versions5

Pros

  • Simple and clear
  • No shared version property
  • Developer can have different versions per platform

Cons

  • Breaks backward compatibility

Option 3. Shared bundle version for platform external version

Figure 5: Versions mappings with “Shared bundle version for platform external version”

unity-versions3

Pros

  • Backward compatibility for Android with Unity 4.6.2 or before

Cons

  • Developer can not have different versions per platform(since they are shared among platforms)
  • “Bundle Version” in Unity GUI, is not for “CFBundleVersion” in iOS Plist, sacrifices property name and mapping simplicity and clarification

Option 4. Shared bundle version for platform internal version

Figure 6: Versions mappings with “Shared bundle version for platform internal version”

unity-versions6

Pros

  • “Bundle Version” in Unity GUI is for “CFBundleVersion” in iOS Plist.

Cons

  • Breaks backward compatibility for Android in both naming and semantic wise.

Conclusion

I personally suggest Option 1-b, or 2, since they are cleaner and simpler than others by sacrificing backward compatibility. But luckily the newest Unity version is 5.0, it’s brand new major version, so I hope it is acceptable change for better/cleaner versions handling for many developers. It may even be acceptable to patch to older Unity 4.x too, since the patch 4.6.2p1 was released not long ago, just 1 month old as of this document writing.

If the backward compatibility is still very important for 5.x, then I suggest Option 1-a, which is clean and simple, as well as keeping good backward compatibility too.

References

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s