您的位置:首页 > 移动开发 > Unity3D

unity中的特效管理器(特效缓存池)

2018-02-02 10:57 399 查看
游戏中普遍都有大量的特效,为了便于管理,写了一个简单的特效管理器。

此管理器用到了一个配置表管理器,之前的文章中有介绍,传送门

我们的配置文件的内容应该是这样:



这里是excel的样子,如果使用我前面提供的配置表管理器还需要把它转成xml格式。

此管理器借鉴了缓存池的设计思路,使用一个字典用来存放所有特效对象。在初始化此管理器时,会根据配置表中配置的同时存在数量来创建特效,并加入到缓存池中。

使用特效时,根据配置表中的id在缓存池中寻找空闲的特效,如果没有找到会新新创建一个。

下面是管理器的代码:

public class GameEffectManager {
//特效池
Dictionary<int ,List<GameEffect>> effectPool = new Dictionary<int ,List<GameEffect>>();

public GameEffectManager(){

//创建特效,加入到池里
List<conf_effect> _conf = ConfigManager.confEffectManager.datas;

for(int i = 0 ; i < _conf.Count ; i ++){
conf_effect conf = _conf[i];
for(int j = 0 ; j < conf.repeat_count ; j++){
CreateEffect(conf);
}
}
}

/// <summary>
/// 添加特效到世界
/// </summary>
/// <returns>The world effect.</returns>
/// <param name="effectid">配置表中的id.</param>
/// <param name="pos">出生位置.</param>
/// <param name="scale">特效的尺寸.</param>
public GameEffect AddWorldEffect(int effectid,Vector3 pos, float scale){
GameEffect ge = GetEffect(effectid,pos);
if(ge == null) return null;
ge.transform.position = pos;
ge.Play(scale);
return ge;
}

/// <summary>
/// 添加特效到指定物体
/// </summary>
/// <returns>The effect.</returns>
/// <param name="effectid">配置表中的id.</param>
/// <param name="obj">跟随物体,如果此物体不为空,特效会跟随此体移动,直到父物体变为null.</param>
/// <param name="pos">特效在obj中的相对坐标(偏移).</param>
/// <param name="scale">特效的尺寸.</param>
public GameEffect AddEffect(int effectid, GameObject obj, Vector3 pos, float scale){
if(obj == null){
return AddWorldEffect(effectid,pos,scale);
}
GameEffect ge = GetEffect(effectid,obj.transform.position + pos);
if(ge == null) return null;
ge.SetParent(obj);
ge.Play(scale);
return ge;
}

GameEffect GetEffect(int effectid ,Vector3 worldPos){
//对应池是否存在
if(!effectPool.ContainsKey(effectid)){
return null;
}

//寻找空闲特效
List<GameEffect> pool = effectPool[effectid];
GameEffect ret = null;
for(int i = 0 ; i < pool.Count ; i ++){
GameEffect eff = pool[i];

if(eff.gameObject.activeSelf){
continue;
}

ret = eff;
break;
}

//如果没有可用特效,则创建一个新的
if(ret == null){
conf_effect conf = ConfigManager.confEffectManager.GetData(effectid);
if(conf != null) ret = CreateEffect(conf);
}

return ret;
}

//添加一个特效到缓存池
GameEffect CreateEffect(conf_effect effect){
Object obj = Resources.Load(effect.file_path);
if(obj == null){
Debug.LogError("cant find file ! : " + effect.file_path);
}
if(effect.res_type == 1){
GameObject go = (GameObject)MonoBehaviour.Instantiate(obj);

GameEffect ge = go.AddComponent<GameEffect>();
ge.Init(effect);

if (!effectPool.ContainsKey(effect.id))
{
effectPool.Add(effect.id, new List<GameEffect>());
}
effectPool[effect.id].Add(ge);

return ge;
}
return null;
}

}

这里只对外提供了2个创建特效的方法,一种是添加到世界的特效,特效播放完即隐藏,另一种是跟随父物体的特效,特效会一直存在直到父物体消失。
这里在创建特效时还会自动赋给特效一个脚本,来控制特效自身的逻辑,该脚本的代码如下:

public class GameEffect : MonoBehaviour {
//配置文件
public conf_effect conf{get;private set;}
//粒子系统
ParticleSystem ps ;
//播放时间
float playTime;
//跟随物体,如果此物体不为空,特效会跟随父物体移动,直到父物体变为null
public GameObject parent;

public void Init(conf_effect conf){
this.conf = conf;
ps = transform.GetComponent<ParticleSystem>();
gameObject.SetActive(false);
}

public void Play(float scale){
playTime = 0;

gameObject.SetActive(true);

ps.Play();

SetScale(transform, scale);
}

public void SetScale(Transform t, float scale){
for (int i = 0; i < t.childCount; i ++){
SetScale(t.GetChild(i),scale);
}
t.localScale = new Vector3(scale, scale, scale);
}

void Update(){
playTime += Time.deltaTime;
if (parent != null)
{
transform.position = parent.transform.position;
return;
}

if(playTime > ps.main.duration){
Die();
}
}

public void SetParent(GameObject obj){
this.parent = obj;
}

public void Die(){
gameObject.SetActive(false);

}

void OnDestroy(){
}
}


使用方法

游戏开始时我们需要先创建管理器:

GameEffectManager gameEffectManager = new GameEffectManager();我们只需要调用创建方法就可以使用特效了:
gameEffectManager.AddEffect(60010010,ojb,pos,1.0);
这样我们不用关心特效的创建和消失的细节,使用起来还是很方便的。在实际的项目开发中,可能还需要根据项目的不同需求进行一些修改。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  unity 特效 管理器