Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure multiple Firebase projects with Unity

Is it possible to configure multiple Firebase projects for my Unity application without diving into the Android or iOS code? I tried simply switching out the google-services.json file, but this failed to point my Unity app to the correct Firebase app. Ideally I'd like to be able to do something like this:

 void Awake()
{
    if (environment == Environment.Development)
    {
        SetDevelopmentEnvironment();
    }

    FirebaseApp.CheckDependencies();
    FirebaseApp.FixDependenciesAsync();
    auth = FirebaseAuth.DefaultInstance;
}

public void SetDevelopmentEnvironment()
{
    AppOptions firebaseDevelopmentAppOptions = new AppOptions();
    firebaseDevelopmentAppOptions.ProjectId = "test";
    firebaseDevelopmentAppOptions.StorageBucket = "test.appspot.com";
    firebaseDevelopmentAppOptions.AppId = "1:12345:android: xyz";
    firebaseDevelopmentAppOptions.ApiKey = "123Key";
    firebaseDevelopmentAppOptions.MessageSenderId = "123SenderID";
    System.Uri dbURL = new System.Uri("https://test.firebaseio.com");
    firebaseDevelopmentAppOptions.DatabaseUrl = dbURL;
    FirebaseApp.Create(firebaseDevelopmentAppOptions);
}

Or better yet, simply pass the appropriate google-services.json from the Resources folder.

like image 725
Sam Seidenberg Avatar asked Jan 09 '18 17:01

Sam Seidenberg


2 Answers

To add more information on Unity specifically:

The shortest answer is that right now, multiple configurations are not officially supported by the Unity plugin. There are a number of custom processes put into place for backwards compatibility

The way this works on Android is that the script generate_xml_from_google_services_json.py converts your google-services.json file into google-services.xml and places it in a place that gets copied over to the Android build (note that on Windows, this is compiled into generate_xml_from_google_services_json.exe so developers don't have to install python). Ths means that when you swap out this file, you need to make sure the xml gets regenerated (and if you export an Android project before changing your google-services file, then you need to replace the xml rather than the json). This basically duplicates the process of the google services plugin whilst also maintaining backwards compatibility with versions of Unity that predate gradle support. Since it does use the Android resources system, this would be hard to swap out after building a game.

On iOS, GoogleServices-Info.plist is copied over to the final XCode project. It would be rather simple to replace this at any point in your build process, although it wouldn't be easy to swap out after making a build.

Now to do what you first ask in your question, if you can do it at run time in some way. You have to be really careful, Firebase in Unity is a lazily initialized singleton. That is, accessing the property FirebaseApp.DefaultInstance or invoking any function that depends on it will cause a Firebase singleton to be created. You can try manually create a Firebase instance with FirebaseApp.Create(AppInfo), but you'll have to be very structured in your game design to ensure that it gets called before FirebaseApp is implicitly constructed (Create should setup the global default instance, but CheckAndFixDependenciesAsync is an async call that may take more than one frame to complete. This could present a tricky bug surface). You can pass in AppOptions generated from a json file as @Twinsens points out, but having multiple files named google-services.json in your Assets/ directory is not a well defined scenario. You will want to rename your non-default configurations (likely changing the extension to .txt as well so you can retrieve them as a TextAsset).

Something like this:

async void Awake()
{
    var dependencyStatus = await FirebaseApp.CheckAndFixDependenciesAsync();
    if (dependencyStatus != DependencyStatus.Available) {
        // error handling here
        return;
    }

    FirebaseApp app;
    if (environment == Environment.Development)
    {
        // I'm being extra cautious. `DefaultInstance` should have the one you create.
        app = SetDevelopmentEnvironment();
    }
    else {
        app = FirebaseApp.DefaultInstance;
    }

    // I'm being extra explicit just in case
    // for large projects, I'd prefer some sort of DI over the singletons anyway
    auth = FirebaseAuth.GetAuth(app);
}

public FirebaseApp SetDevelopmentEnvironment()
{
    AppOptions firebaseDevelopmentAppOptions = new AppOptions();
    firebaseDevelopmentAppOptions.ProjectId = "test";
    firebaseDevelopmentAppOptions.StorageBucket = "test.appspot.com";
    firebaseDevelopmentAppOptions.AppId = "1:12345:android: xyz";
    firebaseDevelopmentAppOptions.ApiKey = "123Key";
    firebaseDevelopmentAppOptions.MessageSenderId = "123SenderID";
    System.Uri dbURL = new System.Uri("https://test.firebaseio.com");
    firebaseDevelopmentAppOptions.DatabaseUrl = dbURL;
    return FirebaseApp.Create(firebaseDevelopmentAppOptions);
}
like image 87
Patrick Martin Avatar answered Oct 03 '22 01:10

Patrick Martin


You can try this;

 AppOptions.LoadFromJsonConfig(string json);

for more information please visit,

https://firebase.google.com/docs/reference/unity/class/firebase/app-options#loadfromjsonconfig

like image 25
Twinsens Avatar answered Oct 03 '22 00:10

Twinsens