Unity Tolua 性能优化(一)减少不必要的c#交互

最近使用的是unity+tolua,由于项目需求和性能改进,后面已经做过大量的修改,本文记录一些优化的地方
tolua是c#生成wrap导出接口给lua使用,在ObjectTranslator中通过一个Dictionary保存lua中引用c#的对象,保证该对象不会被回收,lua需要使用的时候也可以通过id获取该对象。
下面是平时使用时候一个很常见的代码:

代码1

    self.goHead = self.gameObject.transform:Find("GoHead").gameObject;

这段代码功能很简单获取当前GameObject下子结点GoHead的GameObject.
下面看看这段代码与c#交互的过程。
先是self.gameObject.transform,在lua里面访问了gameobject的transform属性 我们看看UnityEngine_GameObjectWrap.cs具体执行了哪些操作

    //UnityEngine_GameObjectWrap.cs 
	static int get_transform(IntPtr L)
	{
		object o = null;
		o = ToLua.ToObject(L, 1);
		UnityEngine.GameObject obj = (UnityEngine.GameObject)o;
		UnityEngine.Transform ret = obj.transform;
		ToLua.Push(L, ret);
		return 1;
	}

    //ToLua.cs
    public static void Push(IntPtr L, UnityEngine.Object obj)
    {
        PushUserObject(L, obj);
    }

    //ToLua.cs
    static void PushUserObject(IntPtr L, object o)
    {
        Type type = o.GetType();
        int reference = LuaStatic.GetMetaReference(L, type);                   
        PushUserData(L, o, reference);
    }

    //ToLua.cs
    public static void PushUserData(IntPtr L, object o, int reference)
    {
        int index;
        ObjectTranslator translator = ObjectTranslator.Get(L);
        index = translator.AddObject(o);
        LuaDLL.tolua_pushnewudata(L, reference, index);
    }    

上面代码取了主要的流程,删除了一些跟问题无关的代码。
可以看到lua通过gameboject访问transform最终调用translator.AddObject(o); 把transfrom增加到lua对c#的引用字典里面进去。Find返回的子节点的transform也是一样的情况。这两个transfrom在这里我们并不需要,在下一次gc的时候就会被回收掉,明显是不必要开销。
解决这个问题也很简单减少lua对c#的调用就可以了,看下面代码:

代码2

    //LuaUtil.cs
    static public GameObject GetGameObject(GameObject goRoot, string path=null)
    {
        return goRoot.transform.Find(path).gameObject;
    }
    self.goHead = LuaUtil.GetGameObject(self.gameObject, "GoHead");

这里我们增加了一个c#的函数把结果直接返回,避免了lua访问不必要transfrom。
优化性能测试:

测试代码1

function LuaUtilTest.DoTest(goTest)
    local tmStart = os.clock();
    local testCount = 1000000;
    local goTmp;
    for __idx=1,testCount do
        goTmp = goTest.transform:Find("GoHead").gameObject;
    end
    print("LuaUtilTest cost:", uiButton, os.clock()-tmStart);
end

测试代码2

function LuaUtilTest.DoTest(goTest)
    local tmStart = os.clock();
    local testCount = 1000000;
    local goTmp;
    for __idx=1,testCount do
        goTmp = LuaUtil.GetGameObject(goTest, "GoHead");
    end
    print("LuaUtilTest cost:", uiButton, os.clock()-tmStart);
end

在unity2018.3 Windows10平台下 分别执行了100万次结果

测试代码 第一次 第二次 第三次
测试代码1 1.928s 1.928s 1.928s
测试代码2 0.884s 0.855s 0.900s

测试结果可以看到性能提升还是很明显的测试代码2执行时间不到测试代码2的一半

posted @ 2020-11-25 19:26  搬山码农  阅读(526)  评论(0)    收藏  举报