With so much time spent on game development, the last thing any game developer wants to see is a low rating as a result of a buggy game. From our very first Crashlytics NDK release back in 2015, our commitment to game developers remains strong. And recently we released a number of NDK and Unity features that not only increase the stability of games, but also enable developers using Unreal, Cocos2d, Unity or any other native game engine to get to resolutions quickly and with more confidence. Read more about these improvements below.
To provide you with a more accurate view into the stability of your gaming apps, we’ve made significant changes to Crashlytics' native crash capture mechanism by adopting Google's open-source Crashpad library. As a result, you can now get access to several additional classes of errors on newer Android versions as well as get more reliable crash reporting on existing Android versions of your app. Additionally, with Crashpad you no longer have to deal with the inherent complexity of native crash capture and instead you can focus your time on growing your game.
The increased reliability of Crashpad lies in its pursuit of minimizing the amount of work done within the signal handler, which ultimately results in a more reliable crash capturing mechanism. One of Crashpad’s core design goals is to reduce the number of system calls inside the handler to just one. Upon receiving a signal, Crashpad captures the memory space of the crashed application by launching a brand new, healthy process, removing some of the problems of other crash capture approaches such as capturing SIGABRT on Android 10+ devices.
More accurate stack traces, especially within the application frames, lead to faster issue resolutions - there is no doubt about it! That is why we’ve switched our symbol file format to one that is more robust - the Breakpad symbol file. The additional debug information within the Breakpad symbol file, in many circumstances, results in a more accurate stack trace than what you’d see in the logcat.
The key to more accurate stack traces lies within the Call Frame Information that is stored within the debug section of the binaries. This information is what differentiates the Breakpad symbol file from our previous symbol file. Call frame information assists our backend stack unwinding process, minimizing the use of heuristics within application frames that may lead to incorrect stack traces. With this information, our backend more precisely determines how the frames within your application should be unwound and which symbols - inlined or not - correspond to each frame!
Take a look at the Google Games Developer Summit session that explains this in more detail. If you’re already using the Crashlytics NDK SDK, switching to the Breakpad symbol file is a breeze, just add symbolGenerator { breakpad() } to your build.gradle. Check out our docs for more info.
symbolGenerator { breakpad() }
The left image shows a stack that is unwound using our previous symbol format, and the right image shows the same stack unwound using the Breakpad symbol file.
The top image shows a frame symbolicated using our previous symbol format, and the bottom image shows the same frame symbolicated using the Breakpad symbol file.
We heard your feedback around symbol uploading for main applications and stand-alone libraries. And with the latest Crashlytics Gradle plugin, specifying the stripped library directory is no longer necessary so you can get quickly set up with minimal error. We’ve also allowed the unstripped path to point to disparate directories, allowing symbol upload for binaries that are compiled outside of the main application.
We’ve improved grouping for Unity crashes to help you more quickly debug and identify the exact cause of a crash. Our analysis backend now has a more robust set of Unity heuristics, resulting in much better issue fidelity and a more intuitive stack trace visual treatment. No longer will issues highlight a system frame when an application frame is the source of the problem.
Revised Unity Grouping in Crashlytics Console
We’ve enabled automatic capture of various hardware attributes and game-specific values to help solve unique issues related to the model of GPU and screen resolution for example, so you no longer have to capture these yourself and use up valuable key-value pairs.
Unity metadata in Crashlytics console
We hope these improvements help make identifying crashes much easier, and we will continue to improve the games experience by focusing on improving Unity IL2CPP support - support that includes capturing Unity Engine and native extension crashes. Let Crashlytics handle crashes for all of the components that your game depends on, because sometimes, the crash is not your game's fault. There is much more on the horizon, stay tuned!
In the meantime to get started, head to our NDK and Unity onboarding pages. We're excited to help you through your game development journey and can’t wait to hear what you think!
A few months ago, we released Firestore for Games into open alpha. Thanks to all of your feedback, today, we're happy to announce that Cloud Firestore for Games is now publicly available in beta for C++ and Unity developers.
Firestore is a new performant and scalable serverless database option from Firebase for all your game development needs. It can help you add guilds to your latest mobile game, build a backend for your next big turn-based game, or add realtime chat. It’s also a key component of Firebase Extensions like Translate Text and Trigger Email, making it easier than ever to deploy pre-built complex workflows to your games.
Cloud Firestore is Google’s next generation cloud NoSQL database. It’s fast, reliable, and ready to scale for whatever workload you send its way. For the past two years it’s been generally available for the Web, iOS, and Android, and now it’s available for game developers as well.
Cloud Firestore exists alongside our existing Realtime Database. We’ll continue to support Realtime Database because it still works great for when you need to share data quickly with lots of players in near realtime. With Firestore you get more advanced queries on your data, 99.999% guaranteed uptime, and support for up to a million concurrent players -- all whilst remaining fast enough for many of your gaming backend needs. If you need more help deciding which database is right for you, check out this helpful guide.
Even though Firestore has been generally available for some time, the existing SDKs were built with the workflows and tools favored by app and web developers. Although game developers working in languages like JavaScript, Kotlin, and Swift would have no problem adopting the existing development kits, you would’ve had to jump through hoops to access them from Unity or C++. However, here at Firebase and Google, we want to make it easy for game developers to build, release, and operate games. So, we've built SDKs that bring game developers the same levels of convenience that app developers enjoy.
The Beta tag means that we believe that the Firestore SDKs for Unity and C++ are now stable enough that game developers can confidently use them in shipping games. Bugs and small API tweaks may crop up here and there as more developers pick it up, but Firestore is now a viable option when starting new game projects.
A big improvement that alpha testers might notice is that the new libraries have full feature parity with the platform specific Firestore SDKs. This includes many features alpha testers have asked for, such as OnSnapshotsInSync and support for the Blob data type. All transforms (like incrementing values) and query types (like "array-contains-any") are now implemented as well. We’ve also worked to make Firestore more consistent with the other Unity Firebase SDKs by ensuring that events fire on the main thread and adding more consistency to error reporting.
OnSnapshotsInSync
Since we’ve seen that many game developers tend to target multiple platforms with a single codebase, we’ve ensured that every feature in Firestore SDK C++ SDK works identically on iOS, Android, Windows, Mac, and Linux. This means that you can develop your game logic on a desktop computer with access to the entire Firestore for games feature set, and remain confident that it will continue to function on your target device. We've also fully opened sourced the C++ SDK so you can easily build, debug, and port your code to wherever you need.
This Firestore beta, like the alpha, ships with the standard Firebase C++ and Unity SDKs. To use it, simply ensure you’re using the latest Firebase SDK either by downloading the C++ zip or the Unity zip. Remember, if you come across any bugs, report them to us through our support channel or on the C++ or Unity issue pages.
how to deal with asynchronous logic in Unity
The Firebase Unity SDK makes judicious use of asynchronous logic for many of its calls. Unity itself isn’t super resilient to threaded logic, with most of the classes and functions in the UnityEngine namespace just flat out throwing exceptions if invoked off of the main Unity thread. My goal with this post is to provide you the tools you need to not only safely use Firebase’s asynchronous function calls, but to do so in a way that best suits your own programming style and preferences. Ideally even giving you more confidence to thread other parts of your game to provide your players with the smooth and responsive gameplay they expect from a modern video game.
UnityEngine
Let’s get started with a very innocent looking demo script:
using Firebase; using Firebase.Auth; using UnityEngine; using UnityEngine.Assertions; public class FirebaseContinueWith : MonoBehaviour { // Start is called before the first frame update void Start() { Debug.Log("Checking Dependencies"); FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(fixTask => { Assert.IsNull(fixTask.Exception); Debug.Log("Authenticating"); var auth = FirebaseAuth.DefaultInstance; auth.SignInAnonymouslyAsync().ContinueWith(authTask => { Assert.IsNull(authTask.Exception); Debug.Log("Signed in!"); var successes = PlayerPrefs.GetInt("Successes", 0); PlayerPrefs.SetInt("Successes", ++successes); Debug.Log($"Successes: {successes}"); auth.SignOut(); Debug.Log("Signed Out"); }); }); } }
The first thing I do is ensure that Firebase’s dependencies are available on the player’s device with CheckAndFixDependenciesAsync. Note that I’m not really handling any failure cases in this example. This shouldn’t be an issue for this post, but you’ll want to do more than assert in your own games.
CheckAndFixDependenciesAsync
Next I use ContinueWith to create a continuation and I start signing in anonymously with SignInAnonymouslyAsync.
ContinueWith
SignInAnonymouslyAsync
When sign-in completes, I figure out how many times this script has run successfully before by reading PlayerPrefs. Then I increment this value, and write it back out before logging the new number of successes.
This is all super straightforward. I run it and… I just see the log “Signed In!” then nothing. What happened?
Firebase does a lot of work that’s dependent on I/O. This can either be out to disk, or even out to the network. Since you don’t want your game to lock up for potentially many seconds for network latency, Firebase uses Tasks to perform much of this I/O work in the background.
Whenever you continue from this work, you have to be careful to come back into your game in a graceful manner. I’ve done none of that here, and have just charged right into a shared resource managed by the UnityEngine in the form of a call to PlayerPrefs. This most likely raised an exception, but it even got lost in the background thread! What can you do to fix it?
PlayerPrefs
C# has the concept of a TaskScheduler. When you say ContinueWith, rather than just letting it continue on whatever thread the task completed on, you can use a TaskScheduler to force it onto a specific thread. So, I can modify the example to cache the TaskScheduler on which Start() was called. Then I pass that into the ContinueWith statement to be able to safely change the state of objects in my game:
TaskScheduler
Start()
Debug.Log("Checking Dependencies"); var taskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(fixTask => { Assert.IsNull(fixTask.Exception); Debug.Log("Authenticating"); var auth = FirebaseAuth.DefaultInstance; auth.SignInAnonymouslyAsync().ContinueWith(authTask => { Assert.IsNull(authTask.Exception); Debug.Log("Signed in!"); var successes = PlayerPrefs.GetInt("Successes", 0); PlayerPrefs.SetInt("Successes", ++successes); Debug.Log($"Successes: {successes}"); auth.SignOut(); Debug.Log("Signed Out"); }, taskScheduler); });
Since Start executes on the Unity main thread, I grab the scheduler with TaskScheduler.FromCurrentSynchronizationContext(). This way I can get back to the main thread later by passing the scheduler into my second ContinueWith statement. Now whatever work I do in that ContinueWith block will be done in sequence with the game rather than in parallel with it, preventing any threading issues.
TaskScheduler.FromCurrentSynchronizationContext()
When I run the script, I can see that I finally have one success (and that this script hasn’t succeeded before).
This pattern is really common so Firebase provides an extension method named ContinueWithOnMainThread that does all of that hard work for you. If you’re using a newer version of the Firebase Unity SDK, you can write the above as simply:
ContinueWithOnMainThread
Debug.Log("Checking Dependencies"); FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(fixTask => { Assert.IsNull(fixTask.Exception); Debug.Log("Authenticating"); var auth = FirebaseAuth.DefaultInstance; auth.SignInAnonymouslyAsync().ContinueWithOnMainThread(authTask => { Assert.IsNull(authTask.Exception); Debug.Log("Signed in!"); var successes = PlayerPrefs.GetInt("Successes", 0); PlayerPrefs.SetInt("Successes", ++successes); Debug.Log($"Successes: {successes}"); auth.SignOut(); Debug.Log("Signed Out"); }); });
A word of caution as well. In C#, you can safely assume that anything in your ContinueWith block hasn’t been garbage collected. The same doesn’t hold true with Unity’s design. If you were to access any fields of this MonoBehaviour or its encompassing GameObject after OnDestroy is invoked, you would want to check that this hasn’t become null. Due to the way Unity implemented this as well, you cannot do so with the ?? operator.
MonoBehaviour
GameObject
OnDestroy
this
??
Hopefully I’ve shed a little light on what’s happening in these tasks and continuations in Unity. You may also be a little frustrated now. What should be a simple block of code where we fix dependencies, sign on, then do work has become this ugly mess of nested statements that just becomes harder to read as we chain more steps into the logic. If only there were a better way!
Although the goal of tasks is to perform operations in parallel, so much logic in programming is sequential. Since continuations get hard to read, C# provides a mechanism in async/await syntax to represent this sequential logic. To use this mechanism, I’ll rewrite the Start method like this:
Start
async void Start() { Debug.Log("Checking Dependencies"); await FirebaseApp.CheckAndFixDependenciesAsync(); Debug.Log("Authenticating"); var auth = FirebaseAuth.DefaultInstance; await auth.SignInAnonymouslyAsync(); Debug.Log("Signed in!"); var successes = PlayerPrefs.GetInt("Successes", 0); PlayerPrefs.SetInt("Successes", ++successes); Debug.Log($"Successes: {successes}"); auth.SignOut(); Debug.Log("Signed Out"); }
The first thing you’ll notice is that I denote Start as async. This tells the C# compiler “this function will perform work in the background. Do something else whilst it finishes up.”
Then, I replace ContinueWith with the await keyword. If I were doing anything with the Task’s result, I could store the result in a variable.
await
Task
This reads much better, but why doesn’t my code break like the very first sample? It turns out that async functions will always return to the thread they’re awaited on. This way you don’t have to be as careful about thread safety in functions where you do this. In fact, by default, async functions that are awaited will typically execute on the thread that called them unless the developer explicitly did something else.
async
There is one downside compared to the ContinueWith sample though: the code following CheckAndFixDependenciesAsync will execute on the Unity main thread rather than potentially running on a background thread. In practice, this won’t be much of an issue. It could be a behaviour of note if you’re doing some significant amount of work between calls to await. Be aware as well that this code is very similar to the continuation example above. Just like how Unity may clean up your underlying MonoBehaviour before ContinueWith executes, Unity may clean it up when the call to await completes. If you access any member fields after a call to await, you should check to ensure this is not yet null.
Unity has the concept of coroutines, which used to be the preferred method of performing asynchronous work across multiple frames. The interesting bit about Coroutines is that they’re not really asynchronous, behind the scenes they simply generate IEnumerators which are evaluated on the main thread.
Unity has some special yield instructions such as WaitForEndOfFrame and WaitForSeconds, allowing you to jump around to different moments in your game’s time. I choose to implement a new CustomYieldInstruction to wait for a task to complete. I’ve even seen some developers convert something like this into an extension method on the Task class itself!
using System.Threading.Tasks; using UnityEngine; public class YieldTask : CustomYieldInstruction { public YieldTask(Task task) { Task = task; } public override bool keepWaiting => !Task.IsCompleted; public Task Task { get; } }
I can now use yield return on a Task, such as the Tasks typically used for Firebase, to make my asynchronous logic read sequentially. Inside it, I wait for a task to complete with a standard continuation. If I were actually doing something with the result of a Task, I’d have to build this class out a little more. For the time being, this will work to illustrate my basic point.
yield return
I can then reimplement my async/await logic using coroutines like this:
using System.Collections; using System.Collections.Generic; using Firebase; using Firebase.Auth; using UnityEngine; public class FirebaseCoroutine : MonoBehaviour { void Start() { StartCoroutine(DoWork()); } private IEnumerator DoWork() { Debug.Log("Checking Dependencies"); yield return new YieldTask(FirebaseApp.CheckAndFixDependenciesAsync()); Debug.Log("Authenticating"); var auth = FirebaseAuth.DefaultInstance; yield return new YieldTask(auth.SignInAnonymouslyAsync()); Debug.Log("Signed in!"); var successes = PlayerPrefs.GetInt("Successes", 0); PlayerPrefs.SetInt("Successes", ++successes); Debug.Log($"Successes: {successes}"); auth.SignOut(); Debug.Log("Signed Out"); } }
My Start function now just immediately calls a function called DoWork, which is my coroutine.
DoWork
Since I’m not doing anything with the return value of the async function calls, I just allocate temporary YieldTask objects and return them in the DoWork coroutine.
YieldTask
Now there are some important pros and cons to consider if you use this type of logic. This will have a performance hit as not only does the work between each yield return call execute on the main thread, but the property keepWaiting is queried every frame. On the other hand coroutines only exist for as long as a MonoBehaviour hasn’t been destroyed. This means that those caveats I mentioned above with having to check for null after an await or inside a ContinueWith don’t apply to coroutines!
keepWaiting
Sometimes the performance characteristics of coroutines don’t match up exactly to what you want. Remembering that a CustomYieldInstruction is queried every frame, you may end up in a state where Unity is performing many checks against against the keepWaiting property. In this case, it may be beneficial to queue these actions on Unity thread manually by adding work to a queue when it’s ready to be processed. Note that this is effectively how ContinueWithOnMainThread works and you should use that method when possible.
With that in mind, let’s look at an example of how I’ve implemented an action queue:
using System; using System.Collections.Generic; using System.Linq; using Firebase; using Firebase.Auth; using UnityEngine; using UnityEngine.Assertions; public class FirebaseQueue : MonoBehaviour { private Queue<Action> _actionQueue = new Queue<Action>(); void Start() { Debug.Log("Checking Dependencies"); FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(fixTask => { Assert.IsNull(fixTask.Exception); Debug.Log("Authenticating"); var auth = FirebaseAuth.DefaultInstance; auth.SignInAnonymouslyAsync().ContinueWith(authTask => { EnqueueAction(() => { Assert.IsNull(authTask.Exception); Debug.Log("Signed in!"); var successes = PlayerPrefs.GetInt("Successes", 0); PlayerPrefs.SetInt("Successes", ++successes); Debug.Log($"Successes: {successes}"); auth.SignOut(); Debug.Log("Signed Out"); }); }); }); } public void EnqueueAction(Action action) { lock (_actionQueue) { _actionQueue.Enqueue(action); } } void Update() { while (_actionQueue.Any()) { Action action; lock (_actionQueue) { action = _actionQueue.Dequeue(); } action(); } } }
This starts much like all of my continuation based examples. Unlike those, I call EnqueueAction to perform work on the main thread. I would highly recommend breaking this into two different MonBehaviours so you don’t forget to call EnqueueAction, but I’m compressing this for illustrative reasons.
EnqueueAction
MonBehaviour
The EnqueueAction function locks the Queue and adds some nugget of logic in the form of a C# Action into a list of logic to be executed later. If you get really clever, you may be able to just replace all of this with a lockless thread safe queue.
Finally, in Update, I execute every enqueued Action. It is very important to NOT execute the action with the _actionQueue locked. If the Action itself enqueues another Action, you’ll end up in a deadlock.
Update
Action
_actionQueue
Similar to the coroutine, this does involve checking whether or not the queue is empty every frame. Using what you’ve learned above about task schedulers and coroutines, I’m confident that you could reduce this burden with little effort if this becomes an issue.
Finally, there is a hip concept running around many programming circles known as reactive programming. Game developers I talk to tend to either love this or hate it, and there is enough public discourse that I won’t spend this post trying to turn you for or against this paradigm.
Reactive programming tends to favor logic that can come in streams -- that is logic that you would typically register for an event or query something every frame for -- and where you’ll perform functional operations on the streams as they flow through your game. For the purpose of staying consistent with the rest of this post, I’ll use it with the current example with the note that I’m not giving reactive programming its chance to shine.
So, with all that said, first I import UniRx from the Unity Asset Store. Then I have to make sure that there’s a MainThreadDispatcher in my scene:
MainThreadDispatcher
Now I can write my logic in UniRx form:
using Firebase; using Firebase.Auth; using UniRx; using UnityEngine; public class FirebaseRx : MonoBehaviour { // Start is called before the first frame update void Start() { Debug.Log("Checking Dependencies"); FirebaseApp.CheckAndFixDependenciesAsync().ToObservable().Subscribe(status => { Debug.Log("Authenticating"); var auth = FirebaseAuth.DefaultInstance; auth.SignInAnonymouslyAsync().ToObservable().ObserveOnMainThread().Subscribe(user => { Debug.Log("Signed in!"); var successes = PlayerPrefs.GetInt("Successes", 0); PlayerPrefs.SetInt("Successes", ++successes); Debug.Log($"Successes: {successes}"); auth.SignOut(); Debug.Log("Signed Out"); }); }); } }
What’s interesting about UniRx is that I can compose behaviour to form complex interactions. A brief example of this is the call ObserveOnMainThread, which guarantees that the following Subscribe executes on the main thread.
ObserveOnMainThread
Subscribe
For an example like this one, I would not pull in the complexities of UniRx but it’s useful to put it on your radar. If you were instead trying to build game logic around realtime database updates or periodically invoking cloud functions based on streams of events in game, you could do worse than combining UniRx and Zenject to quickly build a robust system around asynchronous logic.
I hope that I’ve not only given you some tools to help understand Firebase’s asynchronous API, but have empowered you to deal with them in a way that best suits your own game and coding style. I would strongly encourage you to create a small project using each of the techniques I’ve outlined here to really get a feel for the shape of each solution, and encourage you to think about ways you might improve your game’s performance using threads elsewhere. I’ve personally gotten some great mileage out of background tasks when dealing with peer to peer communication in games as well as processing and annotating screenshots without halting gameplay. I’ve even found that sometimes things like enemy AI doesn’t actually need to finish processing every frame, and it can sometimes be perfectly fine to let it run for a bit in the background over the course of a few frames.
Firebase is returning to the Game Developers Conference this year in San Francisco to share how we're making Firebase even more powerful for game developers!
At the Google Mobile Developer Day on Monday, we announced:
In case you missed these announcements on stage, read on below for a quick recap. We'll also be at booth #P1501 starting tomorrow until the end of the week, and have a special session on Firebase for Games in the Cloud Developer Day track, so if you're at the GDC this year, please come say hello! We're excited to get your feedback, and learn more about how we can make these features and Firebase for Games even better in the future.
Here's a recap of the new Firebase updates for games developers:
Firebase Crashlytics is now available for Unity! Firebase Crashlytics helps you track, prioritize, and fix stability issues in real time. It synthesizes an avalanche of crashes into a manageable list of issues, provides contextual information, and highlights the severity and prevalence of crashes so you can pinpoint the root cause faster. You can also easily reproduce issues by reviewing breadcrumbs, a list of actions that the user performed before the error occurred.
Crashlytics was previously only available for Android and iOS, but you can now use that same powerful crash-reporting functionality in your Unity games!
With the same simplicity of all our Firebase for Unity SDKs, Crashlytics can be integrated directly via your Unity IDE with no extra steps required. Your team can also be alerted of issues using our Email, Slack, Jira and PagerDuty Integrations, or write your own triggers using Cloud Functions with Firebase Crashlytics triggers.
And last, but not least, you can export Crashlytics data into BigQuery for deeper-dives. For example, let's say you log a custom key when reporting a Crashlytics event like so:
Crashlytics.SetCustomKey("current_level", "3");
After you export your Crashlytics data to BigQuery, you will be able to see the distribution of crashes by level 3, or any other level or custom key you've used for your events! And you can use our Data Studio template to quickly analyze this data. This will make tracking and fixing issues in your Unity game development a whole lot easier.
Refer to our documentation to get started with Firebase Crashlytics for Unity.
For C++ developers out there, you can now use an open source SDK for your Firebase for Games integration! This means more control than ever when integrating with the Firebase toolset. You can now easily dig into the code to see or change what's happening within the SDK to better suit your game, or maintain your own branch of the client SDK and cherry pick specific changes you care about. And if there are other platforms you want to use that we haven't yet built support for, you have the option to extend the SDK.
Firebase Test Lab is a cloud-based app-testing infrastructure. With one operation, you can test your Android or iOS app across a wide variety of devices and device configurations, and see the results in the Firebase console. For native Android apps, what are called Robo tests can intelligently analyze the UI elements on-screen and crawl through them. For games, however, this isn't possible because all of your elements are typically in a GL/Vulkan/Metal View. Instead Robo will resort to Monkey Actions, where it will tap randomly.
It could take quite some time for a smoke test like this to complete though, which is why we're happy to announce new AI-assisted Monkey Actions to help test your games with Firebase Test Lab. This will significantly reduce the time it takes for a robot to make progress through your game's user interface and provide useful test results. Check out the before / after videos for Monkey Actions with and without AI-assistance to see the difference. Note the before video showing Monkey Actions without AI assistance takes about 35 seconds to start a game, versus 13 seconds with AI-assistance (the orange dots on the screen represent where the robot is tapping on the screen):
Monkey Actions without AI assistance starting a game.
AI-assisted Monkey Actions starting a game.
Firebase Authentication provides an end-to-end identity solution for your app, which allows you to authenticate and verify users with passwords, phone numbers and popular federated identity providers like Google, Facebook and Twitter.
For iOS games developers, we are pleased to announce that Firebase Authentication now also supports Game Center Authentication, so if an iOS user is already signed into Game Center, they can also sign-in to your app without having to go through an additional sign-in flow.
We'll be at booth #P1501 all throughout the conference starting from March 20th - March 22nd, and have a special presentation on the Cloud Developer Day track on Wednesday at 5:00PM! We hope to see you there.
And of course, you can always learn more about Firebase for Games at:
https://firebase.google.com/games/
With a DIY approach, you'd be faced with having to build user management, data storage, server side logic, and more. This will take a lot of your time, and importantly, it would take critical resources away from what you really want to do: build that amazing new mobile game!
Our Firebase SDKs for Unity and C++ provide you with the tools you need to add these features and more to your game with ease. Plus, to help you better understand how Firebase can help you build your next chart-topper, we've built a sample game in Unity: MechaHamster. Check it out on Google Play or download the sample project at Github to see how easy it is to integrate Firebase into your game.
Before you dive into the sample code for MechaHamster, here's a rundown of the Firebase products that can help your game be successful.
One of the best tools you have to maintain a high-performing game is your analytics. With Google Analytics for Firebase, you can see where your players might be struggling and make adjustments as needed. Analytics also integrates with Adwords and other major ad networks to maximize your campaign performance. If you monetize your game using AdMob, you can link your two accounts and see the lifetime value (LTV) of your players, from in-game purchases and AdMob, right from your Analytics console. And with Streamview, you can see how players are interacting with your game in realtime.
Before releasing updates to your game, you'll want to make sure it works correctly. However, manual testing can be time consuming when faced with a large variety of target devices. To help solve this, we recently launched Firebase Test Lab for Android Game Loop Test at Google I/O. If you add a demo mode to your game, Test Lab will automatically verify your game is working on a wide range of devices. You can read more in our deep dive blog post here.
Another thing you'll want to be sure to take care of before launch is easy sign-in, so your users can start playing as quickly as possible. Firebase Authentication can help by handling all sign-in and authentication, from simple email + password logins to support for common identity providers like Google, Facebook, Twitter, and Github. Just announced recently at I/O, Firebase also now supports phone number authentication. And Firebase Authentication shares state cross-device, so your users can pick up where they left off, no matter what platforms they're using.
As more players start using your game, you realize that there are few spots that are frustrating for your audience. You may even see churn rates start to rise, so you decide that you need to push some adjustments. With Firebase Remote Config, you can change values in the console and push them out to players. Some players having trouble navigating levels? You can adjust the difficulty and update remotely. Remote Config can even benefit your development cycle; team members can tweak and test parameters without having to make new builds.
Now that you have a robust player community, you're probably starting to see a bunch of great player-built levels. With Firebase Realtime Database, you can store player data and sync it in real-time, meaning that the level builder you've built can store and share data easily with other players. You don't need your own server and it's optimized for offline use. Plus, Realtime Database integrates with Firebase Auth for secure access to user specific data.
A few months go by and your game is thriving, with high engagement and an active community. You're ready to release your next wave of new content, but how can you efficiently get the word out to your users? Firebase Cloud Messaging lets you target messages to player segments, without any coding required. And Firebase Dynamic Links allow your users to share this new content — or an invitation to your game — with other players. Dynamic Links survive the app install process, so a new player can install your app and then dive right into the piece of content that was shared with him or her.
At Firebase, our mission is to help mobile developers build better apps and grow successful businesses. When it comes to games, that means taking care of the boring stuff, so you can focus on what matters — making a great game. Our mobile SDKs for C++ and Unity are available now at firebase.google.com/games and don't forget to check out our sample game project, MechaHamster, on GitHub.
Our goal with Firebase is to help developers build better apps and grow them into successful businesses. Six months ago at Google I/O, we took our well-loved backend-as-a-service (BaaS) and expanded it to 15 features to make it Google’s unified app development platform, available across iOS, Android, and the web.
We launched many new features at Google I/O, but our work didn’t stop there. Since then, we’ve learned a lot from you (750,000+ projects created on Firebase to date!) about how you’re using our platform and how we can improve it. Thanks to your feedback, today we’re launching a number of enhancements to Crash Reporting, Analytics, support for game developers and more. For more information on our announcements, tune in to the livestream video from Firebase Dev Summit in Berlin. They’re also listed here:
Often the hardest part about fixing an issue is reproducing it, so we’ve added rich context to each crash to make the process simple. Firebase Crash Reporting now shows Firebase Analytics event data in the logs for each crash. This gives you clarity into the state of your app leading up to an error. Things like which screens of your app were visited are automatically logged with no instrumentation code required. Crash logs will also display any custom events and parameters you explicitly log using Firebase Analytics. Firebase Crash Reporting works for both iOS and Android apps.
Glide, a popular live video messaging app, relies on Firebase Crash Reporting to ensure user quality and release agility. “No matter how much effort you put into testing, it will never be as thorough as millions of active users in different locations, experiencing a variety of network conditions and real life situations. Firebase allows us to rapidly gain trust in our new version during phased release, as well as accelerate the process of identifying core issues and providing quick solutions.” - Roi Ginat, Founder, Glide.
We want to help you deliver high-quality experiences, so testing your app before it goes into the wild is incredibly important. Firebase Test Lab allows you to easily test your app on many physical and virtual devices in the cloud, without writing a single line of test code. Beginning today, developers on the Spark service tier (which is free!) can run five tests per day on physical devices and ten tests per day on virtual devices—with no credit card setup required. We’ve also heard that you want more device options, so we’ve added 11 new popular Android device models to Test Lab, available today.
We know that your data is most actionable when you can see and process it as quickly as possible. Therefore, we’re announcing a number of features to help you maximize the potential of your analytics events:
We were happy to give you a sneak preview at the Firebase Dev Summit of a new feature we are now building, StreamView, which will offer a live, dynamic view of your analytics data as it streams in.
To further enhance your targeting options, we’ve improved the connection between Firebase Analytics and other Firebase features, such as Dynamic Links and Remote Config. For example, you can now use Dynamic Links on your Facebook business page, and we can identify Facebook as a source in Firebase Analytics reporting. Also, you can now target Remote Config changes by User Properties, in addition to Audiences.
Game developers are building great apps, and we want Firebase to work for you, too. We’ve built an entirely new plugin for Unity that supports Analytics, the Realtime Database, Authentication, Dynamic Links, Remote Config, Notifications and more. We've also expanded our C++ SDK with Realtime Database support.
FirebaseUI is a library that provides common UI elements when building apps, and it’s a quick way to integrate with Firebase. FirebaseUI 1.0 includes a drop-in UI flow for Firebase Authentication, with common identity providers such as Google, Facebook, and Twitter. FirebaseUI 1.0 also added features such as client-side joins and intersections for the Realtime Database, plus integrations with Glide and SDWebImage that make downloading and displaying images from Firebase Storage a cinch. Follow our progress or contribute to our Android, iOS, and Web components on Github.
We want to provide the best tool for developers, but it’s also important that we give resources and training to help you get more out of the platform. As such, we’ve created a new Udacity course: Firebase in a Weekend! It’s an instructor-led video course to help all developers get up and running with Firebase on iOS and Android, in two days.
Finally, to help wrap your head around all our announcements, we’ve created a new demo app. This is an easy way to see how Analytics, Crash Reporting, Test Lab, Notifications, and Remote Config work in a live environment, without having to write a line of code.
Helping developers build better apps and successful businesses is at the core of Firebase. We work hard on it every day. We love hearing your feedback and ideas for new features and improvements—and we hope you can see from the length of this post that we take them to heart! Follow us on Twitter, join our Slack channel, participate in our Google Group, and let us know what you think. We’re excited to see what you’ll build next!