iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 12
0
自我挑戰組

用Unity製作連線遊戲系列 第 12

Circling Around

  • 分享至 

  • xImage
  •  

Try Firebase

明明才確定登入會用PlayFab,但昨晚思考了就算Firebase Desktop是Beta,不適合用在Producation上,但這次的遊戲製作也不過就是Demo等級的,若是能夠用Firebase,整個連接會變得容易一些!?不確定,所以今天花了一些來試試看是否Desktop Firebase可用。如果可行,就不用牽扯一大堆沒用過,還要踩雷才能前進的開發方式。

Caution: Firebase Unity SDK desktop support is a beta feature. This feature is intended only for workflows during the development of your game, not for publicly shipping code.

官方在GitHub上的quickstart-unity是相當好的一個範例展示。登入重要的API文件先列在這裡

Standalone的版本也是Follow Android的前期設定。以前,下載的google-services.json放在專案裡任何地方都可以,現在一定要放在StreamingAssets下,要不然就會有錯誤跑出來。另外,這段Code一定要加,不加進來會有InitializationException in 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.
    }
});

將原先的PlayFab登入抽走,直接用Firebase Auth取代。

_auth.SignInWithEmailAndPasswordAsync(userEmail, userPassword)
    .ToObservable()
    .ObserveOnMainThread()
    .SubscribeOnMainThread()
    .Subscribe(x =>
    {
        _logger.Debug($"user: {x.DisplayName} {x.Email}");
    })
    .AddTo(_compositeDisposable);

在Unity Editor裡順利的執行了,是時候來試試看Windows build是否也ok。建置成Windows Build後直接執行。

Firebase in Windows

除了感動之後,也像是吃了一劑定心丸,可以在Windows上登入,其餘的可不可行到還好,因為Firestore的資料本來就打算是從GraphQL的service那拿取,反正收費上也是一樣的,而Cloud Function,本來就沒有打算要用在Client端,可以或不可以用在Windows上都沒有太大的問題。至於Remote Config,反正Unity自家也有一套,使用上差不多。也就是說一但確認了Auth可用,很多事件就變得順暢且一致了。

Auth可行後先來修正一下每次Compile都會彈出的錯誤

Unable to resolve reference 'UnityEditor.iOS.Extensions.Xcode'. Is the assembly missing or incompatible with the current platform?

這篇討論即時又快速,沒有其它方法,只能在不能build ios的windows上於Unity Editor裡放入ios module。

剛好看到2020.1.5f1出來了,就直接安裝,反正2020.1.4f1和2020.2.0b2都有個很討厭的[bug](2020.2.0b2: Cannot open any projects (Failed to load window layout)),新的專案一開就會被卡在layout有問題開不啓來的issue,除了離開外,不論是按Reset Factory或是Load Default都沒有用。可以用Unity官方建議的

Alternatively you can try deleting ~/Library/Preferences/Unity/Editor-5.x/Layouts/LastLayout.dwlt (macOS) or %APPDATA%\Unity\Editor-5.x\Layouts\LastLayout.dwlt (Windows).

試過之後20201.5f1果然修掉了這個問題,但另一個有一段時間沒有出現的錯誤(重新開啓Unity Editor即可)

TLS Allocator ALLOC_TEMP_THREAD, underlying allocator ALLOC_TEMP_THREAD has unfreed allocations, size 21

又跑出來了。

No Match Yet

明明配對不是這次開發最重要的環節,但它複雜度仍是在那,為了要用Golang架設配對server,花了一些時間在找相關的資料,研究Golang之餘現下先暫時擱置這一段。

前些天記錄的另一個問題就是當Client端是全套的Game Flow,但Server端確只有一部份(遊戲主關卡)時,到底要怎麼在Unity的開發下進行。從使用Mirror的製程來看,Gameplay Scene,肯定雙端都有一份。但Gameplay Scene以外的Scene,Server是完全沒有?擺入Dummy?還是完整的也塞一份?

先從只有Gameplay Scene來說,這應該是最正確的架構(在我的想像中)。在這樣的架構裡活在Gameplay Scene裡的Player和所有其它物件,可否有任何其它Scene留下來的元件或是型別引用?回看現在的架構

  • Entry Scene
  • Gameplay scene

Entry Scene是遊戲開始時的進入點,它是所謂的Main Scene,一直持續到遊戲結束。而Gameplay scene則是進入遊戲關卡時才讀取的sub scene,遊戲關卡開始時載入(Addressable或是Asset Bundle),結束時移除。

如果在Gameplay scene產生的任何物件,有著自Entry Scene給予的型別引用或元件等,但Entry Scene只有Client端才有,那這個物件就必需區分是在Server上或是在Client上,來決定是否用或是怎麼用這些Client才有的型別引用。

回到Gameplay scene,在Server端一開始時就先利用Sub scene載入一個場景,並於Player連接時將代表Player的game object移到這個sub scene,利用Client和Server端分別在Unity Editor來看

public override void OnStartServer()
{
    base.OnStartServer();
    SceneManager.LoadScene("Level", LoadSceneMode.Additive);
    _levelSceneLoaded = true;
}

public override void OnServerConnect(NetworkConnection conn)
{
    base.OnServerConnect(conn);
    // Player game object is not created yet
}

public override void OnServerReady(NetworkConnection conn)
{
    base.OnServerReady(conn);
    // Player game object is not created yet
}

public override void OnServerAddPlayer(NetworkConnection conn)
{
    base.OnServerAddPlayer(conn);
    if (_levelSceneLoaded)
    {
        _levelScene = SceneManager.GetSceneByName("Level");
        SceneManager.MoveGameObjectToScene(conn.identity.gameObject, _levelScene);
    }
}

得到的結果就是只有Server端載入到sub scene並將player放到sub scene裡,而Client端,沒有載入到Sub scene,player game object自然地也就是留在原場景。也了解到OnServerConnectOnServerReady時,雖然Connnection建立了,但Player物件還沒有產生。


上一篇
GraphQL Codegen
下一篇
Making The Flow
系列文
用Unity製作連線遊戲30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言