【Unity框架知识】培训机构中的游戏框架

Unity游戏框架深度解析

ModelEngine·创作计划征文活动 10w+人浏览 1.5k人参与

培训机构的游戏框架

1. 悠游课堂(Siki学院)系列框架

A. RealFramework(真正的隐藏宝藏) ⭐ <300 Stars

// Siki学院的实战框架(很少人知道)
// 基于MVC + 消息中心

// 1. 消息中心(核心通信)
public class MessageCenter : Singleton<MessageCenter> {
    private Dictionary<string, Delegate> messageDict = new Dictionary<string, Delegate>();
    
    // 无参消息
    public void AddListener(string msgName, Action callback) {
        if (!messageDict.ContainsKey(msgName)) {
            messageDict[msgName] = null;
        }
        messageDict[msgName] = (Action)messageDict[msgName] + callback;
    }
    
    // 带参消息
    public void AddListener<T>(string msgName, Action<T> callback) {
        if (!messageDict.ContainsKey(msgName)) {
            messageDict[msgName] = null;
        }
        messageDict[msgName] = (Action<T>)messageDict[msgName] + callback;
    }
    
    // 广播消息
    public void Broadcast(string msgName) {
        if (messageDict.TryGetValue(msgName, out Delegate d)) {
            (d as Action)?.Invoke();
        }
    }
    
    public void Broadcast<T>(string msgName, T arg) {
        if (messageDict.TryGetValue(msgName, out Delegate d)) {
            (d as Action<T>)?.Invoke(arg);
        }
    }
    
    // 移除监听
    public void RemoveListener(string msgName, Action callback) {
        if (messageDict.ContainsKey(msgName)) {
            messageDict[msgName] = (Action)messageDict[msgName] - callback;
        }
    }
}

// 2. MVC架构实现
// Model
public class PlayerModel : Singleton<PlayerModel> {
    private int level;
    private int exp;
    
    public int Level {
        get { return level; }
        set {
            level = value;
            // 通知View更新
            MessageCenter.Instance.Broadcast("OnLevelChanged", level);
        }
    }
    
    public void AddExp(int amount) {
        exp += amount;
        if (exp >= GetExpNeeded()) {
            Level++;
            exp = 0;
        }
        MessageCenter.Instance.Broadcast("OnExpChanged", exp);
    }
    
    int GetExpNeeded() => level * 100;
}

// View
public class PlayerView : MonoBehaviour {
    public Text levelText;
    public Slider expSlider;
    
    void Start() {
        // 注册监听
        MessageCenter.Instance.AddListener<int>("OnLevelChanged", OnLevelChanged);
        MessageCenter.Instance.AddListener<int>("OnExpChanged", OnExpChanged);
    }
    
    void OnDestroy() {
        MessageCenter.Instance.RemoveListener<int>("OnLevelChanged", OnLevelChanged);
        MessageCenter.Instance.RemoveListener<int>("OnExpChanged", OnExpChanged);
    }
    
    void OnLevelChanged(int level) {
        levelText.text = $"Level {level}";
    }
    
    void OnExpChanged(int exp) {
        expSlider.value = (float)exp / (PlayerModel.Instance.Level * 100);
    }
}

// Controller
public class PlayerController {
    public void KillEnemy() {
        PlayerModel.Instance.AddExp(50);
    }
}

// 3. UI管理系统
public class UIManager : MonoSingleton<UIManager> {
    private Dictionary<string, GameObject> uiDict = new Dictionary<string, GameObject>();
    private Stack<GameObject> uiStack = new Stack<GameObject>();
    
    public GameObject ShowUI(string uiName) {
        GameObject ui;
        
        if (uiDict.ContainsKey(uiName)) {
            ui = uiDict[uiName];
        } else {
            ui = Resources.Load<GameObject>($"UI/{uiName}");
            ui = Instantiate(ui, transform);
            uiDict[uiName] = ui;
        }
        
        // 隐藏栈顶UI
        if (uiStack.Count > 0) {
            uiStack.Peek().SetActive(false);
        }
        
        uiStack.Push(ui);
        ui.SetActive(true);
        
        return ui;
    }
    
    public void HideUI() {
        if (uiStack.Count > 0) {
            GameObject ui = uiStack.Pop();
            ui.SetActive(false);
            
            // 显示上一个UI
            if (uiStack.Count > 0) {
                uiStack.Peek().SetActive(true);
            }
        }
    }
}

// 4. 音频管理
public class AudioManager : MonoSingleton<AudioManager> {
    private AudioSource bgmSource;
    private AudioSource sfxSource;
    private Dictionary<string, AudioClip> audioDict = new Dictionary<string, AudioClip>();
    
    protected override void Awake() {
        base.Awake();
        
        bgmSource = gameObject.AddComponent<AudioSource>();
        bgmSource.loop = true;
        
        sfxSource = gameObject.AddComponent<AudioSource>();
    }
    
    public void PlayBGM(string bgmName) {
        AudioClip clip = LoadAudio(bgmName);
        if (clip != null) {
            bgmSource.clip = clip;
            bgmSource.Play();
        }
    }
    
    public void PlaySFX(string sfxName) {
        AudioClip clip = LoadAudio(sfxName);
        if (clip != null) {
            sfxSource.PlayOneShot(clip);
        }
    }
    
    AudioClip LoadAudio(string name) {
        if (!audioDict.ContainsKey(name)) {
            audioDict[name] = Resources.Load<AudioClip>($"Audio/{name}");
        }
        return audioDict[name];
    }
}

// ⭐ 悠游课堂特色:
// - 教学向,代码清晰
// - 适合学习和改造
// - 实战案例丰富
// - 没有过度设计

获取方式: Siki学院付费课程、或早期GitHub仓库


B. MFramework(悠游改进版)

// 基于观察者模式的改进框架
public class MFramework {
    // 事件管理器(改进版)
    public class EventManager : Singleton<EventManager> {
        private Dictionary<Type, Delegate> eventDict = new Dictionary<Type, Delegate>();
        
        public void AddListener<T>(Action<T> listener) where T : struct {
            Type eventType = typeof(T);
            
            if (!eventDict.ContainsKey(eventType)) {
                eventDict[eventType] = null;
            }
            
            eventDict[eventType] = Delegate.Combine(eventDict[eventType], listener);
        }
        
        public void Trigger<T>(T eventData) where T : struct {
            Type eventType = typeof(T);
            
            if (eventDict.TryGetValue(eventType, out Delegate d)) {
                (d as Action<T>)?.Invoke(eventData);
            }
        }
        
        public void RemoveListener<T>(Action<T> listener) where T : struct {
            Type eventType = typeof(T);
            
            if (eventDict.ContainsKey(eventType)) {
                eventDict[eventType] = Delegate.Remove(eventDict[eventType], listener);
            }
        }
    }
    
    // 使用
    public struct PlayerDeadEvent {
        public int PlayerId;
        public Vector3 Position;
    }
    
    void Example() {
        EventManager.Instance.AddListener<PlayerDeadEvent>(OnPlayerDead);
        EventManager.Instance.Trigger(new PlayerDeadEvent { PlayerId = 1 });
    }
    
    void OnPlayerDead(PlayerDeadEvent e) {
        Debug.Log($"玩家{e.PlayerId}死亡");
    }
}

2. 培训机构/个人大神的隐藏框架

A. 麦扣框架(小众但实用) ⭐ 内部流传

// 麦扣老师的框架(QQ群内流传)
namespace MKFramework {
    // 单例模板(自动创建GameObject)
    public class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour {
        private static T instance;
        
        public static T Instance {
            get {
                if (instance == null) {
                    GameObject go = new GameObject(typeof(T).Name);
                    instance = go.AddComponent<T>();
                    DontDestroyOnLoad(go);
                }
                return instance;
            }
        }
    }
    
    // 对象池系统
    public class PoolManager : MonoSingleton<PoolManager> {
        private Dictionary<string, Queue<GameObject>> poolDict = new Dictionary<string, Queue<GameObject>>();
        
        public GameObject GetObject(string poolName, GameObject prefab) {
            GameObject obj;
            
            if (poolDict.ContainsKey(poolName) && poolDict[poolName].Count > 0) {
                obj = poolDict[poolName].Dequeue();
            } else {
                obj = Instantiate(prefab);
                obj.name = poolName;
            }
            
            obj.SetActive(true);
            return obj;
        }
        
        public void PushObject(string poolName, GameObject obj) {
            if (!poolDict.ContainsKey(poolName)) {
                poolDict[poolName] = new Queue<GameObject>();
            }
            
            poolDict[poolName].Enqueue(obj);
            obj.SetActive(false);
            obj.transform.SetParent(transform);
        }
    }
    
    // 延迟任务系统
    public class DelayTask : MonoSingleton<DelayTask> {
        public void Delay(float time, Action callback) {
            StartCoroutine(DelayCoroutine(time, callback));
        }
        
        IEnumerator DelayCoroutine(float time, Action callback) {
            yield return new WaitForSeconds(time);
            callback?.Invoke();
        }
        
        public void FrameDelay(int frameCount, Action callback) {
            StartCoroutine(FrameDelayCoroutine(frameCount, callback));
        }
        
        IEnumerator FrameDelayCoroutine(int frameCount, Action callback) {
            for (int i = 0; i < frameCount; i++) {
                yield return null;
            }
            callback?.Invoke();
        }
    }
}

B. 独立游戏作者的框架

  1. TinyFramework ⭐ 个人作品
// 极简但完整的框架
namespace TinyFramework {
    // 场景状态机
    public class SceneStateMachine : MonoSingleton<SceneStateMachine> {
        private Dictionary<string, ISceneState> states = new Dictionary<string, ISceneState>();
        private ISceneState currentState;
        
        public void RegisterState(string name, ISceneState state) {
            if (!states.ContainsKey(name)) {
                states[name] = state;
            }
        }
        
        public void ChangeState(string stateName) {
            if (states.TryGetValue(stateName, out ISceneState newState)) {
                currentState?.OnExit();
                currentState = newState;
                currentState.OnEnter();
            }
        }
        
        void Update() {
            currentState?.OnUpdate();
        }
    }
    
    public interface ISceneState {
        void OnEnter();
        void OnUpdate();
        void OnExit();
    }
    
    // 实现
    public class MenuState : ISceneState {
        public void OnEnter() {
            Debug.Log("进入菜单");
        }
        
        public void OnUpdate() {
            if (Input.GetKeyDown(KeyCode.Space)) {
                SceneStateMachine.Instance.ChangeState("Game");
            }
        }
        
        public void OnExit() {
            Debug.Log("离开菜单");
        }
    }
}
3. 国外小众顶级框架

A. StrangeIoC ⭐ 1.5K Stars(被低估)

// 国外IoC框架,很少人用但很强大
using strange.extensions.context.impl;
using strange.extensions.command.impl;
using strange.extensions.mediation.impl;

// Context(类似Application)
public class GameContext : MVCSContext {
    public GameContext() : base(ContextView.Instance) { }
    
    protected override void mapBindings() {
        // 绑定Command
        commandBinder.Bind(GameEvent.START_GAME)
            .To<StartGameCommand>();
        
        // 绑定Model
        injectionBinder.Bind<IPlayerModel>()
            .To<PlayerModel>()
            .ToSingleton();
        
        // 绑定Service
        injectionBinder.Bind<INetworkService>()
            .To<NetworkService>()
            .ToSingleton();
        
        // 绑定Mediator(View的控制器)
        mediationBinder.Bind<PlayerView>()
            .To<PlayerMediator>();
    }
}

// Mediator(View层的Presenter)
public class PlayerMediator : Mediator {
    [Inject]
    public PlayerView view { get; set; }
    
    [Inject]
    public IPlayerModel model { get; set; }
    
    public override void OnRegister() {
        // 监听View事件
        view.AttackButtonClicked += OnAttackClicked;
        
        // 监听Model变化
        model.HealthChanged += OnHealthChanged;
    }
    
    void OnAttackClicked() {
        // 触发Command
        dispatcher.Dispatch(GameEvent.PLAYER_ATTACK);
    }
    
    void OnHealthChanged(int health) {
        view.UpdateHealth(health);
    }
}

// Command(业务逻辑)
public class StartGameCommand : Command {
    [Inject]
    public IPlayerModel playerModel { get; set; }
    
    [Inject]
    public IGameService gameService { get; set; }
    
    public override void Execute() {
        playerModel.Reset();
        gameService.StartGame();
    }
}

// 🌟 特点:
// - 完整的MVCS架构
// - IoC容器强大
// - 信号系统(Signal)
// - 适合大型项目
// - 学习曲线陡峭(所以小众)

GitHub: https://github.com/strangeioc/strangeioc


B. Fungus ⭐ 1.6K Stars(可视化剧情)

// 隐藏的可视化叙事框架
using Fungus;

public class FungusExample : MonoBehaviour {
    public Flowchart flowchart;
    
    void Start() {
        // 执行特定Block
        flowchart.ExecuteBlock("StartGame");
        
        // 设置变量
        flowchart.SetIntegerVariable("PlayerLevel", 10);
        
        // 获取变量
        int health = flowchart.GetIntegerVariable("Health");
    }
    
    // 从C#触发剧情
    public void TriggerEvent() {
        flowchart.SendFungusMessage("OnBossDead");
    }
}

// 可视化编辑器(类似UE蓝图)
// - 对话系统
// - 分支剧情
// - 角色动画
// - 音效控制
// 全都可视化编辑

// 🎨 用途:
// - AVG游戏
// - RPG对话
// - 教学游戏
// - 互动故事

GitHub: https://github.com/snozbot/fungus


4. 来自实际项目的隐藏框架

A. UniFramework ⭐ 600+ Stars(新秀)

// 模块化框架,正在崛起
using UniFramework.Machine;
using UniFramework.Event;
using UniFramework.Singleton;

// 状态机系统
public enum GameState {
    Boot,
    Login,
    Main,
    Battle
}

public class GameStateMachine {
    private StateMachine<GameState> fsm;
    
    public void Initialize() {
        fsm = new StateMachine<GameState>(this);
        
        fsm.AddNode<BootState>(GameState.Boot);
        fsm.AddNode<LoginState>(GameState.Login);
        fsm.AddNode<MainState>(GameState.Main);
        fsm.AddNode<BattleState>(GameState.Battle);
        
        fsm.Run(GameState.Boot);
    }
    
    public void ChangeState(GameState state) {
        fsm.ChangeState(state);
    }
}

public class BootState : IStateNode<GameState> {
    public void OnCreate(StateMachine<GameState> machine) {
        Debug.Log("创建Boot状态");
    }
    
    public void OnEnter() {
        Debug.Log("进入Boot状态");
        // 加载资源、初始化系统
    }
    
    public void OnUpdate() { }
    
    public void OnExit() {
        Debug.Log("离开Boot状态");
    }
}

// 事件系统
public class EventExample {
    void Start() {
        // 订阅事件
        UniEvent.AddListener<PlayerDeadEvent>(OnPlayerDead);
    }
    
    void OnPlayerDead(PlayerDeadEvent e) {
        Debug.Log($"玩家死亡: {e.PlayerId}");
    }
    
    void TriggerEvent() {
        UniEvent.SendMessage(new PlayerDeadEvent { PlayerId = 1 });
    }
}

// 🚀 特点:
// - 轻量级
// - 模块化
// - 易扩展
// - 文档完善

GitHub: https://github.com/gmhevinci/UniFramework


B. BDFramework ⭐ 600+ Stars

// 从实际项目提取的框架
using BDFramework.Core;
using BDFramework.UI;
using BDFramework.ResourceMgr;

public class GameStart : MonoBehaviour {
    void Start() {
        // 初始化框架
        BDLauncher.Init();
        
        // 加载UI
        UIManager.Inst.LoadWindow<MainWindow>();
        
        // 加载资源
        var sprite = BResources.Load<Sprite>("icon_001");
    }
}

// UI基类
public class MainWindow : AWindow {
    [TransformPath("Button_Start")]
    private Button startButton;
    
    public override void Init() {
        base.Init();
        
        // 自动绑定
        startButton.onClick.AddListener(OnStartClick);
    }
    
    void OnStartClick() {
        // 打开其他UI
        UIManager.Inst.LoadWindow<BattleWindow>();
    }
}

// 🎮 特点:
// - ILRuntime热更新
// - Excel导表工具
// - AssetBundle管理
// - 完整工作流

GitHub: https://github.com/yimengfan/BDFramework.Core


5. 顶级隐藏的企业内部框架(部分开源/泄露)

A. NKGMobaBasedOnET ⭐ MOBA框架

// 基于ET的MOBA游戏框架
// 网咖级MOBA的完整实现

// 技能系统
[ObjectSystem]
public class SkillAwakeSystem : AwakeSystem<SkillComponent> {
    public override void Awake(SkillComponent self) {
        self.Skills = new Dictionary<int, Skill>();
    }
}

public static class SkillComponentSystem {
    public static void LearnSkill(this SkillComponent self, int skillId) {
        var config = SkillConfigCategory.Instance.Get(skillId);
        var skill = self.AddChild<Skill>();
        skill.SkillId = skillId;
        skill.Level = 1;
        
        self.Skills[skillId] = skill;
    }
    
    public static async ETTask CastSkill(this SkillComponent self, int skillId, Vector3 targetPos) {
        if (!self.Skills.TryGetValue(skillId, out Skill skill)) {
            return;
        }
        
        if (!skill.CanCast()) {
            return;
        }
        
        // 播放施法动画
        await skill.PlayCastAnimation();
        
        // 执行技能效果
        skill.Execute(targetPos);
        
        // 进入冷却
        skill.StartCooldown();
    }
}

// Buff系统
public class BuffComponent : Entity {
    public Dictionary<int, Buff> Buffs;
    
    public void AddBuff(int buffId, long casterId) {
        var config = BuffConfigCategory.Instance.Get(buffId);
        var buff = AddChild<Buff>();
        buff.BuffId = buffId;
        buff.CasterId = casterId;
        buff.StartTime = TimeHelper.Now();
        
        Buffs[buffId] = buff;
    }
}

// 🎮 包含:
// - 完整MOBA系统
// - 技能、Buff、物品
// - 战斗逻辑
// - 帧同步

GitHub: https://github.com/wqaetly/NKGMobaBasedOnET


💎 真正的秘密

大厂的真相:

  1. 大部分大厂不用开源框架
  2. 都是基于小众框架改造
  3. 借鉴思想而不是直接用
  4. 教学框架往往更适合学习底层

最佳学习路径:

  1. 学习小众框架(理解架构思想)
  2. 研究大厂开源片段(学习工程化)
  3. 看视频教程(了解实战经验)
  4. 魔改成自己的(形成自己的框架)

🎯 我的建议

如果你想深入学习:

  1. 先看Siki的框架教程(基础扎实)
  2. 研究Loxodon/CatLib(学习设计模式)
  3. 阅读ET Framework源码(理解网络游戏)
  4. 最后自己实现一套(融会贯通)

如果你想快速开发:

  1. QFramework(快速上手)
  2. UniFramework(现代化)
  3. HybridCLR(热更新必备)

✨随便写写

乡音是刻在骨子里的地图,标记着来处与归途。方言藏着故乡与童年,在异乡偶然听见一句乡音也会倍感亲切。那些无法被标准化的声调与词汇,承载着最地道的人间悲喜。当一种声音渐行渐远,它诉说的深情,却与我们永远相关。

by ONE

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值