2025-07-08 10:46:31 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using Superlazy;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
public class EffectView : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
private static readonly Queue<EffectView> unused = new Queue<EffectView>();
|
|
|
|
|
private static readonly Dictionary<string, EffectView> used = new Dictionary<string, EffectView>();
|
|
|
|
|
private static Transform unusedRoot;
|
|
|
|
|
|
|
|
|
|
public static void InitGlobal()
|
|
|
|
|
{
|
|
|
|
|
unusedRoot = new GameObject("UnusedEffectView").transform;
|
|
|
|
|
unusedRoot.gameObject.SetActive(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static EffectView MakeUnitEffect(UnitView unit, string effectName, SLEntity effectContext)
|
|
|
|
|
{
|
|
|
|
|
var instance = GetEffect(effectName);
|
|
|
|
|
instance.transform.SetParent(unit.Zone.Root, false);
|
|
|
|
|
|
|
|
|
|
//// TODO: 추후 개선이 가능할지 모르겠지만 이펙트뷰 레벨에서 유닛을 가져다 쓰는게 맞는지 고민
|
|
|
|
|
//if (effectContext["CellEffect"])
|
|
|
|
|
//{
|
|
|
|
|
// instance.transform.position = unit.Position.ToEntity().PositionToCell().CellToPosition().ToVector3();
|
|
|
|
|
//}
|
|
|
|
|
//else
|
|
|
|
|
{
|
|
|
|
|
instance.transform.position = unit.Position;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
instance.transform.rotation = unit.Rotation;
|
|
|
|
|
instance.transform.localScale = unit.EffectScale;
|
|
|
|
|
instance.OnStart(effectContext.Override(), unit.Zone, unit);
|
|
|
|
|
|
|
|
|
|
instance.gameObject.SetActive(true);
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static EffectView MakeEffect(IZoneView zone, string effectName, SLEntity effectContext/*, IWorld world*/, Vector3 position, Quaternion rotation, Vector3 scale)
|
|
|
|
|
{
|
|
|
|
|
var instance = GetEffect(effectName);
|
|
|
|
|
instance.transform.SetParent(zone.Root, false);
|
|
|
|
|
instance.transform.SetPositionAndRotation(position, rotation);
|
|
|
|
|
instance.transform.localScale = scale;
|
|
|
|
|
instance.OnStart(effectContext.Override(), zone, null);
|
|
|
|
|
|
|
|
|
|
instance.gameObject.SetActive(true);
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static EffectView GetEffect(string effectName)
|
|
|
|
|
{
|
|
|
|
|
EffectView newEffect;
|
|
|
|
|
if (unused != null && unused.Count != 0)
|
|
|
|
|
{
|
|
|
|
|
newEffect = unused.Dequeue();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var newObject = new GameObject();
|
|
|
|
|
newObject.SetActive(false);
|
|
|
|
|
newEffect = newObject.AddComponent<EffectView>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (newEffect.baseRoot == null)
|
|
|
|
|
{
|
|
|
|
|
newEffect.baseRoot = SLResources.CreateInstance(effectName, newEffect.gameObject.transform);
|
|
|
|
|
newEffect.Init();
|
|
|
|
|
}
|
|
|
|
|
newEffect.baseRoot.gameObject.SetActive(true);
|
|
|
|
|
newEffect.gameObject.name = effectName;
|
|
|
|
|
return newEffect;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void ClearEffect()
|
|
|
|
|
{
|
|
|
|
|
foreach (var key in used.Keys.ToList())
|
|
|
|
|
{
|
|
|
|
|
used[key].EndEffect(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
used.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void RemoveEffect(string effectID)
|
|
|
|
|
{
|
|
|
|
|
if (used.ContainsKey(effectID))
|
|
|
|
|
{
|
|
|
|
|
used[effectID].EndEffect();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private SLResourceObject baseRoot;
|
|
|
|
|
private SLEntity context;
|
|
|
|
|
private UnitView unit;
|
|
|
|
|
private Vector3 offset;
|
|
|
|
|
private Vector3 rotationOffset;
|
|
|
|
|
|
|
|
|
|
private Animator[] anims;
|
|
|
|
|
private Renderer[] renderers;
|
|
|
|
|
private ParticleSystem[] particles;
|
|
|
|
|
private TrailRenderer[] trails;
|
|
|
|
|
private Transform bindTransform;
|
|
|
|
|
|
|
|
|
|
private void Init()
|
|
|
|
|
{
|
|
|
|
|
anims = GetComponentsInChildren<Animator>();
|
|
|
|
|
renderers = GetComponentsInChildren<Renderer>();
|
|
|
|
|
particles = GetComponentsInChildren<ParticleSystem>();
|
|
|
|
|
trails = GetComponentsInChildren<TrailRenderer>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void EndEffect(bool force = false)
|
|
|
|
|
{
|
|
|
|
|
if (gameObject.activeSelf == false)
|
|
|
|
|
{
|
|
|
|
|
SLLog.Error($"Already Destroy Effect {context["EffectID"]}");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bindTransform = null;
|
|
|
|
|
|
|
|
|
|
if (used.ContainsKey(context["EffectID"]))
|
|
|
|
|
{
|
|
|
|
|
used.Remove(context["EffectID"]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (unusedRoot)
|
|
|
|
|
{
|
|
|
|
|
transform.localScale = Vector3.one;
|
|
|
|
|
baseRoot.Destroy(force);
|
|
|
|
|
baseRoot = null;
|
|
|
|
|
gameObject.SetActive(false);
|
|
|
|
|
unused.Enqueue(this);
|
|
|
|
|
transform.SetParent(unusedRoot);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Destroy(gameObject);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnStart(SLEntity context, IZoneView zone, UnitView unit)
|
|
|
|
|
{
|
|
|
|
|
this.context = context.Override();
|
|
|
|
|
this.unit = unit;
|
|
|
|
|
|
|
|
|
|
if (this.context["Scale"] != false)
|
|
|
|
|
{
|
|
|
|
|
transform.localScale *= this.context["Scale"];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.context["ForceY"])
|
|
|
|
|
{
|
|
|
|
|
transform.Translate(0, -transform.localPosition.y + context["ForceY"], 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.context["ForceRotate"])
|
|
|
|
|
{
|
|
|
|
|
transform.localRotation = Quaternion.Euler(this.context["ForceRotate"].ToVector3());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
offset = this.context["Offset"].ToVector3() * transform.localScale.x;
|
|
|
|
|
|
|
|
|
|
rotationOffset = this.context["RotationOffset"].ToVector3();
|
|
|
|
|
|
|
|
|
|
if (unit != null)
|
|
|
|
|
{
|
|
|
|
|
if (context["Bind"]["Height"])
|
|
|
|
|
{
|
|
|
|
|
enabled = true;
|
|
|
|
|
|
|
|
|
|
var bindHeight = unit.Entity[context["Bind"]["Height"]];
|
|
|
|
|
offset += Vector3.up * bindHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context["Bind"]["Part"])
|
|
|
|
|
{
|
|
|
|
|
enabled = true;
|
|
|
|
|
var part = unit.Entity[context["Bind"]["Part"]];
|
|
|
|
|
bindTransform = unit.transform.GetComponentsInChildren<Transform>().FirstOrDefault(t => t.name == part["Transform"]);
|
|
|
|
|
offset += part["Offset"].ToVector3();
|
|
|
|
|
transform.localScale *= part["Scale"];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context["Bind"]["Transform"])
|
|
|
|
|
{
|
|
|
|
|
enabled = true;
|
|
|
|
|
bindTransform = unit.transform.GetComponentsInChildren<Transform>().FirstOrDefault(t => t.name == context["Bind"]["Transform"]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context["Bind"]["ShadowScale"])
|
|
|
|
|
{
|
|
|
|
|
enabled = true;
|
|
|
|
|
|
|
|
|
|
var scaleDelta = unit.Entity["ShadowRadius"] / SLSystem.Data["Default"]["DefaultShadowScale"];
|
|
|
|
|
transform.localScale *= scaleDelta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bindTransform == null)
|
|
|
|
|
{
|
|
|
|
|
bindTransform = unit.transform.Find("OffsetRoot");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var r in renderers)
|
|
|
|
|
{
|
|
|
|
|
r.gameObject.layer = unit.Zone.Layer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var p in particles)
|
|
|
|
|
{
|
|
|
|
|
p.gameObject.layer = unit.Zone.Layer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var t in trails)
|
|
|
|
|
{
|
|
|
|
|
t.gameObject.layer = unit.Zone.Layer;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
transform.Translate(offset, Space.Self);
|
|
|
|
|
transform.Rotate(rotationOffset, Space.Self);
|
|
|
|
|
|
|
|
|
|
foreach (var p in particles)
|
|
|
|
|
{
|
|
|
|
|
p.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var t in trails)
|
|
|
|
|
{
|
|
|
|
|
t.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context["EffectID"] == false)
|
|
|
|
|
{
|
|
|
|
|
context["EffectID"] = context["Effect"];
|
|
|
|
|
var index = 1;
|
|
|
|
|
while (used.ContainsKey(context["EffectID"]))
|
|
|
|
|
{
|
|
|
|
|
context["EffectID"] = context["Effect"].ToString() + index;
|
|
|
|
|
++index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
used.Add(context["EffectID"], this);
|
|
|
|
|
|
|
|
|
|
//string layer = "Default";
|
|
|
|
|
//if (this.context["Layer"])
|
|
|
|
|
//{
|
|
|
|
|
// layer = this.context["Layer"];
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
//gameObject.SetLayerRecursively(layer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Update()
|
|
|
|
|
{
|
|
|
|
|
if (unit != null)
|
|
|
|
|
{
|
|
|
|
|
if (unit.isActiveAndEnabled == false)
|
|
|
|
|
{
|
|
|
|
|
EndEffect();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context["Bind"]["TopPosition"])
|
|
|
|
|
{
|
|
|
|
|
transform.position = unit.Entity["TopPosition"].ToVector3();
|
|
|
|
|
transform.Translate(offset, Space.Self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context["Bind"]["Position"])
|
|
|
|
|
{
|
|
|
|
|
transform.position = bindTransform.position;
|
|
|
|
|
transform.Translate(offset, Space.Self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context["Bind"]["Rotation"])
|
|
|
|
|
{
|
|
|
|
|
transform.rotation = bindTransform.rotation;
|
|
|
|
|
transform.Rotate(rotationOffset, Space.Self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (unit.Entity["ActionSpeed"])
|
|
|
|
|
{
|
|
|
|
|
foreach (var particle in particles)
|
|
|
|
|
{
|
|
|
|
|
var particleMain = particle.main;
|
|
|
|
|
particleMain.simulationSpeed = unit.Entity["ActionSpeed"];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context["Duration"])
|
|
|
|
|
{
|
|
|
|
|
context["Duration"] -= Time.deltaTime;
|
|
|
|
|
if (context["Duration"] <= 0)
|
|
|
|
|
{
|
|
|
|
|
EndEffect();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context["End"])
|
|
|
|
|
{
|
|
|
|
|
EndEffect();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context["Loop"]) return; // 자연종료 안한다
|
|
|
|
|
|
|
|
|
|
foreach (var animator in anims)
|
|
|
|
|
{
|
|
|
|
|
if (animator.GetCurrentAnimatorStateInfo(0).loop || animator.GetCurrentAnimatorStateInfo(0).normalizedTime < 1.0f)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var particle in particles)
|
|
|
|
|
{
|
|
|
|
|
if (particle.isPlaying)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EndEffect();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void NoUsePool()
|
|
|
|
|
{
|
|
|
|
|
Destroy(unusedRoot.gameObject);
|
|
|
|
|
}
|
|
|
|
|
}
|