2
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
8.1 KiB
C#

2 years ago
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Game
{
public class EffectPoolItem : ObjectPoolItemBase
{
public GameObject GameObject;
public List<ParticleSystem> ParticleList = new List<ParticleSystem>();
public float DurationMax;
private int _effectCount;
private int _effectCountMax;
private bool _isLoop;
protected override void OnDestroy()
{
base.OnDestroy();
GameObject.transform.position = new Vector3(-100, 0, -100);
GameObject.transform.SetParent(EffectPoolManager.Instance.Root.transform);
}
public void Init(GameObject effectGo)
{
var particles = effectGo.GetComponentsInChildren<ParticleSystem>();
var effectNum = 0;
foreach (var particle in particles)
{
var renderer = particle.GetComponent<ParticleSystemRenderer>();
if (!renderer.enabled) continue;
if (particle.main.loop) _isLoop = true;
var listener = particle.gameObject.AddComponent<EffectListener>();
listener.SetPoolItem(this);
var main = particle.main;
var duration = main.duration + main.startDelay.constantMax;
if (duration > DurationMax) DurationMax = duration;
ParticleList.Add(particle);
effectNum++;
}
_effectCountMax += effectNum;
_effectCount = _effectCountMax;
}
public void Play()
{
foreach (var item in ParticleList) item.Play();
_effectCount = _effectCountMax;
}
public void EffectStopped()
{
_effectCount--;
if (_effectCount <= 0) Destroy();
}
/// <summary>
/// 销毁特效,区别于直接入池,如果是循环特效直接入池,否则只解绑,等待生命周期结束
/// </summary>
public void EffectDestroy()
{
if (_isLoop) Destroy();
GameObject.transform.SetParent(EffectPoolManager.Instance.Root.transform);
}
}
public class EffectPoolManager : ObjectPoolBase<EffectPoolManager>
{
private const string EffectPath = "Effect/";
public override void OnCreate()
{
CastShadowPoolManager.Create();
}
public override void Update()
{
CastShadowPoolManager.Instance.Update();
}
public override void OnDestroy()
{
CastShadowPoolManager.Instance.OnDestroy();
}
private void CreateEffectReal(EffectPoolItem item, Vector3 pos, float rot = 0, int targetEntity = 0,
double duration = 0, bool isAttach = false)
{
var go = item.GameObject;
var scale = Vector3.one;
//跟随实体移动
if (targetEntity != 0 && isAttach)
Util.TryGetEntity(targetEntity, entity =>
{
go.transform.parent = entity.view.TransformViewOther;
scale = entity.view.TransformViewMain.localScale;
if (scale.x == -1) rot -= 180;
});
else
go.transform.parent = Root.transform;
//跟随实体暂停/销毁
if (targetEntity != 0) Util.TryGetEntity(targetEntity, entity => { entity.view.EffectObject.Add(item); });
go.transform.localRotation = Quaternion.AngleAxis(-rot, Vector3.up);
go.transform.position = pos;
//镜像翻转
foreach (var particle in item.ParticleList)
{
var shape = particle.shape;
if (shape.enabled)
shape.scale = scale;
else
particle.transform.localScale = scale;
}
var timeScale = 1f;
if (duration > 0)
{
timeScale = item.DurationMax / (float)duration;
}
foreach (var particle in item.ParticleList)
{
var particleMain = particle.main;
particleMain.simulationSpeed = timeScale;
}
item.Play();
}
public void CreateEffect(GameObject goModule, Vector3 pos, float rot = 0, int targetEntity = 0,
double duration = 0, bool isAttach = false)
{
var effectNew = Create<EffectPoolItem>(goModule, item =>
{
var go = CreateEffectGo(goModule);
item.GameObject = go;
item.Init(go);
});
CreateEffectReal(effectNew, pos, rot, targetEntity, duration, isAttach);
}
public void CreateEffect(string effectId, Vector3 pos, float rot = 0, int targetEntity = 0,
double duration = 0, bool isAttach = false)
{
var effectNew = Create<EffectPoolItem>($"Effect{effectId}", item =>
{
var go = CreateEffectGo(effectId);
item.GameObject = go;
item.Init(go);
});
CreateEffectReal(effectNew, pos, rot, targetEntity, duration, isAttach);
}
private GameObject CreateEffectGo(GameObject goModule)
{
return PrefabManager.Instance.CreateGo(goModule);
}
private GameObject CreateEffectGo(string effectId)
{
var path = $"{EffectPath}{effectId}";
return PrefabManager.Instance.CreateGo(path);
}
}
}
namespace Game
{
public abstract partial class Util
{
// 播放跟随实体的特效
private static void CastFollowEffect(string effectId, int targetEntity, float rot = 0)
{
TryGetEntity(targetEntity, entity =>
{
var pos = entity.PosView();
CastEffect(effectId, pos, rot, targetEntity, 0, true);
});
}
// 受击特效:跟随实体暂停/销毁 但是不跟随移动
public static void CastHitEffect(string effectId, int targetEntity, float rot = 0)
{
TryGetEntity(targetEntity, entity =>
{
var pos = entity.PosView();
CastEffect(effectId, pos, rot, targetEntity, 0, false);
});
}
// 地面特效:在实体对应地面播放,跟随实体暂停/销毁 但是不跟随移动
public static void CastGroundStaticEffect(string effectId, int targetEntity, float rot = 0)
{
TryGetEntity(targetEntity, entity =>
{
var pos = entity.PosGround() + Vector3.up * 0.0001f;
CastEffect(effectId, pos, rot, targetEntity, 0, false);
});
}
// 墙面特效:在实体对应地面播放,跟随实体暂停/销毁 但是不跟随移动
public static void CastWallStaticEffect(string effectId, int targetEntity, Vector3 pos, Vector3 normal)
{
2 years ago
var rot = Util.Vec3ToRot(normal);
2 years ago
CastEffect(effectId, pos, rot, targetEntity, 0, false);
}
private static void CastEffect(string effectId, Vector3 pos, float rot, int targetEntity, double duration,
bool isAttach)
{
try
{
EffectPoolManager.Instance.CreateEffect(effectId, pos, rot, targetEntity, duration, isAttach);
}
catch (Exception e)
{
Print("特效释放失败:", effectId, targetEntity);
Print(e.StackTrace);
}
}
public static void CastEffect(GameObject goModule, Vector3 pos, float rot = 0, int targetEntity = 0,
double duration = 0, bool isAttach = false)
{
EffectPoolManager.Instance.CreateEffect(goModule, pos, rot, targetEntity, duration, isAttach);
}
}
}