Chuyển tới nội dung chính

Tích hợp scene

SDK root trong scene Login cung cấp mọi screen contract và presenter. Mỗi scene của game chỉ đăng ký các component UI của riêng nó trong một scope kế thừa từ một base class của SDK, và nhận những gì cần qua injection.

1. Tham chiếu assembly​

Code trong Assembly-CSharp thấy các kiểu của SDK mà không cần tham chiếu. .asmdef của game tham chiếu SilverTiger.ProjectV.Unity, cộng thêm VContainer khi có inject:

{
"name": "ProjectV.Game.Presentation",
"references": [
"SilverTiger.ProjectV.Unity",
"VContainer",
"UniTask"
]
}

Không tham chiếu các assembly SDK khác, SilverTiger.CrossSDK.* hay Nakama từ code game.

2. Một root trong scene Login​

Scene Login chứa SDK root duy nhất do Setup tạo. Nó vẫn tồn tại khi các scene khác được tải. Không bao giờ thêm root khác, và không bao giờ tự đăng ký screen contract hay presenter trong một scene scope.

3. Scope của scene Login​

Kế thừa scope Login từ ProjectVLoginSceneScope và đăng ký UI Login:

using SilverTiger.ProjectV.Unity.Presentation;
using VContainer;
using VContainer.Unity;

public sealed class LoginSceneScope : ProjectVLoginSceneScope
{
protected override void ConfigureLogin(IContainerBuilder builder)
{
builder.RegisterComponentInHierarchy<PopupLogin>();
}
}

4. Scope của các scene đã đăng nhập​

Lobby, Shop, Character, Alliance và Campaign kế thừa từ ProjectVAuthenticatedSceneScope. Khi chưa ai đăng nhập (ví dụ khi scene được mở thẳng trong Editor), base class đưa người chơi về Login.

using SilverTiger.ProjectV.Unity.Presentation;
using UnityEngine;
using UnityEngine.SceneManagement;
using VContainer;
using VContainer.Unity;

public sealed class LobbySceneScope : ProjectVAuthenticatedSceneScope
{
protected override void ConfigureAuthenticated(IContainerBuilder builder)
{
builder.RegisterComponentInHierarchy<LobbyUIManager>();
builder.RegisterComponentInHierarchy<HeaderUIManager>();
}

protected override void DisableScenePresentation()
{
var lobby = FindFirstObjectByType<LobbyUIManager>(FindObjectsInactive.Include);
if (lobby != null)
{
lobby.enabled = false;
}
}

protected override void NavigateToLogin(string sceneName)
{
SceneManager.LoadScene(sceneName);
}
}

DisableScenePresentation phải tắt mọi script UI của scene trước khi chuyển về Login, để không script nào gửi command (lệnh). Chỉ override LoginSceneName nếu scene Login không tên là Login.

5. Inject vào view​

Yêu cầu screen contract (hoặc presenter, với các màn không có contract) trong một method [Inject]:

using System;
using SilverTiger.ProjectV.Unity.Presentation.Lobby;
using UnityEngine;
using VContainer;

public sealed class LobbyUIManager : MonoBehaviour
{
private IProjectVLobbyScreen lobby = null!;

[Inject]
public void Construct(IProjectVLobbyScreen screen)
{
lobby = screen ?? throw new ArgumentNullException(nameof(screen));
}
}

Đừng tìm chúng bằng FindObjectOfType, tạo chúng bằng new hay giữ chúng trong field static.

6. Trình tự startup trên Login​

Subscribe to Authentication and Startup snapshots
-> StartAsync(contentReady)
Ready -> go to Lobby (session restored)
AwaitingLogin -> show login choices
Maintenance / UpdateRequired / ContractMismatch / Offline / Failed -> blocking UI
-> authenticate (Guest, password, Google or Apple)
-> StartAsync(contentReady) again
-> Ready -> go to Lobby

Chỉ truyền contentReady: true sau khi nội dung riêng của game (Addressables, localization) đã tải xong; trước đó startup chờ ở WaitingForContent. Không bao giờ cho người chơi đi qua một status chặn.

7. Scene nhiệm vụ​

Campaign gọi IProjectVCampaignScreen.BeginMissionAsync(missionId); khi thành công, game tải scene gameplay. Scene đó phải chứa đúng một component implement IProjectVGameplayDataConsumer (component trên object inactive cũng được tính). SDK gọi BindGameplayData(presenter, startingData) của nó với lượt chơi mà server đã bắt đầu, và UnbindGameplayData khi lượt chơi kết thúc. Nếu scene không tải được, gọi CancelSceneLoadAsync để giải phóng lượt chơi. Xem Gameplay data.

8. Vòng đời trang​

Gọi Observe (hoặc SubscribeAsync) khi một trang mở và dispose (giải phóng) đúng IDisposable đó khi trang đóng. Không bao giờ poll từ Update().

Tiếp tục với Tham chiếu presenter và Công thức presentation.