首页 >Unity3D频道 >【CSLight研究院】 > CSLight研究院之学习笔记脚本NGUI里的回调方法(二)
2014
08-14

CSLight研究院之学习笔记脚本NGUI里的回调方法(二)

这两天和李总沟通的十分密切,也给李总提了很多CSLight的Bug,李总很热心一个个都Fix了,嘿嘿。记录一下今天的学习笔记。

Foxmail20140814_1

1.界面里的监听事件,比如按钮的点击一类事件。

2.界面里监听Tween事件,比如NGUI里的位移动画一类的事件。

3.界面里监听自己写的回调Action。

在GitHub上取下CSLight的最新版本,或者在本文的最后来下载我的例子工程。

ScriptMgr.cs (Unity写的C#)脚本管理类

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


/// <summary>
/// 这个类实现脚本的Logger接口,脚本编译时的信息会从Log输出出来
/// </summary>
class ScriptLogger : CSLE.ICLS_Logger
{

    public void Log(string str)
    {
        UnityEngine.Debug.Log(str);
    }

    public void Log_Error(string str)
    {
        Debug.LogError(str);
    }

    public void Log_Warn(string str)
    {
        Debug.LogWarning(str);
    }
}

public class ScriptMgr
{
    /// <summary>
    /// ScriptMgr用单例模式,主要是为了提供C#Light Env的初始化
    /// </summary>
    public static ScriptMgr Instance
    {
        get
        {
            if (g_this == null)
                g_this = new ScriptMgr();
            return g_this;

        }
    }
    #region forInstance
    static ScriptMgr g_this;
    public CSLE.CLS_Environment env
    {
        get;
        private set;
    }
    private ScriptMgr()
    {
        env = new CSLE.CLS_Environment(new ScriptLogger());
        env.logger.Log("C#LightEvil Inited.Ver=" + env.version);

        RegTypes();
    }
    #endregion


    /// <summary>
    /// 这里注册脚本有权访问的类型,大部分类型用RegHelper_Type提供即可
    /// </summary>
    void RegTypes()
    {
        //大部分类型用RegHelper_Type提供即可
        env.RegType(new CSLE.RegHelper_Type(typeof(Vector2)));
        env.RegType(new CSLE.RegHelper_Type(typeof(Vector3)));
        env.RegType(new CSLE.RegHelper_Type(typeof(Vector4)));
        env.RegType(new CSLE.RegHelper_Type(typeof(Time)));

        env.RegType(new CSLE.RegHelper_Type(typeof(Debug)));
        env.RegType(new CSLE.RegHelper_Type(typeof(GameObject)));
        env.RegType(new CSLE.RegHelper_Type(typeof(Component)));
        env.RegType(new CSLE.RegHelper_Type(typeof(Transform)));
		env.RegType(new CSLE.RegHelper_Type(typeof(Resources)));
		env.RegType(new CSLE.RegHelper_Type(typeof(UnityEngine.Object)));

        //对于AOT环境,比如IOS,get set不能用RegHelper直接提供,就用AOTExt里面提供的对应类替换
        env.RegType(new CSLE.RegHelper_Type(typeof(int[]), "int[]"));//数组要独立注册
        env.RegType(new CSLE.RegHelper_Type(typeof(List<int>), "List<int>"));//模板类要独立注册


		//监听Action
		env.RegType(new CSLE.RegHelper_DeleAction(typeof(System.Action),"Action")); 
		env.RegType(new CSLE.RegHelper_DeleAction<int>(typeof(Action<int>),"Action<int>")); 

		//监听NGUI的代理事件
		env.RegType(new CSLE.RegHelper_Type(typeof(UIEventListener)));
		env.RegType(new CSLE.RegHelper_DeleAction<GameObject>(typeof(UIEventListener.VoidDelegate), "UIEventListener.VoidDelegate"));

		//监听NGUI的位移代理事件
		env.RegType(new CSLE.RegHelper_Type(typeof(EventDelegate)));
		env.RegType(new CSLE.RegHelper_Type(typeof(TweenPosition)));
		env.RegType(new CSLE.RegHelper_DeleAction(typeof(EventDelegate.Callback), "EventDelegate.Callback"));


		env.RegType(new CSLE.RegHelper_Type(typeof(TweenScale)));

        env.RegType(new CSLE.RegHelper_Type(typeof(Rect)));
        env.RegType(new CSLE.RegHelper_Type(typeof(PrimitiveType)));
		env.RegType(new CSLE.RegHelper_Type(typeof(UISprite)));
		//监听一个我自己写的类
		env.RegType(new CSLE.RegHelper_Type(typeof(Task)));
    }

    public bool projectLoaded
    {
        get;
        private set;
    }
    public void LoadProject()
    {
        if (projectLoaded) return;
        try
        {
            string[] files = System.IO.Directory.GetFiles(Application.streamingAssetsPath, "*.cs", System.IO.SearchOption.AllDirectories);
            Dictionary<string, IList<CSLE.Token>> project = new Dictionary<string, IList<CSLE.Token>>();
            foreach (var v in files)
            {
                var tokens = env.tokenParser.Parse(System.IO.File.ReadAllText(v));
                project.Add(v, tokens);
            }
            env.Project_Compiler(project, true);
            projectLoaded = true;
        }
        catch (Exception err)
        {

            Debug.LogError("编译脚本项目失败,请检查" + err.ToString());
        }
    }
    public void Execute(string code)
    {
        var content = env.CreateContent();


        try
        {
            var tokens = env.ParserToken(code);
            var expr = env.Expr_CompilerToken(tokens);
            expr.ComputeValue(content);
        }
        catch (Exception err)
        {
            var dumpv = content.DumpValue();
            var dumps = content.DumpStack(null);
            var dumpSys = err.ToString();
            Debug.LogError(dumpv + dumps + dumpSys);
        }
    }
}

UICommon.cs (Unity写的C#)绑定在NGUI的Panel下,用来调用热更新的测试脚本。

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

public class UICommon : MonoBehaviour {

	void Start ()
	{
		ScriptMgr.Instance.LoadProject();
		ScriptMgr.Instance.Execute("UIMain.Start(""+name+"");");
	}
}

Task.cs (Unity写的C#)这是一条测试工具脚本,意思是在热更新脚本中传入Action ,在这里完成以后在将回调返回给热更新的脚本。

using UnityEngine;
using System.Collections;
using System;

public class Task : MonoBehaviour {

	static public Task instance;
	static Task()
	{
		GameObject go = new GameObject("_Task");
		DontDestroyOnLoad(go);
		instance = go.AddComponent<Task>();
	}

	static private Action taskAction;

	static public void RegistrationAction(System.Action action)
	{
		//在热更新类里面调用此方法,传入一个Action
		taskAction = action;
		instance.StartCoroutine(DelayCoroutine());
	}

	private static IEnumerator DelayCoroutine() {
		yield return new WaitForSeconds(0.1f);
		//事情做完以后在回调返回热更新类
		taskAction();
	}
}

UIMain.cs (可以进行下载热更新的脚本)

using UnityEngine;
using System.Collections;
using System;

public class UIMain  {

	static GameObject button ;

	static GameObject button1 ;

	//UICommon里面调用脚本的Start方法,并且传入了名子的字符串
	static void Start (string root) 
	{
		Transform rootUI = GameObject.Find(root).transform;
		//在Resources下面读取资源或者 Assetbundle来读取,并且实例化在场景视图中。这一句操作我觉得也可以在Unity的脚本中完成
		GameObject prefab  = Resources.Load("UIMain") as GameObject;
		GameObject gameObject = GameObject.Instantiate(prefab) as GameObject;
		//放在UIPanel下面,让坐标在原点
		gameObject.transform.parent = rootUI;
		gameObject.transform.localPosition = Vector3.zero;
		gameObject.transform.localScale = Vector3.one;

		Transform	transform = gameObject.transform;
		//找到UIPrefab下面的一个Sprite并且修改一下Sprite的名子。
		UISprite sprite = transform.Find("Sprite").GetComponent("UISprite")as UISprite;
		sprite.spriteName ="Glow";
		sprite.transform.localPosition = new Vector3 (10,100,0);
		sprite.MakePixelPerfect();

		//获取按钮对象,并且增加按钮的监听
		button = transform.Find("Button").gameObject;
		button1= transform.Find("Button1").gameObject;

		//监听按钮事件
		UIEventListener.Get(button).onClick =Click;
		UIEventListener.Get(button1).onClick =Click;

		TweenPosition move = TweenPosition.Begin(sprite.gameObject,1f,new Vector3(sprite.transform.position.x,sprite.transform.position.y + 200,sprite.transform.position.z));


		//处理NGUI的位移事件
		EventDelegate.Callback  callBack=()=>{
			Debug.Log("雨松MOMO提示您:位移完毕");
		};
		//利用NGUIDelegate来监听回调
		EventDelegate.Add(move.onFinished,callBack);

		////注册进我自己写类,等待回调
		Action act =()=>
		{
			Debug.Log("doSomeThings");
		};
		//利用我自己写类来监听回调
		Task.RegistrationAction(act);

	}

	//当按钮点击的时候在脚本中得到回调
	static void Click(GameObject go)
	{
		//根据不同的按钮执行不同的逻辑

		//我在写这篇文章的时候 向李总提了bug 	说  不能 
		//if(go == button)这样来判断,不过后来他说已经修改了这个bug 。大家更新一下应该就可以了
		if(go.Equals(button))
		{
			Debug.Log("雨松MOMO");
		}else if(go.Equals(button1)){
			Debug.Log("东方小败败");
		}
	}
}

下载地址:http://pan.baidu.com/s/1nt8zrst

最近工作也有点忙, 学习只能在下班以后,目前看来还有泛型这块CSLight支持的不好。等我明天做一个更为复杂的界面在看看效率。 加油!!

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

CSLight研究院之学习笔记脚本NGUI里的回调方法(二)》有 12 条评论

  1. 豌豆说:

    不支持Class的继承,这个很蛋疼,写惯了C#,突然没了这功能很不舒服,不知道有没有什么办法可以像lua那样模拟出来

  2. 脚趾上的星光说:

    在unity4.5里面打开这个例子可以正常运行,但是在unity5里,点击按钮就没响应了,这是为什么呢

  3. 孤臣说:

    请问一下,比如我有两个热更新脚本被加载,其中一个要调用另一个的函数,这样可以吗?因为脚本调用其他类要注册,但是因为被调用那个也是热更新脚本,好像注册不了。还有请问一下大神做项目的时候一般是怎么划分普通代码和热更新代码的呢?

  4. 请问下 ios的网络图片怎么能下载到本地?Application.persistentDataPath我用的这个路径 读取图片可以读取到 不知道为什么下载不下来www = new WWW(url); yield return www; byte[] pngData = newTexture.EncodeToPNG();File.WriteAllBytes(PicName, pngData);这是我的代码

  5. 请问下 ios的网络图片怎么能下载到本地?Application.persistentDataPath我用的这个路径 读取图片可以读取到 不知道为什么下载不下来 www = new WWW(url); yield return www; byte[] pngData = newTexture.EncodeToPNG(); File.WriteAllBytes(PicName, pngData);这是我的代码

  6. Tammy说:

    加油。很看好这个。比ulua管理起来方便些。

  7. 洪峤说:

    活到老,学到老!跟着鱼松有饭吃

  8. AK--47说:

    沙发。momo,加油。跟进中。。。。。

留下一个回复

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