StrangeIOC游戲編程框架

160010517611623.png
這是一個(gè)MVCS的游戲編程框架,下面是這個(gè)編程框架的框架圖,在做項(xiàng)目的時(shí)候可以多對(duì)照這張框架圖去實(shí)現(xiàn)模塊與模塊之間的對(duì)接。
ROOT:會(huì)去 啟動(dòng)整個(gè)StringeIOC框架
MVCS ConText:進(jìn)行框架的綁定[圖片上傳中...(7SF3LKON@%M8FOZ%{RO]R@S.png-89eb36-1510043753510-0)]

Controller:控制邏輯層
View:視圖層,通過Mediator去與Controller模塊交互
Services:服務(wù)層,在這里取得數(shù)據(jù)
Models:模型層,在這里將數(shù)據(jù)存儲(chǔ)起來

2345_image_file_copy_1.jpg
下面我們做個(gè)小案例,通過這個(gè)案例更徹底了解這個(gè)框架的執(zhí)行流程
Paste_Image.png

這個(gè)小Demo是這樣的:創(chuàng)建一個(gè)Cube,Cube上有一個(gè)text的UI顯示一個(gè)隨機(jī)的分?jǐn)?shù),運(yùn)行的時(shí)候CUbe會(huì)不停的在頻幕上隨機(jī)移動(dòng),Text上的值也是隨機(jī)的,當(dāng)我們鼠標(biāo)點(diǎn)擊中一次Cube分?jǐn)?shù)就會(huì)增加一。

運(yùn)行邏輯是:開始的時(shí)候View通過Mediator向Controller請(qǐng)求數(shù)據(jù),然后Controller向服務(wù)端請(qǐng)求數(shù)據(jù),服務(wù)端Service返回一個(gè)隨機(jī)值給Controller里面創(chuàng)建的請(qǐng)求數(shù)據(jù)的Command,Controller邏輯層再將數(shù)據(jù)傳遞給Mediator,Mediator再負(fù)責(zé)顯示到View上,然后為了將數(shù)據(jù)保存下來Controller再將數(shù)據(jù)傳給Models模型層。然后我們?cè)賱?chuàng)建一個(gè)點(diǎn)擊更新數(shù)據(jù)的Command,在這個(gè)Command里面我們將模型層的數(shù)據(jù)加一,然后再將數(shù)據(jù)返回給Services.
首先我們的代碼有這些,我們分為Command層,Model層,Service層,View層,就是MVCS,Command負(fù)責(zé)傳遞命名,Model負(fù)責(zé)保存數(shù)據(jù),Service負(fù)責(zé)與服務(wù)器交互,View負(fù)責(zé)視圖的顯示,

7SF3LKOS.png

首先創(chuàng)建ContextView負(fù)責(zé)開啟整個(gè)框架,

using strange.extensions.context.impl;
//啟動(dòng)整個(gè)StringeIOC
public class Demo1ContextView : ContextView {
    private void Awake()
    {
        this.context = new Demo1Cntext(this);//啟動(dòng)StrangeIOC框架
    }
}

然后創(chuàng)建MVCSContext負(fù)責(zé)綁定各個(gè)事件

using strange.extensions.context.api;
using strange.extensions.context.impl;
using UnityEngine;

public class Demo1Cntext : MVCSContext {

    public Demo1Cntext(MonoBehaviour View):base(View) { }

    protected override void mapBindings()//進(jìn)行綁定映射
    {
        //model    M
        injectionBinder.Bind<ScorgModel>().To<ScorgModel>().ToSingleton();
       
        //service   S
        injectionBinder.Bind<IScoreService>().To<ScireService>().ToSingleton();//ToSingleton表示這個(gè)對(duì)象只會(huì)在整個(gè)工程中生成一個(gè)


        //command    C
        commandBinder.Bind(Demo1CommandEvent.RequeestScore).To<RequestscoreCommand>();
        commandBinder.Bind(Demo1CommandEvent.UpdataScore).To<UpdataScoreCommand>();

        //mediator   V
        mediationBinder.Bind<CubeView>().To<CubeMediator>();//完成View和mediator的綁定


        //綁定開始事件  一個(gè)StartCommand  這個(gè)StartCommand會(huì)立即調(diào)用
        commandBinder.Bind(ContextEvent.START).To<StartCommand>().Once();//把哪個(gè)事件與自己的StartCommand綁定上
    }
}

首先是開始的命令

using strange.extensions.command.impl;

//開始命令
public class StartCommand : Command {


    /// <summary>
    ///重寫  當(dāng)這個(gè)命令被執(zhí)行的時(shí)候默認(rèn)會(huì)調(diào)用Execute方法
    /// </summary>
    public override void Execute()
    {
   
    }
}

接下來是視圖層的腳本顯示UI部分

using strange.extensions.dispatcher.eventdispatcher.api;
using strange.extensions.mediation.impl;
using UnityEngine;
using UnityEngine.UI;

public class CubeView : View {

    [Inject]
    public IEventDispatcher dispacher { get; set; }

    private Text scoreText;

    /// <summary>
    /// 做初始化
    /// </summary>
    public void Init() {
        scoreText =transform.Find("Canvas/ScoreText").GetComponent<Text>();
    }
    public void Update()
    {
        transform.Translate(new Vector3(Random.Range(-1,2), Random.Range(-1, 2), Random.Range(-1, 2))*.2f);
    }
    private void OnMouseDown()
    {
        //加分
        Debug.Log("OnMouDown");
        dispacher.Dispatch(Demo1MediatorEvent.ClickDown);
    }
    public void Updatescore(int score) {
        scoreText.text = score.ToString();
    }
}

接下來是視圖層通過View層 Mediator向Command發(fā)起分?jǐn)?shù)的請(qǐng)求

using strange.extensions.context.api;
using strange.extensions.dispatcher.eventdispatcher.api;
using strange.extensions.mediation.impl;


public class CubeMediator : Mediator {

    [Inject]//可以訪問到與自身綁定的 CubeView  完成注入的意思
    public CubeView cubeView { get; set; }

    [Inject(ContextKeys.CONTEXT_DISPATCHER)]//表示全局的派發(fā)器
    public IEventDispatcher dispatcher { get; set; }



    public override void OnRegister()//注冊(cè)  當(dāng)屬性都調(diào)用完成后就會(huì)去調(diào)用這個(gè)方法  在OnRegister里面可以訪問這些屬性
    {
        cubeView.Init();

        dispatcher.AddListener(Demo1MediatorEvent.ScoreChange, OnScoreChange);//監(jiān)聽注冊(cè)方法返回分?jǐn)?shù)
        cubeView.dispacher.AddListener(Demo1MediatorEvent.ClickDown,OnClickDown);

        //通過dispatcher發(fā)起請(qǐng)求分?jǐn)?shù)的命令
        dispatcher.Dispatch(Demo1CommandEvent.RequeestScore);

        base.OnRegister();
    }
    public override void OnRemove()//當(dāng)取消運(yùn)行的時(shí)候會(huì)調(diào)用這個(gè)   當(dāng)Mediator對(duì)應(yīng)的View的視圖被銷毀的時(shí)候會(huì)調(diào)用OnRemove
    {

        dispatcher.RemoveListener(Demo1MediatorEvent.ScoreChange, OnScoreChange);//移除監(jiān)聽
        cubeView.dispacher.RemoveListener(Demo1MediatorEvent.ClickDown, OnClickDown);
    }
    //將返回的分?jǐn)?shù)傳遞給View層
    public void OnScoreChange(IEvent evt) {
        cubeView.Updatescore((int)evt.data);
    }

    //加分
    public void OnClickDown()
    {
        dispatcher.Dispatch(Demo1CommandEvent.UpdataScore);
    }
}

下面是幾個(gè)發(fā)起請(qǐng)求需要的枚舉值,有CommandEvent、ServiceEvent、MediatorEvent。

public enum Demo1CommandEvent  {
       RequeestScore,
       UpdataScore
}

public enum Demo1ServiceEvent  {

RequestScore
}

public enum Demo1MediatorEvent
{
    ScoreChange,
    ClickDown
}

接下來就是Command層了,有請(qǐng)求分?jǐn)?shù)和更新分?jǐn)?shù)的命令,所以兩個(gè)Command

using strange.extensions.command.impl;
using strange.extensions.dispatcher.eventdispatcher.api;
using UnityEngine;

public class RequestscoreCommand : EventCommand {

    [Inject]
    public IScoreService scoreService { get; set; }
    [Inject]
    public ScorgModel scoreModel { get; set; }

    //[Inject(ContextKeys.CONTEXT_DISPATCHER)]//全局的dispatcher
    //public IEventDispatcher dispacher { get; set; }

    public override void Execute()//表示命名執(zhí)行的時(shí)候
    {
        Retain();//表示讓這個(gè)請(qǐng)求先不銷毀,等接收到數(shù)據(jù)后進(jìn)行釋放
        //添加監(jiān)聽器,監(jiān)聽OnComplete方法,第一個(gè)參數(shù)表示方法的事件枚舉類型, 第二個(gè)參數(shù)表示一個(gè)方法
        scoreService.dispatcher.AddListener(Demo1ServiceEvent.RequestScore, OnComplete);

        scoreService.RequestScore("http://xx/xx/xxx");
    }

    //這個(gè)方法表示當(dāng)scoreService請(qǐng)求分?jǐn)?shù)完成后就會(huì)調(diào)用這個(gè)方法去取得數(shù)據(jù)
    private void OnComplete(IEvent evt) {//IEvent存儲(chǔ)的就是參數(shù)

        Debug.Log("request score complete"+evt.data);
        scoreService.dispatcher.RemoveListener(Demo1ServiceEvent.RequestScore, OnComplete);//移除對(duì)OnComplete的監(jiān)聽
        scoreModel.score = (int)evt.data;
        dispatcher.Dispatch(Demo1MediatorEvent.ScoreChange, evt.data);

      

        Release();//釋放請(qǐng)求,銷毀當(dāng)前對(duì)象
    }
}
using strange.extensions.command.impl;

public class UpdataScoreCommand : EventCommand
{
    [Inject]
    public ScorgModel ScoreModel { get; set; }
    [Inject]
    public IScoreService scoreServer { get; set; }

    public override void Execute()
    {
        ScoreModel.score++;
        scoreServer.UpdateScore("http://xx/xx", ScoreModel.score);

        dispatcher.Dispatch(Demo1MediatorEvent.ScoreChange, ScoreModel.score);
    }

}

然后就是Servicevice層了,一個(gè)是接口,一個(gè)是實(shí)現(xiàn)接口的類

using strange.extensions.dispatcher.eventdispatcher.api;

public interface IScoreService  {

    void RequestScore(string url);//請(qǐng)求分?jǐn)?shù)

    void  OnReceiveScore();//收到服務(wù)器端發(fā)送的分?jǐn)?shù)

    void UpdateScore(string url, int Score);//更新分?jǐn)?shù)

    IEventDispatcher dispatcher { get; set; }
}

using strange.extensions.dispatcher.eventdispatcher.api;
using UnityEngine;

public class ScireService : IScoreService
{

    [Inject]
    public IEventDispatcher dispatcher { get; set; }


    public void RequestScore(string url)////請(qǐng)求分?jǐn)?shù)
    {
        Debug.Log("Request Score from url:" + url);
        OnReceiveScore();
    }

    public void  OnReceiveScore()////收到服務(wù)器端發(fā)送的分?jǐn)?shù)
    {
        int score = Random.Range(0, 100);
        dispatcher.Dispatch(Demo1ServiceEvent.RequestScore, score);//通過Demo1CommandEvent.RequeestScore這個(gè)事件將數(shù)據(jù)發(fā)送出去
    }
    public void UpdateScore(string url, int Score)//更新分?jǐn)?shù)
    {
        Debug.Log("Update score to url:"+url+"new score:"+Score);
    }
}


最后就是模型層,保存分分?jǐn)?shù),數(shù)據(jù)。

public class ScorgModel  {
    public int score { get; set; }
}

這樣就完成了,開始請(qǐng)求獲取一個(gè)初始分?jǐn)?shù),往后每點(diǎn)擊Cube一次數(shù)據(jù)就會(huì)更新一次數(shù)據(jù)+1。
1510050484(1).jpg

創(chuàng)建編輯器擴(kuò)展,用來添加需要的音效并用AudioManager管理起來

首先創(chuàng)建一個(gè)Editor文件夾,里面再創(chuàng)建一個(gè)編輯器擴(kuò)展類AudioWindowEditor用來創(chuàng)建一個(gè)音效添加的面板,并將音效的路徑內(nèi)容保存到Text文本里面存儲(chǔ)到Resources文件夾下,代碼如下

using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;

public class AudioWindowEditor : EditorWindow
{

    //創(chuàng)建自定義窗口
    [MenuItem("Manager/AudioManager")]
    static void CreateWindow()
    {
        AudioWindowEditor audio = EditorWindow.GetWindow<AudioWindowEditor>("音效管理");

        //Rect rect = new Rect(400, 400, 300, 300);
        //AudioWindowEditor audio = EditorWindow.GetWindowWithRect (typeof(AudioWindowEditor),rect)as AudioWindowEditor;
        audio.Show();
    }

    private string audioname;
    private string audiopath;
    private Dictionary<string, string> audioDict = new Dictionary<string, string>();//存儲(chǔ)音效路徑


    private void Awake()
    {
        LoadAudioList();
    }

    //OnGUI繪制
    private void OnGUI()
    {
        GUILayout.BeginHorizontal();
        GUILayout.Label("音效名稱");
        GUILayout.FlexibleSpace();
        GUILayout.Label("音效路徑");
        GUILayout.FlexibleSpace();
        GUILayout.Label("操作");
        EditorGUILayout.EndHorizontal();
        foreach (string key in audioDict.Keys)
        {
            string value;
            audioDict.TryGetValue(key, out value);
            GUILayout.BeginHorizontal();
            GUILayout.Label(key);
            GUILayout.FlexibleSpace();
            GUILayout.Label(value);
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("刪除", GUILayout.Width(100), GUILayout.Height(20)))
            {
                audioDict.Remove(key);
                SaveAudioList();
                return;
            }
            GUILayout.EndHorizontal();
        }

        audioname = EditorGUILayout.TextField("音效名字", audioname);
        audiopath = EditorGUILayout.TextField("音效路徑", audiopath);
        if (GUILayout.Button("添加音效"))
        {
            object o = Resources.Load(audiopath);//加載音效路徑
            if (o == null)
            {
                Debug.LogWarning("輸入的音效不存在于:" + audiopath + ",添加不成功");
                audiopath = "";
            }
            else
            {
                if (audioDict.ContainsKey(audioname))
                {

                    Debug.LogWarning("已添加成功,請(qǐng)勿重復(fù)添加");
                }
                else
                {
                    audioDict.Add(audioname, audiopath);
                    SaveAudioList();
                }
            }
        }
    }
    //窗口面板被更新時(shí)調(diào)用
    private void OnInspectorUpdate()
    {
        LoadAudioList();
    }

    //存儲(chǔ)成文本
    private void SaveAudioList()
    {
        StringBuilder sb = new StringBuilder();

        foreach (string key in audioDict.Keys)
        {
            string value;
            audioDict.TryGetValue(key, out value);
            sb.Append(key + "," + value + "\n");//組拼字符串
        }
        //AudioManager.AudioTextPath里面是創(chuàng)建并保存文本的路徑 第二個(gè)參數(shù)是保存內(nèi)容的路徑
        File.WriteAllText(AudioManager.AudioTextPath, sb.ToString());//可覆蓋之前內(nèi)容
        //File.AppendAllText(savePath,sb.ToString());
    }
    //讀取音效文本里面的內(nèi)容并加載到字典里面顯示到面版上
    private void LoadAudioList()
    {
        audioDict = new Dictionary<string, string>();
        if (File.Exists(AudioManager.AudioTextPath) == false) return;
        string[] lines = File.ReadAllLines(AudioManager.AudioTextPath);
        foreach (string line in lines)
        {
            if (string.IsNullOrEmpty(line)) continue;
            string[] keyvalue = line.Split(',');
            audioDict.Add(keyvalue[0], keyvalue[1]);
        }

    }
}

,這樣音效添加面板創(chuàng)建出來了并將其內(nèi)容保存到了Text文本里,然后再Scripts文件夾下創(chuàng)建音效管理腳本AudioManager,用來管理所有的音效,并寫入播放音效的方法,代碼下

using System.Collections.Generic;
using UnityEngine;

public class AudioManager
{

    private static string audioTextPathPrefix = Application.dataPath + "\\FrameworkAudio\\Resources\\";
    private const string audioTextPathMiddle = "audiolist";
    private const string audioTextPathPostfix = ".txt";


    public static string AudioTextPath
    {
        get
        {
            return audioTextPathPrefix + audioTextPathMiddle + audioTextPathPostfix;
        }
    }




    Dictionary<string, AudioClip> AudioClipDict = new Dictionary<string, AudioClip>();//存儲(chǔ)音效

    private bool IsMult = false;//是否靜音

    //public AudioManager()
    //{
    //    LoadAudioClip();
    //}

        //初始化
    public void Init()
    {

        LoadAudioClip();
    }
    //加載解析音效并保存到字典里
    private void LoadAudioClip()
    {
        AudioClipDict = new Dictionary<string, AudioClip>();
        TextAsset ta = Resources.Load<TextAsset>(audioTextPathMiddle);
        string[] lines = ta.text.Split('\n');

        foreach (string line in lines)
        {
            if (string.IsNullOrEmpty(line)) return;
            string[] keyvalue = line.Split(',');
            string key = keyvalue[0];
            AudioClip value = Resources.Load<AudioClip>(keyvalue[1]);
            AudioClipDict.Add(key, value);
        }
    }
    //播放音效
    public void playAudio(string name)
    {
        if (IsMult) return;
        AudioClip ac;
        AudioClipDict.TryGetValue(name, out ac);
        if (ac != null)
        {
            AudioSource.PlayClipAtPoint(ac, Vector3.zero);
        }
    }
    //有位置的音效播放
    public void playAudio(string name, Vector3 position)
    {
        if (IsMult) return;
        AudioClip ac;
        AudioClipDict.TryGetValue(name, out ac);
        if (ac != null)
        {
            AudioSource.PlayClipAtPoint(ac, position);
        }
    }
}

這樣就可以在面板里面創(chuàng)建音效并保存到文本里面,然后管理到了AudioManager里面,下次需要用的時(shí)候只需要添加路徑然后調(diào)用AudioManager里面的playAudio方法就可以播放音效了,非常方便


D`0DQ2.png

下面去框架里面使用下音效試下效果,首先去Demo1Cntext里面綁定我們的音效的管理類。


QERMSA.png
然后在調(diào)用開始命令StartCommand的時(shí)候去初始化就是讀取解析文本里面的音效內(nèi)容存儲(chǔ)到字典里,所以在StartCommand里面寫入
using strange.extensions.command.impl;

//開始命令
public class StartCommand : Command {

    [Inject]
    public AudioManager audioManager { get; set; }
    /// <summary>
    ///重寫  當(dāng)這個(gè)命令被執(zhí)行的時(shí)候默認(rèn)會(huì)調(diào)用Execute方法
    /// </summary>
    public override void Execute()
    {
        audioManager.Init();
    }
}

接下來我們就可以在每次點(diǎn)擊的時(shí)候使用文本里面的一個(gè)音效了,在視圖層CubeView的OnMouseDown方法里面,每次點(diǎn)擊Cube的時(shí)候調(diào)用一下音效管理里面的播放方法,把需要播放的音效名字輸入上去就OK了

    [Inject]
    public AudioManager audiomanger { get; set; }
  private void OnMouseDown()
    {
        //加分
        Debug.Log("OnMouDown");
        audiomanger.playAudio("Hit");
        dispacher.Dispatch(Demo1MediatorEvent.ClickDown);
    }

這樣就完成了一個(gè)音效的播放

PoolManager資源池

創(chuàng)建資源池,就好比子彈需要不斷的生成創(chuàng)建這樣會(huì)很耗費(fèi)性能,這時(shí)候我們就可以把子彈放到List集合里面,比如我們有十發(fā)子彈,在最開始的時(shí)候List會(huì)保存這十發(fā)子彈,后面這十發(fā)子彈是不會(huì)銷毀的,只需要把其SetActive設(shè)置成False就行,下次再生成子彈的時(shí)候只需要去List集合里面去取得自動(dòng)將其SetActive設(shè)置成True就行。這樣這些子彈就會(huì)不斷的循環(huán)利用。當(dāng)然不止子彈,或者其他的物體需要不停的創(chuàng)建的就可以使用PoolManager去管理,例如一些特效、NPC等等。

下面我來做一個(gè)簡單的池子,這里可以使用Unity里面的一個(gè)工具:使用定制資源配置文件
相關(guān)學(xué)習(xí)文檔:http://www.360doc.com/content/14/0323/13/12282510_363016017.shtml
首先創(chuàng)建GameobjectPool一個(gè)資源池里面寫入需要的屬性,讓其成為可序列化的

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

/// <summary>
/// 資源池  用來單獨(dú)編輯一個(gè)資源池
/// </summary>
[Serializable]//序列化  可以把這個(gè)類保存到本地文件
public class GameobjectPool  {

    [SerializeField]
    private  string name;//表示這個(gè)池子的名字
    [SerializeField]
    private  GameObject prefab;
    [SerializeField]
    private  int maxAmount;//池子最大可容納對(duì)象

    [NonSerialized]//不需要序列化
    private List<GameObject> goList = new List<GameObject>();

}

然后再創(chuàng)建一個(gè)資源管理器GameobjectPoolList

using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 管理所有的資源池
/// </summary>
public class GameobjectPoolList : ScriptableObject
{//表示把GameobjectPoolList變成可以自定義資源配置的文件

    public List<GameobjectPool> poolList;
}

接著創(chuàng)建一個(gè)編輯器類PoolManagerEditor,讓其可生成一個(gè)配置文件

using UnityEditor;
using UnityEngine;

public class PoolManagerEditor
{
    [MenuItem("Manager/Crate GameobjectPoolConfig")]
    static void CreateGameObjectPoolList()
    {
        GameobjectPoolList poolList =ScriptableObject.CreateInstance<GameobjectPoolList>();
        //創(chuàng)建一個(gè)資源,c參數(shù)一創(chuàng)建什么類型的資源,參數(shù)二 資源的路徑
        AssetDatabase.CreateAsset(poolList, "Assets/FrameworkAudio/Resources/gameobjectpool.asset");//gameobjectpool.property文件名+后綴
        AssetDatabase.SaveAssets();
    }
}

這樣我們只要一點(diǎn)擊打Manager下Crate GameobjectPoolConfig,就會(huì)在Resouces下生成一個(gè)資源配置文件,里面可以管理我們所有的資源池,這里我在里面創(chuàng)建了兩個(gè)資源池,一個(gè)子彈Bullet,一個(gè)特效HitEff,并設(shè)置了其屬性


W`HBTHRD%8L.png

下面再兩個(gè)Prefaba兩個(gè)添加禁用的腳本DeactiveForTime,讓其在三秒的時(shí)候禁用.

using UnityEngine;

public class DeactiveForTime : MonoBehaviour {

    private void OnEnable()
    {
        Invoke("Deactive", 3);//5秒后禁用 
    }
    void Deactive()
    {
        this.gameObject.SetActive(false);
    }
}

這樣在生成后的三秒就會(huì)禁用。
接著創(chuàng)建一個(gè)PoolManager腳本去解析gameobjectpool配置文件里面屬性,將里面所有的資源池放到Dictionary里面管理起來,需要用的時(shí)候只有根據(jù)PoolName就可以獲取到相應(yīng)的資源池了,所以在PoolManager腳本里面的代碼如下

using System.Collections.Generic;
using UnityEngine;

public class PoolManager : MonoBehaviour {

    private static PoolManager _instance;
    public static PoolManager Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new PoolManager();
            }
            return _instance;      
        }
    }

    private static string poolConfigPathPrefix = "Assets/FrameworkAudio/Resources/";
    private const string pooConfigPathMiddle = "gameobjectpool";
    private const string pooConfigPathPostfix = ".asset";


    public static string pooConfigPath
    {
        get
        {
            return poolConfigPathPrefix + pooConfigPathMiddle + pooConfigPathPostfix;
        }
    }
    private Dictionary<string, GameobjectPool> poolDict;
    private PoolManager()
    {
        GameobjectPoolList pooList = Resources.Load<GameobjectPoolList>(pooConfigPathMiddle);//加載資源池
        poolDict = new Dictionary<string, GameobjectPool>();
        foreach (GameobjectPool pool in pooList.poolList)
        {
            poolDict.Add(pool.name,pool);//將所有資源池里面的屬性存儲(chǔ)進(jìn)poolDict里面
        }
    }
    public void Init()
    {
        //Do nothing

    }
    public GameObject GetInstBullet(string poolName)
    {
        GameobjectPool pool;
        //判斷有沒有這個(gè)資源池
        if (poolDict.TryGetValue(poolName, out pool))
        {
            return pool.GetInstance();
        }
        Debug.LogWarning("Pool:"+poolName+"is not exits!!");
        return null;
    }

}

接下來去GameobjectPool里面寫入實(shí)例化的代碼,在GameobjectPool里面添加代碼

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

/// <summary>
/// 資源池  用來單獨(dú)編輯一個(gè)資源池
/// </summary>
[Serializable]//序列化  可以把這個(gè)類保存到本地文件
public class GameobjectPool  {


    public   string name;//表示這個(gè)池子的名字
    [SerializeField]
    private  GameObject prefab;
    [SerializeField]
    private  int maxAmount;//池子最大可容納對(duì)象


    [NonSerialized]//不需要序列化
    private List<GameObject> goList = new List<GameObject>();

    /// <summary>
    /// 表示從資源池中獲取一個(gè)實(shí)例
    /// </summary>
    public GameObject GetInstance()
    {
        foreach (GameObject go in goList)
        {
            //判斷里面的每個(gè)游戲?qū)ο笫欠駟⒂茫绻锩嬗袥]有啟用的表示這個(gè)游戲?qū)ο罂捎?返回當(dāng)前游戲?qū)ο?            if (go.activeInHierarchy == false)
            {
                go.SetActive(true);
                return go;
            }

        }
        //如果池子里的游戲?qū)ο蟠笥诨虻扔谖覀冃枰淖畲蟮娜萘?        if (goList.Count>=maxAmount )
        {
            //從集合里面銷毀一個(gè)
            GameObject.Destroy(goList[0]);
            goList.RemoveAt(0);
        }

        //如果池子里面既沒有可用的并且池子里還有容量那么就需要?jiǎng)?chuàng)建新的游戲?qū)ο罅?        GameObject temp=GameObject.Instantiate(prefab);
 
        goList.Add(temp);

        return temp;
    }
}

接下來我們就需要去框架里面應(yīng)用一下了,只需要在游戲的視圖層里面調(diào)用PoolManager里面的 GetInstBullet()方法,將需要的資源池PoolName傳遞上去就OK了。我這里在CubeView里面的Updata里面寫入以下代碼,讓每點(diǎn)擊一次就生產(chǎn)一個(gè)Bullet。

 if (Input.GetMouseButtonDown(0))
        {
            PoolManager.Instance.GetInstBullet("Bullet");
        }

這樣就完成了所有資源池的管理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容