Firebase Compatibility with Unity 2020.1 and Later

Firebase is committed to building an easy to use and robust backend service for Unity developers. Recent changes in the build system accompanying Unity 2020.1 have caused some of the integrations that the Firebase games team built for Unity to stop functioning correctly. Our team is aware of this, and is working hard to rectify the situation. Until then, we recommend that you continue to use Unity 2019 for the best developer experience. For those of you that are on Unity 2020.1, the rest of this post details the workarounds needed to get things up and running.

What happened?

The Firebase SDK for Unity includes native C++ code and Android specific logic. It also requires some build time operations for all of its products to function properly. Because of this, we have written a number of tools and custom routines that make strong assumptions about Unity’s build process. These continue to work to simplify integration back to Unity version 5, but in Unity 2020.1 the engine overhauled its build system invalidating our previous assumptions. This means that the mechanism by which AndroidX and Jetifier are integrated no longer functions as well as the mechanism by which the information in google-services.json is transmitted to your final Android game. This is required to initialize the Android side of Firebase and to properly hook it up to the Firebase backend.

Further, components that the Crashlytics SDK requires to function are no longer generated. In the worst case scenario, this manifests in a crash on launch.

Can I use Firebase with Unity 2020.1 now?

Although we recommend sticking with the 2019 branch of Unity for the best experience, Unity’s new build system is very similar to a typical Android Java project. This simplifies the workaround we will highlight below, and will mirror some steps in the getting started with Android guide.

Note that because you are performing operations that the Firebase SDK would typically handle automatically, you may have to undo any changes when a full fix is rolled out by our team.

Getting Firebase Running

The first fix is to help Firebase find your google-services.json file. Normally the Firebase Unity Plugin would do this automatically, replicating the work of the Google Services plugin Android developers may be familiar with. When you add or update your google-services.json file, the plugin creates a version that Android reads as a “resource” at Assets/Plugins/Android/Firebase/res/values/google-services.xml. Typically this would get copied into your final project automatically, but we can do a little manual work to ensure it gets included!

First generate a custom mainTemplate.gradle and gradleTemplate.properties (which we’ll need in a moment) via Project Settings/Player/Publishing Settings if you haven’t already:

image
image

If you’ve disabled EDM4U’s integration or you just want to be extra careful, now is a great time to also force resolve your Android dependencies from Assets/External Dependency Manager/Android Resolver/Force Resolve. This will update mainTemplate.gradle in a manner that still cuts back on most of the work we’ll have to do:

image
image

Now you need to tell gradle where to find the google-services.xml file by adding this to the very bottom of your mainTemplate.gradle:

android {
    sourceSets {
        main {
            def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("", "/")
            res.srcDirs += (unityProjectPath +  '/Assets/Plugins/Android/Firebase/res/values/google-services.xml')
        }
    }
} 

There’s one more fix to get base functionality working in Unity, you’ll see that towards the top of mainTemplate.gradle there are some lines like:

// Android Resolver Repos Start
([rootProject] + (rootProject.subprojects as List)).each {
    ext {
        it.setProperty("android.useAndroidX", true)
        it.setProperty("android.enableJetifier", true)
    }
} 

This code used to go through every project in the build and enable AndroidX and Jetifier. Although we could perform a similar modification via gradle, Android developers are generally encouraged to use gradleTemplate.properties - which is supported via Unity’s new build pipeline.

So if you remembered to generate it earlier in the tutorial, add the following lines to the end of gradleTemplate.properties:

android.useAndroidX=true
android.enableJetifier=true 

At this point, most of Firebase should function. This includes your ability to measure your game’s performance with Google Analytics, use that to customize your player’s experience with Remote Config, and to Authenticate you user to begin your game’s connection social experience.

Crashlytics Support

Crashlytics needs a little more work to get operational since it has to embed itself a little deeper into the build process. To continue, you will need the baseProjectTemplate.gradle (the “project level gradle file”). You’ll also need launcherTemplate.gradle since we need an “Application” for Crashlytics (mainTemplate.gradle is technically a “Library”):

image
image

There’s no need to Force Resolve dependencies again since EDM4U doesn’t know about these files yet! But you can always do it to be safe (the way I modified mainTemplate.gradle purposely avoids bits of the file that would get updated).

Now open baseProjectTemplate.gradle and look for something that looks roughly like:

allprojects {
    buildscript {
        repositories {**ARTIFACTORYREPOSITORY**
            google()
            jcenter()
        }

        dependencies { 

Inside allprojects.buildscript.dependencies (the dependencies { bit in this example), add this code to tell gradle about Crashlytics:

// Add the Crashlytics Gradle plugin.
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.2.0' 

and this line of code to the very end of launcherTemplate.gradle to add the Crashlytics plugin to your Application:

// Apply the Crashlytics Gradle plugin
apply plugin: 'com.google.firebase.crashlytics' 

Wrap Up

We are working hard to resolve these issues as soon as possible so you can go back to building games quickly, easily, and confidently, with Firebase and Unity. To those developers who did upgrade to Unity 2020.1 and encountered issues, we apologize for any confusion or difficulty that this has caused. We would like to reassure you all that there is also active work on some exciting updates that will aid in avoiding similar issues in the future and bring more transparency to this process.

If these steps don’t work for you, or a specific Firebase library isn’t working after you’ve completed these steps, feel free to join in the conversation at the Unity GitHub repository or reach out to support and we will be happy to provide further help.

Appendix

For your reference, I’ve included all of my modified files here. Do not copy these files directly, but use them to verify that you’ve made the proper changes in the proper locations:

mainTemplate.gradle

// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN

// Android Resolver Repos Start
([rootProject] + (rootProject.subprojects as List)).each {
    ext {
        it.setProperty("android.useAndroidX", true)
        it.setProperty("android.enableJetifier", true)
    }
}
([rootProject] + (rootProject.subprojects as List)).each { project ->
    project.repositories {
        def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("", "/")
        maven {
            url "https://maven.google.com"
        }
        maven {
            url (unityProjectPath + "/Assets/GeneratedLocalRepo/Firebase/m2repository") // Assets/Firebase/Editor/AnalyticsDependencies.xml:18, Assets/Firebase/Editor/AppDependencies.xml:20, Assets/Firebase/Editor/CrashlyticsDependencies.xml:20, Assets/Firebase/Editor/RemoteConfigDependencies.xml:20
        }
        mavenLocal()
        jcenter()
        mavenCentral()
    }
}
// Android Resolver Repos End
apply plugin: 'com.android.library'
**APPLY_PLUGINS**

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
// Android Resolver Dependencies Start
    implementation 'com.google.firebase:firebase-analytics:17.4.1' // Assets/Firebase/Editor/RemoteConfigDependencies.xml:15
    implementation 'com.google.firebase:firebase-analytics-unity:6.15.2' // Assets/Firebase/Editor/AnalyticsDependencies.xml:18
    implementation 'com.google.firebase:firebase-app-unity:6.15.2' // Assets/Firebase/Editor/AppDependencies.xml:20
    implementation 'com.google.firebase:firebase-common:19.3.0' // Assets/Firebase/Editor/AppDependencies.xml:13
    implementation 'com.google.firebase:firebase-config:19.1.4' // Assets/Firebase/Editor/RemoteConfigDependencies.xml:13
    implementation 'com.google.firebase:firebase-config-unity:6.15.2' // Assets/Firebase/Editor/RemoteConfigDependencies.xml:20
    implementation 'com.google.firebase:firebase-crashlytics:17.0.0' // Assets/Firebase/Editor/CrashlyticsDependencies.xml:13
    implementation 'com.google.firebase:firebase-crashlytics-unity:6.15.2' // Assets/Firebase/Editor/CrashlyticsDependencies.xml:20
// Android Resolver Dependencies End
**DEPS**}

// Android Resolver Exclusions Start
android {
  packagingOptions {
      exclude ('/lib/arm64-v8a/*' + '*')
      exclude ('/lib/armeabi/*' + '*')
      exclude ('/lib/mips/*' + '*')
      exclude ('/lib/mips64/*' + '*')
      exclude ('/lib/x86/*' + '*')
      exclude ('/lib/x86_64/*' + '*')
  }
}
// Android Resolver Exclusions End
android {
    compileSdkVersion **APIVERSION**
    buildToolsVersion '**BUILDTOOLS**'

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        minSdkVersion **MINSDKVERSION**
        targetSdkVersion **TARGETSDKVERSION**
        ndk {
            abiFilters **ABIFILTERS**
        }
        versionCode **VERSIONCODE**
        versionName '**VERSIONNAME**'
        consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD**
    }

    lintOptions {
        abortOnError false
    }

    aaptOptions {
        ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
    }**PACKAGING_OPTIONS**
}**REPOSITORIES**
**IL_CPP_BUILD_SETUP**
**SOURCE_BUILD_SETUP**
**EXTERNAL_SOURCES**

android {
    sourceSets {
        main {
            def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("", "/")
            res.srcDirs += (unityProjectPath +  '/Assets/Plugins/Android/Firebase/res/values/google-services.xml')
        }
    }
} 

gradleTemplate.properties

org.gradle.jvmargs=-Xmx**JVM_HEAP_SIZE**M
org.gradle.parallel=true
android.enableR8=**MINIFY_WITH_R_EIGHT**
**ADDITIONAL_PROPERTIES**
android.useAndroidX=true
android.enableJetifier=true 

baseProjectTemplate.gradle

// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN

allprojects {
    buildscript {
        repositories {**ARTIFACTORYREPOSITORY**
            google()
            jcenter()
        }

        dependencies {
            // If you are changing the Android Gradle Plugin version, make sure it is compatible with the Gradle version preinstalled with Unity
            // See which Gradle version is preinstalled with Unity here https://docs.unity3d.com/Manual/android-gradle-overview.html
            // See official Gradle and Android Gradle Plugin compatibility table here https://developer.android.com/studio/releases/gradle-plugin#updating-gradle
            // To specify a custom Gradle version in Unity, go do "Preferences > External Tools", uncheck "Gradle Installed with Unity (recommended)" and specify a path to a custom Gradle version
            classpath 'com.android.tools.build:gradle:3.6.0'
            **BUILD_SCRIPT_DEPS**

            // Add the Crashlytics Gradle plugin.
            classpath 'com.google.firebase:firebase-crashlytics-gradle:2.2.0'
        }
    }

    repositories {**ARTIFACTORYREPOSITORY**
        google()
        jcenter()
        flatDir {
            dirs "${project(':unityLibrary').projectDir}/libs"
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
} 

launcherTemplate.gradle

// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN

apply plugin: 'com.android.application'

dependencies {
    implementation project(':unityLibrary')
    }

android {
    compileSdkVersion **APIVERSION**
    buildToolsVersion '**BUILDTOOLS**'

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        minSdkVersion **MINSDKVERSION**
        targetSdkVersion **TARGETSDKVERSION**
        applicationId '**APPLICATIONID**'
        ndk {
            abiFilters **ABIFILTERS**
        }
        versionCode **VERSIONCODE**
        versionName '**VERSIONNAME**'
    }

    aaptOptions {
        noCompress = ['.unity3d', '.ress', '.resource', '.obb'**STREAMING_ASSETS**]
        ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
    }**SIGN**

    lintOptions {
        abortOnError false
    }

    buildTypes {
        debug {
            minifyEnabled **MINIFY_DEBUG**
            proguardFiles getDefaultProguardFile('proguard-android.txt')**SIGNCONFIG**
            jniDebuggable true
        }
        release {
            minifyEnabled **MINIFY_RELEASE**
            proguardFiles getDefaultProguardFile('proguard-android.txt')**SIGNCONFIG**
        }
    }**PACKAGING_OPTIONS****SPLITS**
**BUILT_APK_LOCATION**
    bundle {
        language {
            enableSplit = false
        }
        density {
            enableSplit = false
        }
        abi {
            enableSplit = true
        }
    }
}**SPLITS_VERSION_CODE****LAUNCHER_SOURCE_BUILD_SETUP**

// Apply the Crashlytics Gradle plugin
apply plugin: 'com.google.firebase.crashlytics'