|
@@ -0,0 +1,219 @@
|
|
|
+using CommonAI.Zone;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using CommonAI.ZoneClient;
|
|
|
+using UnityEngine;
|
|
|
+using System.Text.RegularExpressions;
|
|
|
+using CommonLang;
|
|
|
+using Sirenix.Utilities;
|
|
|
+using ET.EventType;
|
|
|
+
|
|
|
+namespace ET.Client
|
|
|
+{
|
|
|
+
|
|
|
+ [Event(SceneType.None)]
|
|
|
+ public class PlayEffectEventHandler : BEvent<EventType.PlayEffectEvent>
|
|
|
+ {
|
|
|
+ private static Vector3 vecTemp = new();
|
|
|
+ public override void OnEvent(PlayEffectEvent args)
|
|
|
+ {
|
|
|
+ vecTemp.Set(args.Pos.X, args.Pos.Y, args.Pos.Z);
|
|
|
+ EffectMgr.Instance.PlayEffect(args.Effect, args.HostId, vecTemp, args.Time, args.Rotation).Coroutine();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class EffectMgr : Singleton<EffectMgr>, ISingletonAwake, ISingletonUpdate
|
|
|
+ {
|
|
|
+ private HashMap<uint, EffectPlayInfo> playingList = new();
|
|
|
+ private HashMap<string, List<GameObject>> effectPool = new();
|
|
|
+ private static Vector3 vecTemp = new();
|
|
|
+
|
|
|
+ public void Awake()
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Update()
|
|
|
+ {
|
|
|
+ var now = Time.realtimeSinceStartup;
|
|
|
+ foreach (var epi in playingList.Values)
|
|
|
+ {
|
|
|
+ if (epi.EndTime >= now)
|
|
|
+ {
|
|
|
+ playingList.Remove(epi.Id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public async ETTask<uint> PlayEffect(LaunchEffect effect, uint HostId, Vector3 pos, float time = 0f, float rotation = 0f)
|
|
|
+ {
|
|
|
+ var starttime = Time.realtimeSinceStartup;
|
|
|
+
|
|
|
+ GameObject go = null;
|
|
|
+ if (!effect.Name.IsNullOrWhitespace())
|
|
|
+ {
|
|
|
+ go = await loadEffect(effect.Name);
|
|
|
+ UnitRenderComponet render = null;
|
|
|
+ if (effect.BindBody)
|
|
|
+ {
|
|
|
+ render = ModelViewComponent.Instance.GetChild<UnitRenderComponet>(HostId);
|
|
|
+ if (render == null)
|
|
|
+ {
|
|
|
+ Log.Debug($"ignore unit effect: {effect.Name}@{HostId}, cause of No Render");
|
|
|
+ recycleEffect(go);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var timeComponent = go.GetComponent<EffectTime>();
|
|
|
+ if (time == 0f) time = timeComponent.duration;
|
|
|
+ if (time < 0f) time = EffectPlayInfo.TIME_FOREVER;
|
|
|
+ setupEffect(go, effect, render, pos, rotation);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (effect.EarthQuakeMS > 0)
|
|
|
+ {
|
|
|
+ vecTemp.Set(effect.EarthQuakeXYZ, effect.EarthQuakeXYZ, effect.EarthQuakeXYZ);
|
|
|
+ CameraMgr.ShakeMe(effect.EarthQuakeMS, vecTemp);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!effect.SoundName.IsNullOrWhitespace())
|
|
|
+ {
|
|
|
+ //TODO: Sound
|
|
|
+ }
|
|
|
+
|
|
|
+ var epi = ObjectPool.Instance.Fetch<EffectPlayInfo>();
|
|
|
+ epi.Reset(go, starttime + time);
|
|
|
+ playingList.Add(epi.Id, epi);
|
|
|
+ return epi.Id;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setupEffect(GameObject go, LaunchEffect effectData, UnitRenderComponet render, Vector3 pos, float rotation)
|
|
|
+ {
|
|
|
+ var gt = go.transform;
|
|
|
+
|
|
|
+ if (effectData.BindBody)
|
|
|
+ {
|
|
|
+ if (!effectData.BindPartName.IsNullOrWhitespace())
|
|
|
+ {
|
|
|
+ gt.parent = render.GetBindPart(effectData.BindPartName);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ gt.parent = render.GameObject.transform;
|
|
|
+ }
|
|
|
+ vecTemp.Set(effectData.EffectOffsetX, 0, effectData.EffectOffsetY);
|
|
|
+ gt.localPosition = vecTemp;
|
|
|
+ if (effectData.Tag == "FixStartRotaion")
|
|
|
+ {
|
|
|
+ gt.rotation = Quaternion.Euler(0, 90, 0);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ gt.localRotation = Quaternion.identity;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ gt.parent = GlobalViewComponent.Instance.Unit;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pos != Vector3.zero)
|
|
|
+ {
|
|
|
+ vecTemp.Set(effectData.EffectOffsetX, effectData.EffectHight, effectData.EffectOffsetY);
|
|
|
+ gt.position = pos + vecTemp;
|
|
|
+ }
|
|
|
+ if (rotation != 0)
|
|
|
+ {
|
|
|
+ gt.rotation = Quaternion.Euler(0, rotation * Mathf.Rad2Deg + 90, 0);
|
|
|
+ }
|
|
|
+ var scale = effectData.ScaleToBodySize != 0 ? effectData.ScaleToBodySize : 1f;
|
|
|
+ gt.localScale = new Vector3(scale, scale, scale);
|
|
|
+
|
|
|
+ if (!string.IsNullOrEmpty(effectData.Tag))
|
|
|
+ {
|
|
|
+ //Effect支持Tag设置Event,格式:Event:事件名(事件参数)
|
|
|
+ Match m = Regex.Match(effectData.Tag, @"^Event:(\w+)\((.*)\)");
|
|
|
+ if (m.Groups.Count >= 3)
|
|
|
+ {
|
|
|
+ string eventName = m.Groups[1].Value;
|
|
|
+ string eventParam = m.Groups[2].Value;
|
|
|
+ if (!string.IsNullOrEmpty(eventName))
|
|
|
+ {
|
|
|
+ Log.Error("Not support: Effect({0}) Triggle event:{1}", effectData.Name, effectData.Tag);
|
|
|
+ /*EventManager.Fire("Event." + eventName, new Dictionary<string, object>()
|
|
|
+ {
|
|
|
+ {"param", eventParam},
|
|
|
+ {"position", gt.position}
|
|
|
+ });*/
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Clear()
|
|
|
+ {
|
|
|
+ foreach (var epi in playingList.Values)
|
|
|
+ {
|
|
|
+ GameObject.Destroy(epi.GameObj);
|
|
|
+ }
|
|
|
+ playingList.Clear();
|
|
|
+
|
|
|
+ foreach (var list in effectPool.Values)
|
|
|
+ {
|
|
|
+ foreach (var go in list)
|
|
|
+ {
|
|
|
+ GameObject.Destroy(go);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ effectPool.Clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void RemoveEffect(uint id)
|
|
|
+ {
|
|
|
+ if (playingList.ContainsKey(id))
|
|
|
+ {
|
|
|
+ var info = playingList[id];
|
|
|
+ playingList.Remove(id);
|
|
|
+ recycleEffect(info.GameObj);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private async ETTask<GameObject> loadEffect(string prefabName)
|
|
|
+ {
|
|
|
+ if (effectPool.TryGetValue(prefabName, out var golist))
|
|
|
+ {
|
|
|
+ if (golist.Count > 0)
|
|
|
+ {
|
|
|
+ var gobj = golist[0];
|
|
|
+ golist.RemoveRange(0, 1);
|
|
|
+ return gobj;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ effectPool.Add(prefabName, new List<GameObject>());
|
|
|
+ }
|
|
|
+
|
|
|
+ var handle = await YooAssetProxy.LoadAssetAsync<GameObject>($"Effect_{prefabName}");
|
|
|
+ var prefab = handle.GetAssetObject<GameObject>();
|
|
|
+ var gameobj = UnityEngine.Object.Instantiate(prefab, GlobalViewComponent.Instance.Unit, true);
|
|
|
+ gameobj.name = prefabName;
|
|
|
+ return gameobj;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void recycleEffect(GameObject go)
|
|
|
+ {
|
|
|
+ go.SetActive(false);
|
|
|
+ go.transform.SetParent(GlobalViewComponent.Instance.RecycleNode, false);
|
|
|
+ var name = go.name;
|
|
|
+ if (effectPool.TryGetValue(name, out var golist))
|
|
|
+ {
|
|
|
+ golist.Add(go);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ effectPool.Add(name, new List<GameObject>() { go });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|