LUA学习--Hotfix

HotFix相当于对已写好的脚本做一个打补丁的操作。

首先,需要在发布前对可能会修改的类前面添加[Hotfix]标识。然后在类中对于要修改的方法前添加[LuaCallCSharp]标识。至于后面这个标识,发现在编辑器模式下是可以不加的,类前面添加[Hotfix]就可以了,不过看官方Git上的FAQ,貌似发布后会报错,这里就先不深究了,就以需要添加为准了。

第一阶段:xlua.hotfix

[Hotfix]
public class HotFixMgr : MonoBehaviour
{

    private LuaEnv m_env;

    private GameObject Cube, Sphere, Capsule;
    
    void Start ()
	{
	    m_env = new LuaEnv();
	    m_env.AddLoader(MyLoader);

        m_env.DoString("require 'HotFix'");
	    Cube=GameObject.Find("Cube");
	    Sphere= GameObject.Find("Sphere");
	    Capsule = GameObject.Find("Capsule");



    }
	
    [LuaCallCSharp]
    private void SetParent()
    {
        Cube.transform.SetParent(Sphere.transform);
        Cube.transform.localPosition=Vector3.zero;
    }
    private byte[] MyLoader(ref string filePath)
    { string absPath = @"C:\Users\xxxx\Desktop" + "/" + filePath + ".lua.txt";
        string info = File.ReadAllText(absPath);
        return System.Text.Encoding.UTF8.GetBytes(info); }
  private void OnDestroy()
    {
        m_env.Dispose();
    }
}

上面涉及到一个自定义Loader的编写,为的是方便处理我们自己路径下的lua脚本。这里关键写lua脚本中的内容。

'HotFix.lua.txt'

xlua.private_accessible(CS.HotFixMgr)
xlua.hotfix(CS.HotFixMgr,'SetParent',function(self)
self.Cube.transform:SetParent(self.Capsule.transform);
--self.Cube.transform.SetParent(self,self.Capsule.transform);
self.Cube.transform.localPosition=CS.UnityEngine.Vector3.zero;
end)

这里重点说两点

1.lua访问类中的私有变量

可以看到上述多了一句xlua.private_accessible(CS.HotFixMgr),作用在于访问HotFixMgr中的私有变量,因为这里Cube等变量都是私有的,直接访问会导致报空。如果本身变量公有,不需要添加这句。

2.Lua中对unity中函数的访问

比如Vector3,在lua中访问时,需要写清楚它所有的父类引用:CS.UnityEngine.Vector3。

某一个属性,可以直接通过.来访问,而某一个方法,就有两种书写方式了。

一种是self.Cube.transform:SetParent(self.Capsule.transform);

一种是self.Cube.transform.SetParent(self,self.Capsule.transform);

这里就是lua中.和:的区别。

到这里最基本的lua修改某个方法就实现了,当然c#中各种类型的方法多了去了,比如重写带参数的,带返回值的,IEnumerator等等。这个稍后继续。

接下来还有一个坑,就是

它会在OnDestroy中调用m_env.Dispose()时报错,就是说我们在lua脚本中修改的SetParent的方法并没有释放掉。这里需要另起一个lua脚本,哪个方法改过,就把哪个方法置为nil就可以了。而这个要在OnDestroy之前调用,所以,在OnDisable()中新加一个。

 

 private void OnDisable()
    {
        m_env.DoString("require 'HotDispose'");
    }

而在'HotDispose'的lua脚本中,加入xlua.hotfix(CS.HotFixMgr,'SetParent',nil)就可以了。

第二阶段:util.hotfix_ex

如果本身方法中大部分都是可用的,只有小部分修改,也就是既想调用原方法,又想在原方法的基础上执行新的方法。

这里需要引入Xlua已经封装好的util.lua.txt,它所在路径为XLua\Resources\xlua。上代码:

local util=require 'util'
util.hotfix_ex(CS.HotFixMgr,'SetParent',function(self)
self:SetParent()
self.Cube.transform:SetParent(self.Capsule.transform);
self.Cube.transform.localPosition=CS.UnityEngine.Vector3.zero;
end)

和xlua.hotfix写法一样,直接在新的方法体中调用self:SetParent()就可以执行C#原来的方法了。这里也是要注意两点。

1.不能在xlua.hotfix中再调用当前要修改的方法

不然会报这个错。

2.这里需要把util.lua.txt脚本放到和当前自定义loader相同的路径下,虽然它本身在工程的Resource目录下,但这里发现是调用不到的,会提示找不到该文件。

第三阶段:修改各式函数(带参,带返回值,构造函数)

1.带参数的方法

这个直接在方法后面添加参数就可以了

xlua.hotfix(CS.HotFixMgr,'ShowNum',function(self,val)
local c=val+3
print(c)

end)

2.带返回值的方法修改,这里引用一个C#中写的枚举。

public enum Fruit
{
    Apple,
    Banana
}

xlua.hotfix(CS.HotFixMgr,'GetValue',function(self)
return CS.Fruit.Banana

end)

3.构造函数

比如C#代码如下

[Hotfix]
public class Test : MonoBehaviour {
    public Test()
    {
        Debug.Log("222");
    }
}

在lua中,通过[.ctor]标识构造函数

 xlua.hotfix(CS.Test,{
          ['.ctor'] = function(self)
           print('ccccc')
            end  
    })

这里发现,每次Test ts=new Test(),都会先执行原C#脚本中的构造函数,再执行lua中重写的方法,而不会直接替换掉。

你可能感兴趣的:(unity,Xlua)