YuriFrameWork

目的

  • 彼此好維護:確保一致性、易讀性
  • 執行效能更好:了解執行成本
  • 更安全:避免掉不安全的作法
  • 減少專案交接時,由於程式碼風格水土不服所帶來的風險。
  • 可以減少加人時所帶來的人力浪費(可以讓一個人花更少的時間去看懂某個專案的程式碼)。
  • 防止專案過了一段時間一些實現自己都看不懂了。

規範說明

  • 邏輯基於MVC
    Model用於共通資料的存儲,且提供取用的Method。
    View為Unity的視圖,無腳本。
    System負責複雜的資料處理邏輯,處理完邏輯將資料存入Model供Controller取用。
    Controller用於View邏輯處理,通常會需要[SerializeField]等,所以會繼承MonoBehaviour掛在場景物件上,調用System處理資料,並從Model取用。
    腳本命名
    Controller為有控制用途的Contorller,其他屬於MVC Controller的腳本不加Controller
    Manager為有總管理責任的Contorller,通常只會有一個,掛在場景物件上。

  • 需依賴DI框架,目前選用Reflax(速度較快、效能較好)

  • 需要給其他腳本調用的腳本需宣告介面並宣告Public的Value或Method,透過DI綁定以上介面實作,在需調用的腳本利用DI注入
    這樣若需要替換實作只要更換綁定的實作就可以了,不用動到其他參考。

  • 遵守CodeStyle : C# code style in Unity

  • 工具們 : Unity Tools

  • Unity問題整合 : Unity 避坑指南

  • Disign Pattens筆記: Game Programming Patterns

開始使用

  1. Unity安裝Reflax
    https://github.com/gustavopsantos/Reflex?tab=readme-ov-file#-installation
  2. 在專案內Assets/Resources添加Prefab Reflex/ProjectScope
    此物件用於執行全域的綁定
  3. 場景上新增物件並掛上腳本 SceneScope.cs
    一定要掛否則ProjectScope.cs不會啟動
  4. 撰寫Installer.cs
    全域綁定物件腳本掛到 ProjectScope.cs 同物件下
    場景綁定物件腳本掛到 SceneScope.cs 同物件下
    Sample綁定
using Reflex.Core;
using UnityEngine;

public class MainSceneInstaller : MonoBehaviour, IInstaller
{
    [Header("Manager")]
    [SerializeField] private DialogManager dialogManager;
    
    public void InstallBindings(ContainerBuilder builder)
    {
        //Model
        builder.AddSingleton(new PlayerModel(), typeof(PlayerModel));
        builder.AddSingleton(new DialogModel(), typeof(DialogModel));

        //System
        builder.AddSingleton(new DialogSystem(builder.Build()), typeof(IDialogSystem));

        //Manager
        builder.AddSingleton(dialogManager, typeof(IDialogManager));
    }
}

其他腳本注入

[Inject] private IPlayerModel playerModel;

[Inject]發生在遊戲周期的Awake之前,且為MonoBehaviour掛在場上的物件上,以下特殊狀況

  • 物件如果是Awake後才生成的需要手動注入
[Inject] private ViewManager viewManager;
private void Awake()
{
    GameObjectInjector.InjectObject(gameObject, MainSceneInstaller.instance.container);
}
  • 物件不是MonoBehaviour,在建構函數注入範例
public DialogSystem(Container container)
{
    dialogModel = container.Single<DialogModel>();
}