【Unity框架知识】流行的游戏框架

新星杯·14天创作挑战营·第17期 10w+人浏览 492人参与

最流行的Unity游戏框架

1. GameFramework(GF框架) ⭐⭐⭐⭐⭐

最流行的国产Unity框架,商业项目首选

// GameFramework架构
public class GameEntry : MonoBehaviour {
    // 核心组件
    public static BaseComponent Base { get; private set; }
    public static ConfigComponent Config { get; private set; }
    public static DataNodeComponent DataNode { get; private set; }
    public static DataTableComponent DataTable { get; private set; }
    public static DownloadComponent Download { get; private set; }
    public static EntityComponent Entity { get; private set; }
    public static EventComponent Event { get; private set; }
    public static FsmComponent Fsm { get; private set; }
    public static LocalizationComponent Localization { get; private set; }
    public static NetworkComponent Network { get; private set; }
    public static ObjectPoolComponent ObjectPool { get; private set; }
    public static ProcedureComponent Procedure { get; private set; }
    public static ResourceComponent Resource { get; private set; }
    public static SceneComponent Scene { get; private set; }
    public static SettingComponent Setting { get; private set; }
    public static SoundComponent Sound { get; private set; }
    public static UIComponent UI { get; private set; }
    public static WebRequestComponent WebRequest { get; private set; }
}

// 使用示例
public class GameLogic {
    void Start() {
        // 加载UI
        GameEntry.UI.OpenUIForm("UIMain", "Default", this);
        
        // 播放音效
        GameEntry.Sound.PlaySound(1001);
        
        // 加载实体
        GameEntry.Entity.ShowEntity<PlayerEntity>(1, "Assets/Player.prefab", "Player");
        
        // 触发事件
        GameEntry.Event.Fire(this, new LevelUpEventArgs { Level = 10 });
        
        // 下载资源
        GameEntry.Download.AddDownload("http://cdn.com/asset.ab", "asset.ab");
        
        // 网络请求
        GameEntry.Network.Connect("127.0.0.1", 8080);
    }
}

// 流程(Procedure)系统 - 游戏流程管理
public class ProcedureLaunch : ProcedureBase {
    protected override void OnEnter(IFsm<IProcedureManager> procedureOwner) {
        base.OnEnter(procedureOwner);
        Log.Info("进入启动流程");
        
        // 初始化框架
        InitFramework();
    }
    
    protected override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds) {
        base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
        
        if (IsFrameworkReady()) {
            // 切换到下一个流程
            ChangeState<ProcedureSplash>(procedureOwner);
        }
    }
    
    void InitFramework() {
        // 初始化逻辑
    }
    
    bool IsFrameworkReady() {
        return true;
    }
}

// 实体(Entity)系统
public class PlayerEntity : EntityLogic {
    private PlayerData m_PlayerData;
    
    protected override void OnInit(object userData) {
        base.OnInit(userData);
    }
    
    protected override void OnShow(object userData) {
        base.OnShow(userData);
        m_PlayerData = userData as PlayerData;
        
        // 设置位置
        transform.position = m_PlayerData.Position;
    }
    
    protected override void OnUpdate(float elapseSeconds, float realElapseSeconds) {
        base.OnUpdate(elapseSeconds, realElapseSeconds);
        
        // 更新逻辑
    }
    
    protected override void OnHide(bool isShutdown, object userData) {
        base.OnHide(isShutdown, userData);
    }
}

// 数据表(DataTable)
// Excel配置自动生成代码
public class DRWeapon : DataRowBase {
    private int m_Id;
    private string m_Name;
    private int m_Attack;
    private float m_AttackSpeed;
    
    public override int Id => m_Id;
    public string Name => m_Name;
    public int Attack => m_Attack;
    public float AttackSpeed => m_AttackSpeed;
    
    public override bool ParseDataRow(string dataRowString, object userData) {
        string[] columnStrings = dataRowString.Split('\t');
        m_Id = int.Parse(columnStrings[0]);
        m_Name = columnStrings[1];
        m_Attack = int.Parse(columnStrings[2]);
        m_AttackSpeed = float.Parse(columnStrings[3]);
        return true;
    }
}

// 使用数据表
void LoadWeaponData() {
    DRWeapon weapon = GameEntry.DataTable.GetDataTable<DRWeapon>().GetDataRow(1001);
    Debug.Log($"武器: {weapon.Name}, 攻击力: {weapon.Attack}");
}

特点:

  • 模块化设计,高度解耦
  • 完善的资源管理(热更新支持)
  • 内置对象池、事件系统
  • 完整的网络框架
  • 商业项目验证
  • 中文文档完善

GitHub: https://github.com/EllanJiang/GameFramework


2. ET Framework(Unity ET) ⭐⭐⭐⭐⭐

双端框架,客户端+服务器一体,适合网络游戏

// ET采用ECS架构
// Entity-Component-System

// 定义组件
[ComponentOf(typeof(Scene))]
public class PlayerComponent : Entity, IAwake, IDestroy {
    public string Name;
    public int Level;
    public Vector3 Position;
}

// 系统(System)
[EntitySystemOf(typeof(PlayerComponent))]
public static partial class PlayerComponentSystem {
    [EntitySystem]
    private static void Awake(this PlayerComponent self) {
        Log.Debug("玩家组件创建");
    }
    
    [EntitySystem]
    private static void Destroy(this PlayerComponent self) {
        Log.Debug("玩家组件销毁");
    }
    
    // 扩展方法
    public static void Move(this PlayerComponent self, Vector3 target) {
        self.Position = target;
    }
}

// 使用
public class GameMain {
    async ETTask Start() {
        // 创建场景
        Scene scene = await SceneFactory.CreateScene("Game");
        
        // 添加组件
        PlayerComponent player = scene.AddComponent<PlayerComponent>();
        player.Name = "玩家1";
        player.Level = 1;
        
        // 调用系统方法
        player.Move(new Vector3(10, 0, 10));
    }
}

// 网络消息(protobuf)
// C2G_Login.proto
message C2G_Login {
    string Account = 1;
    string Password = 2;
}

message G2C_Login {
    int32 Error = 1;
    int64 PlayerId = 2;
}

// 消息处理器
[MessageHandler(SceneType.Gate)]
public class C2G_LoginHandler : MessageHandler<Session, C2G_Login, G2C_Login> {
    protected override async ETTask Run(Session session, C2G_Login request, G2C_Login response) {
        // 验证登录
        if (request.Account == "admin" && request.Password == "123456") {
            response.PlayerId = 10001;
            response.Error = 0;
        } else {
            response.Error = 1;
        }
        
        await ETTask.CompletedTask;
    }
}

// 热更新层(HotfixView)
[EntitySystemOf(typeof(UILoginComponent))]
public static partial class UILoginComponentSystem {
    [EntitySystem]
    private static void Awake(this UILoginComponent self) {
        // 绑定UI事件
        self.LoginButton.onClick.AddListener(() => {
            self.OnLogin().Coroutine();
        });
    }
    
    private static async ETTask OnLogin(this UILoginComponent self) {
        C2G_Login request = new C2G_Login {
            Account = self.AccountInput.text,
            Password = self.PasswordInput.text
        };
        
        G2C_Login response = await self.Root().GetComponent<ClientSenderComponent>()
            .Call<G2C_Login>(request);
        
        if (response.Error == 0) {
            Log.Debug("登录成功");
        }
    }
}

特点:

  • 真正的ECS架构
  • 客户端+服务器双端
  • 支持热更新(HybridCLR)
  • protobuf网络通信
  • 异步async/await
  • 适合MMO/MOBA

GitHub: https://github.com/egametang/ET


3. QFramework ⭐⭐⭐⭐

轻量级框架,适合中小型项目

// QFramework核心:Architecture + MVC

// 1. 定义架构
public interface ICounterApp : IArchitecture {
    // 定义接口
}

public class CounterApp : Architecture<ICounterApp> {
    protected override void Init() {
        // 注册Model
        this.RegisterModel<ICounterModel>(new CounterModel());
        
        // 注册System
        this.RegisterSystem<IScoreSystem>(new ScoreSystem());
        
        // 注册Utility
        this.RegisterUtility<IStorage>(new PlayerPrefsStorage());
    }
}

// 2. Model(数据层)
public interface ICounterModel : IModel {
    BindableProperty<int> Count { get; }
    void AddCount();
}

public class CounterModel : AbstractModel, ICounterModel {
    public BindableProperty<int> Count { get; } = new BindableProperty<int>(0);
    
    public void AddCount() {
        Count.Value++;
    }
    
    protected override void OnInit() {
        // 从本地加载数据
        var storage = this.GetUtility<IStorage>();
        Count.Value = storage.LoadInt("Count", 0);
    }
}

// 3. System(业务逻辑层)
public interface IScoreSystem : ISystem {
    int CalculateScore(int count);
}

public class ScoreSystem : AbstractSystem, IScoreSystem {
    public int CalculateScore(int count) {
        return count * 10;
    }
    
    protected override void OnInit() {
        // 初始化
    }
}

// 4. Command(命令)
public class AddCountCommand : AbstractCommand {
    protected override void OnExecute() {
        var model = this.GetModel<ICounterModel>();
        model.AddCount();
        
        // 保存数据
        var storage = this.GetUtility<IStorage>();
        storage.SaveInt("Count", model.Count.Value);
    }
}

// 5. Controller(控制器)
public class GameController : MonoBehaviour, IController {
    public IArchitecture GetArchitecture() {
        return CounterApp.Interface;
    }
    
    private void Start() {
        // 获取Model
        var model = this.GetModel<ICounterModel>();
        
        // 监听数据变化
        model.Count.Register(OnCountChanged).UnRegisterWhenGameObjectDestroyed(gameObject);
    }
    
    private void OnCountChanged(int newCount) {
        Debug.Log($"Count changed: {newCount}");
    }
    
    public void OnButtonClick() {
        // 执行命令
        this.SendCommand<AddCountCommand>();
    }
}

// 6. UI自动绑定
public class UIGamePanel : UIPanel {
    // 使用代码生成器自动生成
    [SerializeField] private Button BtnAdd;
    [SerializeField] private Text TxtCount;
    
    protected override void OnInit() {
        BtnAdd.onClick.AddListener(() => {
            this.SendCommand<AddCountCommand>();
        });
        
        this.GetModel<ICounterModel>().Count.RegisterWithInitValue(count => {
            TxtCount.text = count.ToString();
        }).UnRegisterWhenGameObjectDestroyed(gameObject);
    }
}

// 7. 类型事件
public struct OnPlayerDead {
    public int PlayerId;
}

public class EventExample : MonoBehaviour, IController {
    public IArchitecture GetArchitecture() => CounterApp.Interface;
    
    void Start() {
        // 注册事件
        TypeEventSystem.Global.Register<OnPlayerDead>(OnPlayerDiedHandler)
            .UnRegisterWhenGameObjectDestroyed(gameObject);
    }
    
    void OnPlayerDiedHandler(OnPlayerDead e) {
        Debug.Log($"玩家{e.PlayerId}死亡");
    }
    
    void OnAttack() {
        // 发送事件
        TypeEventSystem.Global.Send(new OnPlayerDead { PlayerId = 1 });
    }
}

特点:

  • 简单易学
  • MVC架构清晰
  • 响应式编程(BindableProperty)
  • UI代码生成工具
  • 丰富的工具包
  • 适合快速开发

GitHub: https://github.com/liangxiegame/QFramework


4. xLua/ILRuntime(热更新方案) ⭐⭐⭐⭐⭐

xLua(Lua热更新)

// C# 调用Lua
public class XLuaExample : MonoBehaviour {
    private LuaEnv luaEnv;
    
    void Start() {
        luaEnv = new LuaEnv();
        
        // 执行Lua代码
        luaEnv.DoString(@"
            print('Hello from Lua')
            
            function add(a, b)
                return a + b
            end
        ");
        
        // 调用Lua函数
        var add = luaEnv.Global.Get<Func<int, int, int>>("add");
        int result = add(1, 2);
        Debug.Log($"Result: {result}");
    }
    
    void Update() {
        if (luaEnv != null) {
            luaEnv.Tick();  // 清理Lua的GC
        }
    }
    
    void OnDestroy() {
        luaEnv.Dispose();
    }
}

// Lua调用C#
[LuaCallCSharp]
public class Player {
    public string Name;
    public int Level;
    
    public void Attack() {
        Debug.Log($"{Name} 攻击!");
    }
}

// Lua代码
/*
local player = CS.Player()
player.Name = "玩家1"
player.Level = 10
player:Attack()
*/

// 热修复(HotFix)
[Hotfix]
public class BuggyClass {
    public int Calculate(int a, int b) {
        return a - b;  // BUG: 应该是加法
    }
}

// Lua热修复代码
/*
xlua.hotfix(CS.BuggyClass, 'Calculate', function(self, a, b)
    return a + b  -- 修复BUG
end)
*/

ILRuntime(C#热更新)

// ILRuntime示例
public class ILRuntimeExample : MonoBehaviour {
    private ILRuntime.Runtime.Enviorment.AppDomain appdomain;
    
    void Start() {
        appdomain = new ILRuntime.Runtime.Enviorment.AppDomain();
        
        // 加载热更新DLL
        byte[] dll = File.ReadAllBytes("Hotfix.dll");
        byte[] pdb = File.ReadAllBytes("Hotfix.pdb");
        
        using (MemoryStream fs = new MemoryStream(dll))
        using (MemoryStream p = new MemoryStream(pdb)) {
            appdomain.LoadAssembly(fs, p, new Mono.Cecil.Pdb.PdbReaderProvider());
        }
        
        // 调用热更新代码
        appdomain.Invoke("HotfixProject.GameMain", "Start", null, null);
    }
}

// 热更新DLL中的代码(HotfixProject)
namespace HotfixProject {
    public class GameMain {
        public static void Start() {
            Debug.Log("热更新代码运行中");
            
            // 使用主工程的类
            var player = new Player();
            player.Name = "热更新玩家";
        }
    }
    
    public class HotfixBattle {
        public void StartBattle() {
            // 热更新的战斗逻辑
        }
    }
}

5. UniRx(响应式编程) ⭐⭐⭐⭐
using UniRx;
using UniRx.Triggers;

public class UniRxExample : MonoBehaviour {
    void Start() {
        // 1. 响应式属性
        var health = new ReactiveProperty<int>(100);
        
        health.Subscribe(value => {
            Debug.Log($"生命值变化: {value}");
            if (value <= 0) {
                Debug.Log("玩家死亡");
            }
        });
        
        health.Value = 50;  // 触发订阅
        
        // 2. 事件流
        this.UpdateAsObservable()
            .Where(_ => Input.GetKeyDown(KeyCode.Space))
            .Subscribe(_ => {
                Debug.Log("按下空格");
            });
        
        // 3. 定时器
        Observable.Timer(TimeSpan.FromSeconds(3))
            .Subscribe(_ => {
                Debug.Log("3秒后执行");
            });
        
        // 4. 间隔执行
        Observable.Interval(TimeSpan.FromSeconds(1))
            .Subscribe(x => {
                Debug.Log($"第{x}秒");
            });
        
        // 5. 异步操作
        ObservableWWW.Get("http://api.com/data")
            .Subscribe(
                data => Debug.Log($"获取数据: {data}"),
                error => Debug.LogError($"错误: {error}")
            );
        
        // 6. 组合操作
        var click = this.UpdateAsObservable()
            .Where(_ => Input.GetMouseButtonDown(0));
        
        var position = this.UpdateAsObservable()
            .Select(_ => Input.mousePosition);
        
        click.Zip(position, (c, p) => p)
            .Subscribe(pos => {
                Debug.Log($"点击位置: {pos}");
            });
        
        // 7. MVVM绑定
        var viewModel = new PlayerViewModel();
        viewModel.Score
            .SubscribeToText(scoreText)  // 自动更新Text组件
            .AddTo(this);
        
        // 8. 防抖(Throttle)
        this.UpdateAsObservable()
            .Where(_ => Input.anyKeyDown)
            .ThrottleFirst(TimeSpan.FromSeconds(1))  // 1秒内只响应一次
            .Subscribe(_ => {
                Debug.Log("技能释放");
            });
    }
}

// MVVM示例
public class PlayerViewModel {
    public ReactiveProperty<int> Score { get; } = new ReactiveProperty<int>(0);
    public ReactiveProperty<string> Name { get; } = new ReactiveProperty<string>("");
    
    public ReactiveCommand AttackCommand { get; }
    
    public PlayerViewModel() {
        // 当Score > 0时才能攻击
        AttackCommand = Score.Select(s => s > 0).ToReactiveCommand();
        
        AttackCommand.Subscribe(_ => {
            Debug.Log("执行攻击");
            Score.Value -= 10;
        });
    }
}
6. Addressables(官方资源管理) ⭐⭐⭐⭐⭐
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class AddressablesExample : MonoBehaviour {
    async void Start() {
        // 1. 加载单个资源
        var handle = Addressables.LoadAssetAsync<GameObject>("Assets/Prefabs/Enemy.prefab");
        GameObject prefab = await handle.Task;
        Instantiate(prefab);
        
        // 2. 实例化(自动管理生命周期)
        var instance = await Addressables.InstantiateAsync("Enemy").Task;
        
        // 3. 加载场景
        await Addressables.LoadSceneAsync("GameScene").Task;
        
        // 4. 批量加载
        var handles = Addressables.LoadAssetsAsync<Sprite>(
            new List<string> { "Sprite1", "Sprite2", "Sprite3" },
            sprite => {
                Debug.Log($"加载: {sprite.name}");
            }
        );
        await handles.Task;
        
        // 5. 标签加载
        var enemies = await Addressables.LoadAssetsAsync<GameObject>(
            "Enemy",  // 标签
            null
        ).Task;
        
        // 6. 预加载
        var preloadHandle = Addressables.DownloadDependenciesAsync("MainAssets");
        while (!preloadHandle.IsDone) {
            float progress = preloadHandle.PercentComplete;
            Debug.Log($"预加载进度: {progress * 100}%");
            await Task.Yield();
        }
        
        // 7. 释放资源
        Addressables.Release(handle);
        
        // 8. 检查更新
        var checkHandle = Addressables.CheckForCatalogUpdates();
        var catalogs = await checkHandle.Task;
        
        if (catalogs.Count > 0) {
            var updateHandle = Addressables.UpdateCatalogs(catalogs);
            await updateHandle.Task;
            Debug.Log("资源目录已更新");
        }
    }
}

推荐组合方案

🎮 方案1:中小型单机游戏
  • QFramework (架构)
    – Addressables (资源)
    – UniRx (响应式)
    – DOTween (动画)
🌐 方案2:网络游戏
  • ET Framework (双端框架)
    – HybridCLR (热更新)
    – Addressables (资源)
🏢 方案3:商业大型项目
  • GameFramework (架构)
    – xLua/HybridCLR (热更新)
    – Addressables (资源)
    – UniTask (异步)

✨随便写写

人总是相信他们选择相信的,记忆是主观的。从这个角度来说,当我们坚持自己版本的往事时,我们在某种程度上也在对别人施加煤气灯效应。可是我们总得相信自己的记忆,否则我们就会分崩离析,荡然无存。

by 张翎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值