using CommonAI.Zone; using UnityEngine; using System.Text.RegularExpressions; using CommonLang; using Sirenix.Utilities; using ET.EventType; using System.Collections.Generic; using System; namespace ET.Client { [Event] public class PlayEffectEventHandler : BEvent<EventType.PlayEffectEvent> { private static Vector3 vecTemp = new(); protected override async ETTask OnEvent(PlayEffectEvent args) { vecTemp.Set(args.Pos.X, args.Pos.Y, args.Pos.Z); EffectMgr.Instance.PlayEffect(args.Effect, args.HostId, vecTemp, args.Rotation).Coroutine(); var tag = args.Effect.Tag; if (!tag.IsNullOrWhitespace()) { ProcessLauncheffectTag(args.HostId, args.Effect.Tag).Coroutine(); } await ETTask.CompletedTask; } public async ETTask ProcessLauncheffectTag(uint objectid, string tag) { //Effect支持Tag设置Event,格式:Event:事件名(事件参数) Match m = Regex.Match(tag, @"^@(\w+)\(([\w\d\s_,]+)\)"); if (m.Groups.Count >= 3) { string name = m.Groups[1].Value; string param = m.Groups[2].Value; switch (name) { case "ChangeMode": var ps = param.Split(','); if (ps.Length > 1) { try { var delay = Convert.ToInt32(ps[1]); await TimerComponent.Instance.WaitAsync(delay); EventSystem.Instance.Publish(ChangeModeEvent.Static.Clone(objectid, ps[0])); } catch { Log.Error($"effect tag param error: {tag}"); } } else { EventSystem.Instance.Publish(ChangeModeEvent.Static.Clone(objectid, param)); } return; default: Log.Error($"effect unknow tag: {tag}"); return; } } Log.Error($"effect illegal tag: {tag}"); /*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 class EffectMgr : Singleton<EffectMgr>, ISingletonUpdate { private HashMap<uint, EffectPlayInfo> playingList = new(); private static Vector3 vecTemp = new(); private List<uint> listTemp = new(); public void Update(int timeMS) { listTemp.Clear(); var now = Time.realtimeSinceStartup; foreach (var epi in playingList.Values) { if (epi.EndTime <= now) { listTemp.Add(epi.Id); } } foreach(var id in listTemp) { RemoveEffect(id); } } public async ETTask<uint> PlayEffect(LaunchEffect effect, uint HostId, Vector3 pos, float rotation = 0f) { var starttime = Time.realtimeSinceStartup; float time = EffectPlayInfo.TIME_DEFAULT; GameObject go = null; if (!effect.Name.IsNullOrWhitespace()) { 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"); return 0; } } else if(pos == Vector3.zero) { var unit = UnitMgr.Instance.GetUnit(HostId); if(unit != null) { var zu = unit.ZoneObject; pos.Set(zu.X, zu.Y, zu.Z); } } go = await GameObjectPool.Instance.Acquire("Effect_" + effect.Name); if (effect.EffectTimeMS > 0) { time = effect.EffectTimeMS / 1000.0f; } else if (effect.EffectTimeMS < 0) { time = EffectPlayInfo.TIME_FOREVER; } else { var timeComponent = go.GetComponent<EffectTime>(); if (timeComponent != null && timeComponent.duration > 0) { time = timeComponent.duration; } } setupEffect(go, effect, render, pos, rotation); } else if(!effect.SoundName.IsNullOrWhitespace()) { //TODO: 音效的位置这里还有一堆逻辑的 SoundManager.Instance.Play3DSound(effect.SoundName, pos).Coroutine(); } if (effect.EarthQuakeMS > 0) { vecTemp.Set(effect.EarthQuakeXYZ, effect.EarthQuakeXYZ, effect.EarthQuakeXYZ); CameraMgr.ShakeMe(effect.EarthQuakeMS /1000.0f, vecTemp); } if (go != null) { var epi = ObjectPool.Instance.Fetch<EffectPlayInfo>(); epi.Reset(go, starttime + time); playingList.Add(epi.Id, epi); return epi.Id; } return 0; } 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, effectData.EffectHight, effectData.EffectOffsetY); gt.localPosition = vecTemp; if (effectData.Tag == "FixStartRotaion") { gt.rotation = RenderUtils.UnityRotationFromBattle(0); } else { gt.localRotation = Quaternion.identity; } } else { gt.rotation = RenderUtils.UnityRotationFromBattle(0); gt.parent = GlobalViewMgr.Instance.Unit; } if (pos != Vector3.zero) { if (effectData.BindBody) { Log.Warning($"Warning: set pos @ BindBody effect: {effectData.Name}"); } vecTemp.Set(effectData.EffectOffsetX, effectData.EffectOffsetY, effectData.EffectHight); gt.position = RenderUtils.UnityPosFromBattle(pos + vecTemp); } if (rotation != 0) { gt.rotation = RenderUtils.UnityRotationFromBattle(rotation); } var scale = effectData.ScaleToBodySize != 0 ? effectData.ScaleToBodySize : 1f; vecTemp.Set(scale, scale, scale); gt.localScale = vecTemp; go.SetActive(true); if (!effectData.SoundName.IsNullOrWhitespace()) { SoundManager.Instance.Play3DSound(effectData.SoundName, gt.position).Coroutine(); } } public void Clear() { foreach (var epi in playingList.Values) { GameObject.Destroy(epi.GameObj); } playingList.Clear(); } public void RemoveEffect(uint id) { if (playingList.ContainsKey(id)) { var info = playingList[id]; playingList.Remove(id); GameObjectPool.Instance.RecycleObject(info.GameObj); } } public void ResetEffect(uint id) { if (playingList.ContainsKey(id)) { //var info = playingList[id]; //TODO:Reset effect } } } }