首页 >Unity3D频道 >【CSLight研究院】 > CSLight研究院之与uLua的效率对比(三)
2014
08-18

CSLight研究院之与uLua的效率对比(三)

测试环境

1.红米手机一枚。

2.4张1024的Atals图集。

3.脚本中实例化400个UISprite。

4.随机设置UISprite的深度,这样可以让UI的drawCall 数量非常恐怖。

以上参数已经非常恐怖了。如下图所示在电脑上 230个DrawCall 23帧。 测试环境每一张UISprite没1秒随即移动到另外一个位置。所有控制代码均在脚本中完成,我们来分别测试一下 预编译DLL、CSLight、uLua的效率怎么样。

Foxmail20140818_2

 

 

装红米手机上运行一下看看。预编译DLL 加载400个UISprite耗时 0.16s,运行时帧数 16.83FPS

device-2014-08-18-c#

 

使用CSLight来 加载400个UISprite耗时 0.78s,运行时帧数 13.81FPS

device-2014-08-18-CSLight

 

使用uLua来 加载400个UISprite耗时 0.53s,运行时帧数 11.87FPS

device-2014-08-18-lua

 

测试结果:

在脚本中调用Unity自身的方法,比如Resource.Load、 Instantiate 、uLua效率要高一些。

但是如果处理脚本与C#之间的来回调用,那么CSLight效率更高一些。

测试到这里,我觉得无论你用uLua还是CSLight都可以进行Unity的热更新,因为它俩效率差不多呵呵。就看你的个人喜好了!

测试代码比较丑,不过能说明问题,因为 C# 的代码和 CSLight的代码完全一样,所以这里我只贴C#和ulua的代码。

C#

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

public class UIMain  {

	private static int SpriteCount = 100;
	
	private static List<UISprite>spriteList;
	
	// Use this for initialization
	static public  void Start (string root) 
	{
		spriteList = new List<UISprite>();
		Transform rootUI = GameObject.Find(root).transform;
		GameObject yusongPrefab = Resources.Load("yusong") as GameObject;
		GameObject ruoruoPrefab  = Resources.Load("ruoruo") as GameObject;
		GameObject yusongPrefab1 = Resources.Load("yusong1") as GameObject;
		GameObject ruoruoPrefab1  = Resources.Load("ruoruo1") as GameObject;
		
		for(int i =0; i< SpriteCount; i++)
		{
			GameObject go = Object.Instantiate(yusongPrefab) as GameObject;
			go.transform.parent = rootUI;
			go.transform.localPosition = Vector3.zero;
			go.transform.localScale = Vector3.one;
			UISprite sprite = go.GetComponent("UISprite") as UISprite;
			sprite.depth = Random.Range(0,SpriteCount);
			spriteList.Add(sprite);
			
			go = Object.Instantiate(ruoruoPrefab) as GameObject;
			go.transform.parent = rootUI;
			go.transform.localPosition = Vector3.zero;
			go.transform.localScale = Vector3.one;
			sprite = go.GetComponent("UISprite") as UISprite;
			sprite.depth = Random.Range(0,SpriteCount);
			spriteList.Add(sprite);

			go = Object.Instantiate(yusongPrefab1) as GameObject;
			go.transform.parent = rootUI;
			go.transform.localPosition = Vector3.zero;
			go.transform.localScale = Vector3.one;
			sprite = go.GetComponent("UISprite") as UISprite;
			sprite.depth = Random.Range(0,SpriteCount);
			spriteList.Add(sprite);
			
			go = Object.Instantiate(ruoruoPrefab1) as GameObject;
			go.transform.parent = rootUI;
			go.transform.localPosition = Vector3.zero;
			go.transform.localScale = Vector3.one;
			sprite = go.GetComponent("UISprite") as UISprite;
			sprite.depth = Random.Range(0,SpriteCount);
			spriteList.Add(sprite);
		}
	}

	static public void Move()
	{
		for(int i =1; i<spriteList.Count; i++ )
		{
			UISprite	sprite = spriteList[i];
			Vector3 next = new Vector3( Random.Range(-400,400) , Random.Range(-260,260),0);
			TweenPosition position = TweenPosition.Begin(sprite.gameObject,1,next);
		}
		
		Vector3 firstNext = new Vector3( Random.Range(-400,400) , Random.Range(-260,260),0);
		TweenPosition firstPosition = TweenPosition.Begin(spriteList[0].gameObject,1,firstNext);
		UIEventCommon.EventMove(firstPosition);
	}

}

 

uLua

luanet.load_assembly('UnityEngine')
GameObject = luanet.import_type('UnityEngine.GameObject')
Transform = luanet.import_type('UnityEngine.Transform')
Resources = luanet.import_type('UnityEngine.Resources')
Vector3 = luanet.import_type('UnityEngine.Vector3')
Random = luanet.import_type('UnityEngine.Random')



UISprite = luanet.import_type('UISprite')
TweenPosition = luanet.import_type('TweenPosition')
UIEventCommon = luanet.import_type('UIEventCommon')

local SpriteCount =400
local myData = {}


function Start(name)
	local go = GameObject.Find(name)

	local yusongPrefab = Resources.Load("yusong")
	local ruoruoPrefab  = Resources.Load("ruoruo");
	local yusongPrefab1 = Resources.Load("yusong1");
	local ruoruoPrefab1  = Resources.Load("ruoruo1");

	for a=0,SpriteCount,4 do        
		local go = GameObject.Instantiate(yusongPrefab);
		go.transform.parent = rootUI;
		go.transform.localPosition = Vector3.zero;
		go.transform.localScale = Vector3.one;
		local sprite = go:GetComponent('UISprite'); 
		sprite.depth = Random.Range(0,SpriteCount);
		myData[a] = sprite;

		local go = GameObject.Instantiate(ruoruoPrefab);
		go.transform.parent = rootUI;
		go.transform.localPosition = Vector3.zero;
		go.transform.localScale = Vector3.one;
		local sprite = go:GetComponent('UISprite'); 
		sprite.depth = Random.Range(0,SpriteCount);
		myData[a+1] = sprite;

		local go = GameObject.Instantiate(yusongPrefab1);
		go.transform.parent = rootUI;
		go.transform.localPosition = Vector3.zero;
		go.transform.localScale = Vector3.one;
		local sprite = go:GetComponent('UISprite'); 
		sprite.depth = Random.Range(0,SpriteCount);
		myData[a+2] = sprite;

		local go = GameObject.Instantiate(ruoruoPrefab1);
		go.transform.parent = rootUI;
		go.transform.localPosition = Vector3.zero;
		go.transform.localScale = Vector3.one;
		local sprite = go:GetComponent('UISprite'); 
		sprite.depth = Random.Range(0,SpriteCount);
		myData[a+3] = sprite;
	end 
end

function Move()

	for key, value in pairs(myData) do  
		local sprite = value
		local next = Vector3(Random.Range(-400,400),Random.Range(-260,260),0);
		TweenPosition.Begin(sprite.gameObject,1,next);
	end 
		local firstNext = Vector3( Random.Range(-400,400) , Random.Range(-260,260),0);
		local firstPosition = TweenPosition.Begin(myData[0].gameObject,1,firstNext);
		UIEventCommon.EventMove(firstPosition);

end

UICommon.cs 测试入口脚本,为了公平我分别把这个脚本挂在了三个场景中。每次切场景Unity会自动施放内存,我会根据场景名来动态初始化脚本。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using LuaInterface;
public class UICommon : MonoBehaviour {


	static public LuaState luaState ;

	private float InitTime;
	void Start()
	{
		float time = Time.realtimeSinceStartup;
		if(Application.loadedLevel == 0)
		{
			//C# DLL方式加载
			CUIMain.Start(name);
			CUIMain.Move();
		}else if(Application.loadedLevel == 1)
		{
			//CSLight方式加载
				ScriptMgr.Instance.LoadProject(new string[]{"UIMain"});
				ScriptMgr.Instance.Execute("UIMain.Start(""+name+"");");
				ScriptMgr.Instance.Execute("UIMain.Move();");
		}else 
		{
			//uLua方式加载
			TextAsset scriptFile = Resources.Load<TextAsset>("UIMain.lua");
			luaState= new LuaState();
			luaState.DoString(scriptFile.text);
			LuaFunction f = luaState.GetFunction("Start");
			f.Call(name);
			f = luaState.GetFunction("Move");
			f.Call();
		}
		InitTime = Time.realtimeSinceStartup - time;
	}

	void OnGUI()
	{
		GUI.color = Color.red;

		if(GUILayout.Button("CS加载",GUILayout.Width(100),GUILayout.Height(100))){
			Application.LoadLevel(0);
		}
		if(GUILayout.Button("CSLight加载",GUILayout.Width(100),GUILayout.Height(100))){
			Application.LoadLevel(1);
		}
		if(GUILayout.Button("uLua加载",GUILayout.Width(100),GUILayout.Height(100))){
			Application.LoadLevel(2);
		}
		GUILayout.Label("加载时间 :" + InitTime);
	}

}

UIEventCommon.cs 用来测试脚本与C#之间的回调,这里每一秒会回调一次。

using UnityEngine;
using System.Collections;
using LuaInterface;

public class UIEventCommon  {

	static public  void EventMove(TweenPosition tweenPostion)
	{
		EventDelegate.Add(tweenPostion.onFinished,delegate() {
		
			if(Application.loadedLevel == 0)
			CUIMain.Move();
			else 	if(Application.loadedLevel == 1)
			ScriptMgr.Instance.Execute("UIMain.Move();");
			else
			{
				LuaFunction f = UICommon.luaState.GetFunction("Move");
				f.Call();
			}
		});
	}
}

 

最后是下载地址,欢迎大家在下面给我留言,也欢迎大家一起讨论Unity的热更新。谢谢。

http://pan.baidu.com/s/1o6NWyX8

工程下载完以后,大家可以直接打包装在Android手机上或者IOS上 。iOS我没上真机看,没找到iPhone4,如果你有机器的话帮我测试一下嘿嘿。

我在iPhone5s上看了一下 全程无压力,有iPhone4的朋友帮我看看哦。。

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

CSLight研究院之与uLua的效率对比(三)》有 33 条评论

  1. 雨松哥您好,目前我们在使用ToLua请问有时间可以发布一份相关介绍吗?

  2. mily说:

    雨松,能就ulua和slua在性能和易用性上面简单分析下各自优劣吗?最近项目准备引入热更新,基本上就在这2个之中选一个了

  3. 流年 伊说:

    @雨松 请问下 你们用的slua框架现在游戏上线了吗 使用起来感觉怎么样

  4. 说:

    雨松,Unity5x 下 mac 上运行 uLua的方式要崩!

  5. CSLight初学者说:

    请问下,使用CSLight只能使用Static的函数,对于Unity提供的Invoke、InvokeRepeating之类的API应该怎么调用呢?

  6. Mike说:

    这语言官网在哪,或者官方论坛,我想看个release note来决定用哪个版本啊

  7. Tango说:

    最近也在开始用slua,但是一直没有找到调试lua的方法,这个很不方便,不知道雨神你是怎么解决的= =

  8. 华仔说:

    大大 看你留言说是用SLUA 我也是用SLUA做 能不能做个建议的DEMO 或者写点文章让我也学习一下 谢谢

  9. ZFHM说:

    雨神, 现在你们项目。用的是C#Light还是uLua。我下载你这个在Unity5中运行,点击运行uLua的时候。Unity直接崩溃了。

  10. 唐平说:

    事先保存文件名,后用www加载

  11. MOMO请问一下,ScriptMgr.Instance.LoadProject();中的实现是否在安卓下是有问题的,我看其中用的是System.IO.Directory.GetFiles(Application.streamingAssetsPath。应该怎么处理安卓下的遍历路径内文件呀?

  12. 风之来者说:

    c#light目前还不完善,缺少luajit的安全编译,缺少国内众多游戏公司流行的Protobuffer-lua的动态协议解析,效率还低于tolua c#,所以目前还不具备实用性。选用的人慎用!!~~

  13. hi说:

    CSEvil就是个垃圾,千万别用.写的垃圾脚本解释器,各种不支持,各种崩溃. 跟ulua根本不在一个级别上.

  14. 流水说:

    LuaFunction f = UICommon.luaState.GetFunction(“Move”); f.Call();uLua里的LuaFunction需要缓存的,不然每次都会new出一个function出来,你这样对测试结果是有影响的。修正下测试看看呢

  15. 支持,测试数据结果最有说服力。 CSLight研究院之与uLua的效率对比(三) - 雨松MOMO程序研究院 - 1

  16. AK--47说:

    很有说服力。不错。接下去,这方面再研究什么更新呢,期待。。。。

  17. 说:

    你们俩口字这头像是谁做的啊???好羡慕 CSLight研究院之与uLua的效率对比(三) - 雨松MOMO程序研究院 - 1

留下一个回复

你的email不会被公开。 必填项已用 * 标注。