码迷,mamicode.com
首页 > 编程语言 > 详细

unity3d热更新解决方案,使用ulua插件开发的框架。

时间:2015-11-11 11:16:08      阅读:454      评论:0      收藏:0      [点我收藏+]

标签:

ulua插件下载地址 www.ulua.org,下面要说的是ulua的开发框架。

首先是 LuaLoader 类,它负责把一个 lua 的 table 加载起来,使此 lua 的 table 像一个 unity 的 component 一样挂在游戏对象上,代码如下:

using LuaInterface;
using System;
using UnityEngine;

public class LuaLoader : MonoBehaviour
{
    public string Name;

    LuaTable m_table;
    LuaFunction m_updateFunc;
    LuaFunction m_fixedUpdateFunc;

    void Awake()
    {
        if (string.IsNullOrEmpty(Name))
            throw new ArgumentException("Name");

        m_table = LuaHelper.GetLuaTable(Name);
        if (m_table == null)
            throw new ArgumentNullException("No table in " + Name);

        // Init lua
        m_table["transform"] = transform;
        m_table["gameObject"] = gameObject;

        // Awake
        CallMethod("Awake");

        //
        m_updateFunc = GetMethod("Update");
        m_fixedUpdateFunc = GetMethod("FixedUpdate");
    }

    void Start()
    {
        CallMethod("Start");
    }

    void Update()
    {
        if (m_updateFunc != null)
            m_updateFunc.Call(Time.deltaTime);
    }

    void FixedUpdate()
    {
        if (m_fixedUpdateFunc != null)
            m_fixedUpdateFunc.Call();
    }

    void OnEnable()
    {
        CallMethod("OnEnable");
    }

    void OnDisable()
    {
        CallMethod("OnDisable");
    }

    void OnDestroy()
    {
        CallMethod("OnDestroy");

        // 释放内存
        m_table["transform"] = null;
        m_table["gameObject"] = null;

        m_table.Release();
        m_table = null;

        if (m_updateFunc != null)
            m_updateFunc.Release();

        if (m_fixedUpdateFunc != null)
            m_fixedUpdateFunc.Release();

        LuaScriptMgr.Instance.LuaGC();
    }

    LuaFunction GetMethod(string methodName)
    {
        return m_table[methodName] as LuaFunction;
    }

    void CallMethod(string name)
    {
        var func = GetMethod(name);

        if (func != null)
        {
            func.Call();
            func.Release();     // 释放内存
        }
    }

    public LuaTable Table
    {
        get { return m_table; }
    }
}

  其次是 lua 与 c# 的交互,提供了两个帮助类,一个是 LuaHelper ,与游戏逻辑无关的方法封装在里面;另外一个是 LuaUtils, lua 中要访问 c# 代码的方法(与游戏逻辑有关的)都封装在里面。

  LuaHelper 关键的几个方法代码如下:

using LuaInterface;
using Resource;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;

public static class LuaHelper
{
    #region GetLuaComponent

    public static LuaTable GetLuaComponent(Transform transform, string type)
    {
        var loaders = transform.GetComponents<LuaLoader>();
        var rightLoader = loaders.FirstOrDefault(lt => lt.Table != null && lt.Table.name == type);

        return rightLoader != null ? rightLoader.Table : null;
    }

    public static LuaTable GetLuaComponent(GameObject gameObject, string type)
    {
        return GetLuaComponent(gameObject.transform, type);
    }

    #endregion

    /// <summary>
    /// 从ab包中加载table,供lua使用
    /// </summary>
    /// <param name="name">table名</param>
    public static void LoadLuaTable(string name)
    {
        if (string.IsNullOrEmpty(name))
            throw new ArgumentException("name");

        LuaTable table = LuaScriptMgr.Instance.GetLuaTable(name);

        if (table == null)
        {
            using (var loadLua = new LoadLuaHandler(name))
                LuaScriptMgr.Instance.DoString(loadLua.Text);
        }
    }

    public static LuaTable GetLuaTable(string name)
    {
        if (string.IsNullOrEmpty(name))
            throw new ArgumentException("name");

        LuaTable table = LuaScriptMgr.Instance.GetLuaTable(name);

        if (table == null)
        {
            using (var loadLua = new LoadLuaHandler(name))
                LuaScriptMgr.Instance.DoString(loadLua.Text);

            table = LuaScriptMgr.Instance.GetLuaTable(name);
        }

        return table;
    }

    public static LuaFunction GetLuaFunction(string className, string funcName)
    {
        if (string.IsNullOrEmpty(className))
            throw new ArgumentException(className);
        if (string.IsNullOrEmpty(funcName))
            throw new ArgumentException(funcName);

        LuaTable table = GetLuaTable(className);
        return table[funcName] as LuaFunction;
    }

    public static object[] CallFunction(string className, string funcName, params object[] args)
    {
        LuaFunction func = GetLuaFunction(className, funcName);
        if (func == null)
            throw new ArgumentNullException(string.Format("Cann‘t find lua function: {0}.{1}", className, funcName));

        var returnArgs = args == null ? func.Call() : func.Call(args);
        func.Release();

        return returnArgs;
    }
}

  另外,关于通过 lua 代码给c#打补丁的功能,是在 UIPanel OnEnable 的第一帧检测补丁和打补丁的,c#代码如下:

using LuaInterface;
using System;
using System.Collections.Generic;
using UnityEngine;

public class LuaPatchManager : IDisposable
{
    List<Patch> m_patches;

    #region Singleton

    static LuaPatchManager s_instance;

    public static LuaPatchManager Instance
    {
        get { return s_instance; }
    }

    #endregion

    #region Patch

    class Patch : IDisposable
    {
        LuaFunction m_validate;
        LuaFunction m_correct;

        public Patch(LuaFunction validate, LuaFunction correct)
        {
            if (validate == null)
                throw new ArgumentNullException("validate");
            if (correct == null)
                throw new ArgumentNullException("correct");

            m_validate = validate;
            m_correct = correct;
        }

        public bool Validate(UIPanel uiPanel)
        {
            var objs = m_validate.Call(uiPanel);
            return (bool)objs[0];
        }

        public void Correct(UIPanel uiPanel)
        {
            m_correct.Call(uiPanel);
        }

        #region IDisposable

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        void Dispose(bool disposing)
        {
            if (disposing)
            {
                m_validate.Release();
                m_validate = null;
                m_correct.Release();
                m_correct = null;
            }
        }

        ~Patch()
        {
            Dispose(false);
        }

        #endregion
    }

    #endregion

    private LuaPatchManager(LuaTable listTable)
    {
        if (listTable == null || listTable.Values.Count <= 0)
            throw new ArgumentException("listTable == null || listTable.Values.Count <= 0");

        m_patches = new List<Patch>();

        foreach (string name in listTable.Values)
        {
            var patch = LuaHelper.GetLuaTable(name);
            if (patch != null)
            {
                var validateFunc = patch["Validate"] as LuaFunction;
                var correctFunc = patch["Correct"] as LuaFunction;

                if (validateFunc != null && correctFunc != null)
                    m_patches.Add(new Patch(validateFunc, correctFunc));

                patch.Release();
            }
        }

        listTable.Release();
        LuaScriptMgr.Instance.LuaGC();
    }

    public static void Load()
    {
        LuaTable listTable = null;
        string targetFileName = "LuaPatchList";

        try
        {
            listTable = LuaHelper.GetLuaTable(targetFileName);
        }
        catch
        {
            Debug.LogWarning("No file: " + targetFileName);
        }

        if (listTable != null)
        {
            if (listTable.Values.Count > 0)
                s_instance = new LuaPatchManager(listTable);

            listTable.Release();
        }
    }

    public void DoPatch(UIPanel uiPanel)
    {
        if (uiPanel == null)
            throw new ArgumentNullException("uiPanel");

        for (int i = 0; i < m_patches.Count; i++)
        {
            Patch p = m_patches[i];
            if (p.Validate(uiPanel))
            {
                p.Correct(uiPanel);
                break;
            }
        }
    }

    #region IDisposable

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    void Dispose(bool disposing)
    {
        if (disposing)
        {
            for (int i = 0; i < m_patches.Count; i++)
                m_patches[i].Dispose();

            m_patches.Clear();
            m_patches = null;
        }
    }

    ~LuaPatchManager()
    {
        Dispose(false);
    }

    #endregion
}

  lua代码如下:

LuaPatchList=
{
	
};

// 一个补丁例子如下:
MainInfoControllerPatch={};

local function ClickTest()
	TipsShowController.Show("Who are you?");
end

-- 验证此uiPanel是否是希望打补丁的uiPanel --
function MainInfoControllerPatch.Validate(uiPanel)
	return uiPanel.transform.parent~=nil and uiPanel.transform.parent.name=="MainInfoController(Clone)";
end

-- 纠正此uiPanel上的展示内容,执行方法等 --
function MainInfoControllerPatch.Correct(uiPanel)
	local titleLabel=uiPanel.transform:Find("LabelName"):GetComponent("UILabel");
	titleLabel.text="TianJie";

	local mustBuyButton=uiPanel.transform:Find("ButtonFashion"):GetComponent("UIButton");
	mustBuyButton.onClick:Clear();
	EventDelegate.Add(mustBuyButton.onClick,DelegateFactory.EventDelegate_Callback(ClickTest));
end

  

unity3d热更新解决方案,使用ulua插件开发的框架。

标签:

原文地址:http://www.cnblogs.com/jietian331/p/4955282.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!