Unity组件的基类单例模式

0. 背景

单例模式非常常见,在各种语言上都能见到,用处也十分广泛,前一篇文章有讲到python的两种单例模式。当然Unity中组件的单例模式用途也很广,例如游戏中各种Manager, 使用StartCoroutine, GetComponent等方法的单例,本文简要讲述一下Unity中对于组件的单例模式如何构建。

1. 相同之处

首先既然是单例模式,也就符合单例的一些既定规则:

- 构造参数为私有;

- 存在static的实例变量名instance

- 存在static的方法-Instance or GetInstance,以获取instance,若第一次获取instance则需要new一个实例。

2. 不同之处

- 既然是Unity的组件Component,在new组件实例时: 先需要new GameObject, 然后new Component, 并把新建的组件实例挂载到GameObject

- 当然这个新建的GameObject不能持久化到Unity Editor,也就是xxxx.unity上不能将这个GameObejct保存进去;

- 作为一个单例的基类其实需要使用到泛型。

3. Singleton

Post Code是最好的解释行为。
首先声明命名空间:

using UnityEngine; // Unity相关API
using System.Collections;
using System;

其次声明单例类和其static的实例变量名instance

// 泛型T,继承自MonoBehaviour, 保证了此单例是组件的基类
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    protected static T instance;
    ...
}

然后实现static的方法-Instance or GetInstance

    /** Returns the instance of this singleton. */
    public static T Instance //使用c#的get,set Property的写法
    {
        get
        {

            if(instance == null){ //第一次调用Singleton<T>.Instance时instance==null
                if(instantiated)
                    return null;
                instance = (T) FindObjectOfType(typeof(T)); // 寻找object,找到后转为Component

                if (instance == null){ //如果没有找到
                    GameObject go = new GameObject();//新建GameObject
                    go.name = typeof(T).ToString();
                    instance = go.AddComponent<T>();//把T挂载到go上,
                    instantiated = true; //初始化成功
                }
            }

            //Destroy instance if the singleton persists into the editor
            if (Application.isEditor && !Application.isPlaying){ //持久化之前消除该GameObject
                Destroy(instance);
                instance = null;
            }

            return instance;
        }
    }   

4. Program

使用Singleton请看如下代码:

//新建一个HttpRequest单例
class HttpRequest : Singleton<HttpRequest>
{

    // Get请求
    public WWW GET(string url)
    {
        WWW www = new WWW (url);
        StartCoroutine (WaitForRequest (www)); // 由于是继承自MonoBehaviour,所以可以调用协程函数StartCoroutine
        while (!www.isDone) {}
        return www;
    }

    // Post请求
    public WWW POST(string url, Dictionary<string,string> post)
    {
        WWWForm form = new WWWForm();
        foreach(KeyValuePair<String,String> post_arg in post)
        {
           form.AddField(post_arg.Key, post_arg.Value);//添加表单字段数据
        }
        WWW www = new WWW(url, form);

        StartCoroutine(WaitForRequest(www));
        while (!www.isDone) {}
        return www; 
    }

    //枚举器,yield关键字作用
    private IEnumerator WaitForRequest(WWW www)
    {
        yield return www;

        // check for errors
        if (www.error == null)
        {
            Debug.Log("WWW Ok!: " + www.text);
        } else {
            Debug.Log("WWW Error: "+ www.error);
        }    
    }
}

5. 总结

上述单例介绍简单易用,欢迎大家指正交流。cs脚本文件,请移步csdz的gitbub下载。

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