如何解决如何在Unity中的哪里放置Firebase Check and Fix Dependencies代码?
我想在Unity游戏中使用Firebase,因此步骤之一是添加以下代码,但未指定应添加代码的位置。有帮助吗?
Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
var dependencyStatus = task.Result;
if (dependencyStatus == Firebase.DependencyStatus.Available) {
// Create and hold a reference to your FirebaseApp,// where app is a Firebase.FirebaseApp property of your application class.
app = Firebase.FirebaseApp.DefaultInstance;
// Set a flag here to indicate whether Firebase is ready to use by your app.
} else {
UnityEngine.Debug.LogError(System.String.Format(
"Could not resolve all Firebase dependencies: {0}",dependencyStatus));
// Firebase Unity SDK is not safe to use here.
}
});
(这是Firebase上的说明的链接) https://firebase.google.com/docs/unity/setup?authuser=0#confirm-google-play-version
解决方法
我能给出的最佳答案是在Unity中“先做其他事情”。
在普通应用程序中,您会遇到类似主api入口点(iOS中为application:didFinishLaunchingWithOptions
,Android中为Activity.onCreate
或典型C / C ++桌面中为void main(int,char**)
的东西。应用)。但是在Unity中,您没有任何“先执行此操作”逻辑。哪种情况取决于您,并且可能会发生变化,并且脚本大致并行执行(最好以随机的顺序执行,但从技术上讲可以顺序执行)。
以下是我使用过或考虑过使用的模式以及一些相关的利弊:
- [推荐给初学者和小型项目]在我的视频中,我通常建议使用“加载”或“设置”场景。在该场景中,我放置了一个
FirebaseInit
脚本,该脚本将初始化Firebase并在完成后引发一个事件。然后,我可以收集一堆初始化功能(例如下载资产捆绑包或进行一些初始设置处理),也可以立即进入我的主要场景。在大多数情况下,这会变为无操作状态(在Android Play服务上是最新的),因此,如果您小心一点,甚至可以在主菜单中将其推入:
using System;
using Firebase;
using Firebase.Extensions;
using UnityEngine;
using UnityEngine.Events;
public class FirebaseInit : MonoBehaviour
{
public UnityEvent OnInitialized = new UnityEvent();
public InitializationFailedEvent OnInitializationFailed = new InitializationFailedEvent();
void Start()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
{
if (task.Exception != null)
{
OnInitializationFailed.Invoke(task.Exception);
}
else
{
OnInitialized.Invoke();
}
});
}
[Serializable]
public class InitializationFailedEvent : UnityEvent<Exception>
{
}
}
-
我不是依赖注入的主要支持者(因为我通常不使用DI框架,但是我确实倾向于使用
[SerializedField]
作为伪DI系统)没有可供分享的好示例。您可以使用ZenJect创建Firebase单例并将其注入任何需要它们的对象。您遇到的最大问题是,您必须等待要初始化的依赖项,这是可能的,但我只是没有在示例项目中完成这些步骤。好处是您只需要表达“我依赖Firebase”,ZenJect将负责其余的工作(在这种情况下,只需避免使用DefaultInstance
函数即可。 -
在更复杂的项目中,我倾向于将Firebase包装在
Coroutine
中(或异步任务,但我更喜欢Unity中的协程)。因此,我将有一个Coroutine
,它将等待检查和修复依赖项完成,并在完成时返回Realtime Database实例(并在必要时使用智能逻辑跳过该等待)。同样,您必须避免在管理脚本之外使用DefaultInstance
,并且Firebase的每次使用都会成为协程,但是您可以确保始终等待构建。这是一个专注于实时数据库的示例(我正在剥离不必要的代码以使其适合SO答案),并且我重申,这对于一个小型项目来说是很多开销:
public class FirebaseBehaviour : MonoBehaviour
{
private IEnumerator _setupFirebase;
private DatabaseReference _databaseReference;
void Awake()
{
// everything depends on firebase being setup. Do this first.
_setupFirebase = SetupFirebase();
StartCoroutine(_setupFirebase);
}
private IEnumerator SetupFirebase()
{
// we need to fix dependencies on Android
if (Application.platform == RuntimePlatform.Android && !Application.isEditor)
{
Debug.Log("Checking dependencies on Android");
var checkDependencies = new TaskYieldInstruction<DependencyStatus>(FirebaseApp.CheckDependenciesAsync());
yield return checkDependencies;
Debug.Log($"Check Dependencies: {checkDependencies.Result}");
}
_databaseReference = FirebaseDatabase.DefaultInstance.RootReference;
}
/// <summary>
/// Safely gets a database reference at the given path
/// </summary>
/// <param name="path">The path at which to get a reference</param>
/// <returns>A yield instruction that can be yielded in a coroutine</returns>
public GetDatabaseReferenceYieldInstruction GetDatabaseReference(string path)
{
return new GetDatabaseReferenceYieldInstruction(path,_setupFirebase);
}
/// <summary>
/// Asynchronously gets a database reference at the given path after a predicate executes
/// </summary>
public class GetDatabaseReferenceYieldInstruction : IEnumerator
{
private IEnumerator _predicate;
private readonly string _path;
public DatabaseReference Root { get; private set; }
public GetDatabaseReferenceYieldInstruction(string path,IEnumerator predicate)
{
_path = path;
_predicate = predicate;
}
public bool MoveNext()
{
if (_predicate != null)
{
if (_predicate.MoveNext())
{
return true;
}
_predicate = null;
// TODO: this is a cross cutting concern to inject
Root = FirebaseDatabase.DefaultInstance.RootReference.Child(_path);
}
return false;
}
public void Reset()
{
}
public object Current => Root;
}
}
您可以这样使用:
[SerializeField] private FirebaseSingleton _firebaseSingleton;
public void Awake()
{
_firebase = _firebaseSingleton.Instance;
_getDatabase = _firebase.GetDatabaseReference(DatabaseName);
}
private IEnumerator RegisterForEvents()
{
yield return _getDatabase;
_getPigDatabase.Root.ValueChanged += HandlePigValuesChanged;
}
- 对于Unity's new DOTS system,我一直在想将Unity的初始化转移到系统的
OnCreate
函数中。因为您拥有一个干净的入口点,所以您可以阻止Firebase功能,直到它联机为止,并且您可以通过将特定的实体注入到具有自定义Firebase特定组件的世界来控制Firebase。尽管尚在我的项目积压中,但我还没有一个很好的例子。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。