Unity3d使用线程的姿势

想必大家也知道,U3D中可以使用线程,但是却不能在子线程中访问U3D的类型,这里我就分享下我的做法。


首先分享两个脚本~

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

public class CoroutineWrapper : MonoBehaviour {
    #region 单例
    static CoroutineWrapper inst;
    private readonly static object mutex = new object();
    public static CoroutineWrapper Inst {
        get {
            lock (mutex) {
                if (inst == null) {
                    var obj = new GameObject("CoroutineWrapper");
                    inst = obj.AddComponent();
                }
                return inst;
            }
        }
    }
    void Awake() {
        inst = this;
        DontDestroyOnLoad(this);
    }
    #endregion
    public IEnumerator ExeDelay(int frames,Action ev) {
        for (int i = 0; i < frames;i++ ) {
            yield return new WaitForEndOfFrame();
        }
        ev();
    }
    public IEnumerator ExeDelayS(float sec, Action ev) {
        yield return new WaitForSeconds(sec);
        ev();;
    }
    public static void EXES(float sec, Action ev) {
        inst.StartCoroutine(inst.ExeDelayS(sec,ev));
    }
    public static void EXEF(int frames, Action ev) {
        inst.StartCoroutine(inst.ExeDelay(frames, ev));
    }
    public static void EXEE(Func ien) {
        inst.StartCoroutine(ien());
    }
    public Action OnPerFrame;
    void Update() {
        if (OnPerFrame != null)
            OnPerFrame();
    }
}

另一个~

using System;
using System.Collections;
using System.Collections.Generic;
/// 
/// 安全线程调用
/// 需要场上存在脚本 CoroutineWrapper
/// 
public class ThreadWrapper{

    static List actLst = new List();
    static bool isInited = false;
    static object mutex = new object();
    /// 
    /// 用此方法以在子线程调用不允许调用的方法,实质是主线程执行
    /// 
    public static void Invoke(Action act) {
        if (!isInited) {
            UnityEngine.Debug.LogError("ThreadWrapper的Init()还没被调用过");
            return;
        }
        lock (mutex) {
            if(act!=null)
                actLst.Add(act);
        }
    }
    public static void Init() {
        if (!isInited) {
            CoroutineWrapper.Inst.OnPerFrame += Loop;
            isInited = true;
        }
    }
    static void Loop() {
        if (actLst != null && actLst.Count > 0) {
            lock (mutex) {
                CoroutineWrapper.EXEF(1, actLst[0]);
                actLst.RemoveAt(0);
            }
        }
    }
}

举个栗子:

我想UGUI在不操作5秒后淡出,然后又想用.net里的Timer,那么姿势如下:

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using YangXun;
using System.Timers;

public class ui_main : MonoBehaviour {

    Component[] allUIele;

    Timer timer = new Timer(5000);
	// Use this for initialization
	void Start () {
        var t1 = CoroutineWrapper.Inst;
        ThreadWrapper.Init();
        
        allUIele = GetComponentsInChildren();
        timer.AutoReset = false;
        timer.BeginInit();
        timer.Elapsed += (a, b) => {
            ThreadWrapper.Invoke(() => {
                Debug.Log("timer trigger");
                foreach (var i in allUIele)
                    if (i is Graphic)
                        ((Graphic)i).CrossFadeAlpha(0.1f, 2, true);
                UIisHide = true;
            });
        };
        timer.Start();
	}
    bool UIisHide = false;
    void Update() {
        if (Input.GetMouseButtonDown(0)) {
            timer.Stop();
            if (UIisHide) {
                foreach (var i in allUIele)
                    if (i is Graphic)
                        ((Graphic)i).CrossFadeAlpha(1, 0.2f, true);
            }
        }
        if (Input.GetMouseButtonUp(0)) {
            timer.Start();
        }
        if (Input.GetKeyUp(KeyCode.Escape))
            Application.Quit();
    }
}

格式有点问题的样子,大约就是这样喵

你可能感兴趣的:(今天天气哈哈哈)