Getting a large 4.x project to work with Unity 5 can be a very painful experience. Even though there is some official documentation available, it basically comes down to first installing Unity 5 and then wrestling with compile, build and runtime problems one by one. Since Unity officially stopped supporting the 4.x version, it's useful to share some of the things that we came across while doing the migration.
yield return www;. After spending days trying to figure out what the problem was, we tried building it with 5.1.3p3 and it worked like a charm. Also, newer versions don't seem to have this problem.
Below is a list of concrete problems we had and how we fixed them.
There were a bunch of obsolete functions that had to be replaced. These were:
which had to be replaced with:
respectively. Those were very easy to track and fix.
Unity 5.2 has a new
Mono.Cecil implementation so you might get this error:
error CS0433: The imported type `Mono.Cecil.Cil.SequencePoint' is defined multiple times
The solution is to copy:
C:\Program Files (x86)\Unity\Editor\Data\PlaybackEngines\metrosupport\Tools\SerializationWeaver\Mono.Cecil.dll C:\Program Files (x86)\Unity\Editor\Data\PlaybackEngines\metrosupport\Tools\SerializationWeaver\Mono.Cecil.Mdb.dll
and replace the ones in:
Versions newer than 5.2.0 shouldn't have this problem.
The Unity Analytics system is integrated into Unity 5 so there is no need for SDK. Therefore, if you're using Unity Analytics SDK, you will have to delete all its code and initialize it from the editor (Window -> Unity Services -> Settings). Remember, when building for production, in order for everything to work, you will have to be logged in with the Unity account for which the service is configured. You will get a nice warning in the Build Settings window if you're not logged in properly.
Unable to verify assembly data; you must provide an authorization key when loading this assembly. UnityEngine.Security:LoadAndVerifyAssembly(Byte) c__Iterator3:MoveNext() (at Assets/Plugins/Facebook/Scripts/FB.cs:422)
Unity 4.5 and newer versions have a new way of loading assembly files. This required the Facebook SDK to have an
#if directive to check how to load them. Our version of the Facebook SDK had a check only for Unity 4.5, so you'll just have to add
|| Unity_5 and you're good to go.
There are also standard
Invalid serialized file version warnings that'll require you to rebuild all your assets as Unity has changed the way asset bundles are built (here are a couple of docs on the subject: asset bundle manager and new asset bundle system). Some functions of the
BuildPipeline are now obsolete and you have to use the new system, which also allows you to use Asset Bundle Manager. However, we needed a way of building asset bundles through code by explicitly setting certain assets to specific asset bundles, which meant we could not use the Asset Bundle Manager, and it took some time figuring out how to do that with the new system.
If you've ever built asset bundles then you're probably familiar with their dependencies. Basically, when you build multiple asset bundles that have some shared asset, then you'll most probably want to add that asset only to one asset bundle and avoid unnecessary increase in bundle size. Previously, it was possible to manage those dependencies with
BuildPipeline.PopAssetDependencies. Now you'll have to create an array of
AssetBundleBuilds and pass that array to the
BuildPipeline.BuildAssetBundles function. You'll get all asset bundles along with their manifest files, where you'll be able to see their dependencies. Manifest files, though, won't show you all the assets that are packed in that asset bundle, but just as in previous versions, you can see that in the editor log.
Another thing you should be aware of when building asset bundles with
BuildPipeline is that dependencies between asset bundles are handled only for asset bundles built with the same call of
BuildAssetBundles. So, for example, if you have an asset in an asset bundle created with the first call of
BuildAssetBundles, and the same asset in an asset bundle created with the second call of
BuildAssetBundles, dependencies will not be determined and the shared asset will end up in both asset bundles.
One more thing regarding asset bundles that gave us trouble: after unpacking the asset bundle in the previous version, we used to get its
MainAsset, but now it was always null so we had to get it with the
LoadAsset function. We had that issue with the 5.2 version — not sure if Unity have since fixed it.
Unable to convert classes into dex format
At some point, while we were trying to build for the Android platform, we ended up with an error:
Unable to convert classes into dex format
This was most probably a problem with some of the outdated third-party plugins (for example payment providers, analytics, etc.) that have to be updated with newer versions, which support Unity 5. Another possible reason for having this error was having two or more same .jar files, which some of those plugins use. Check all the .jar files in your plugins and see if you have conflicts.
Unity 5 has changed its lighting engine to
Enlighten. What this means to you is that you'll have to update all of your lighting settings in all scenes and re-bake your lightmaps. Unfortunately, there isn't a way of exporting the
Beast settings and converting them to Enlighten; you will have to do it all over again. Since it can take a lot of time to do that, this was probably the worst thing in all this migration process! Lightmapping Top Eleven Ground in Unity 5 article can help you with that.
After switching our project over to
Unity 5.2.3p1, we noticed that after we unloaded the texture with
Resources.UnloadAsset(texture), even if we used it again later, it never got reloaded. This is despite the fact that, according to the documentation, Unity will reload the asset from disk as soon as it is accessed. After investigating a bit more, we concluded that this behaviour was not the same in the editor and on Android:
- Unity 4.6.8p3
- Editor – The issue was present. After unloading, the texture showed only on objects it was explicitly set to. The exception was that after unloading, the texture was set to the last object it was assigned to — it then showed on all objects it has been assigned to. (It also seemed to work if it was a new object — one on which texture wasn't assigned to previously).
- Android - The issue was present, with no exception. After unloading, the texture always showed only on objects it was explicitly assigned to.
- Unity 5.2.3p1
- Editor – Same as the 4.6.8p3 Editor
- Android – After unloading, the texture didn't ever show again. This was regardless of whether it was set on objects it was previously set on, to new ones, the last one it was set on or some other.
After a long conversation with Unity developers, they informed us that this behaviour has changed since Unity 5.0 and the documentation update got missed. The documentation update will read something along these lines:
The referenced asset will be unloaded. The object will become invalid and can't be loaded back from the disk. Only by loading scenes or assets later that reference the asset on the disk will cause the new instance of the object to be loaded. This instance will be new and not connected to the previously unloaded object.
This was a huge problem for us since we used this functionality to unload textures which we didn't need in order to reduce memory usage on mobile phones. Low-end devices are especially affected by this. At this point, we are still searching for a solution to the issue and will update you if we figure out any workarounds.
Debugging in Visual Studio
If you're using Unity 5.2 (or newer) and Visual Studio to work with C# files, you will probably want to upgrade Visual Studio Tools for Unity to 2.1 (or newer) in order to make the debugging work. Here is an article where you can find the VSTU that your Visual Studio needs.
iOS Specific Problems
We also ran into couple of iOS specific problems:
- Unity now uses ARC (Automatic Reference Counting) by default, so some plugins can give you a headache because of it if they're not migrated. Luckily there is an easy fix because Unity has a neat way of letting you add custom Compile tags for each file. Simply find the concerned .mm/.h file in the Unity project window, then in the inspector check whether iOS is not checked and then add -fno-objc-arc compile — you should be able to see the Compile flags field near the bottom of the inspector. This will disable ARC only for those files and they'll therefore compile.
- After trying to run with Xcode, it couldn't be run because of some missing hpp files. For some reason, Unity 5 doesn't copy hpp files at all! As a workaround, just rename them to .h files update references in the you .m files and you're good to go.
- You can get a lot of linking problems. In our case, it usually meant that some plugin needed an update.
Migrating from older versions to Unity 5 can take a lot of time. Updating third-party plugins can be tricky, especially if you don't update them on regular basis. Some of them might have changed their API a lot and you will find yourself having to re-integrate them if you want them to support Unity 5. Another very time consuming thing is migrating to Enlighten: you'll have to redo all the lightning in all the scenes. And of course, you will have to do the full regression testing of your entire application. Thus, deciding on when to do the migration has to be carefully considered, since it'll most probably require more time than you initially thought!
We've listed concrete problems we stumbled upon while migrating Top Eleven to the new version of Unity with the hope that it'll make it a bit easier for you when you finally do choose to migrate one of your projects. If you have any questions and/or comments along the way, leave a comment below and we'll be more than happy to assist you in any way we can.
Good luck with migration!