Add more precise life time manager for gfx
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd4abef93430bca4682d8ab452a246b7
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -93124,7 +93124,7 @@ ParticleSystem:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2701600085856382526}
|
||||
serializedVersion: 8
|
||||
lengthInSec: 20
|
||||
lengthInSec: 2
|
||||
simulationSpeed: 1
|
||||
stopAction: 0
|
||||
cullingMode: 0
|
||||
@@ -181200,7 +181200,7 @@ ParticleSystem:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7464649752712418363}
|
||||
serializedVersion: 8
|
||||
lengthInSec: 20
|
||||
lengthInSec: 2
|
||||
simulationSpeed: 1
|
||||
stopAction: 0
|
||||
cullingMode: 0
|
||||
|
||||
@@ -5045,7 +5045,7 @@ ParticleSystem:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3552871021763365661}
|
||||
serializedVersion: 8
|
||||
lengthInSec: 100000
|
||||
lengthInSec: 3
|
||||
simulationSpeed: 1
|
||||
stopAction: 0
|
||||
cullingMode: 0
|
||||
@@ -14770,14 +14770,14 @@ ParticleSystem:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5430282689790728998}
|
||||
serializedVersion: 8
|
||||
lengthInSec: 100000
|
||||
lengthInSec: 3
|
||||
simulationSpeed: 1
|
||||
stopAction: 0
|
||||
cullingMode: 0
|
||||
ringBufferMode: 0
|
||||
ringBufferLoopRange: {x: 0, y: 1}
|
||||
emitterVelocityMode: 0
|
||||
looping: 0
|
||||
looping: 1
|
||||
prewarm: 0
|
||||
playOnAwake: 0
|
||||
useUnscaledTime: 0
|
||||
@@ -19661,7 +19661,7 @@ ParticleSystem:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5710796646422175874}
|
||||
serializedVersion: 8
|
||||
lengthInSec: 0.3
|
||||
lengthInSec: 3
|
||||
simulationSpeed: 1
|
||||
stopAction: 0
|
||||
cullingMode: 0
|
||||
|
||||
@@ -49,7 +49,7 @@ ParticleSystem:
|
||||
ringBufferLoopRange: {x: 0, y: 1}
|
||||
emitterVelocityMode: 0
|
||||
looping: 1
|
||||
prewarm: 1
|
||||
prewarm: 0
|
||||
playOnAwake: 1
|
||||
useUnscaledTime: 0
|
||||
autoRandomSeed: 1
|
||||
|
||||
@@ -9713,7 +9713,7 @@ ParticleSystem:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5361231896778627509}
|
||||
serializedVersion: 8
|
||||
lengthInSec: 7.2
|
||||
lengthInSec: 0.72
|
||||
simulationSpeed: 1
|
||||
stopAction: 0
|
||||
cullingMode: 0
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e90308105a31b6743aa5cfe1db61c2bf
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,209 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: yuanhuanpurple
|
||||
m_Shader: {fileID: 4800000, guid: 0a016a83287664641b867743f19faf14, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords:
|
||||
- _DISSOLVETEXUVS_NORMAL
|
||||
- _DISTORTTEXUVS_NORMAL
|
||||
- _MAINTEXUVS_NORMAL
|
||||
- _MASKTEXUVS_NORMAL
|
||||
m_InvalidKeywords:
|
||||
- _DISSOLVETEXAR_ON
|
||||
- _DISTORTTEXAR_ON
|
||||
- _MASKTEXAR_ON
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses:
|
||||
- MOTIONVECTORS
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BaseMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DissolveTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DistortTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 1714058caa22a3a478730e24f420b8fc, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MaskTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _SpecGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_Lightmaps:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_LightmapsInd:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- unity_ShadowMasks:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _AddPrecomputedVelocity: 0
|
||||
- _AlphaClip: 0
|
||||
- _AlphaCutoff: 0.5
|
||||
- _AlphaToMask: 0
|
||||
- _Blend: 0
|
||||
- _BlendMode: 1
|
||||
- _BlendModePreserveSpecular: 1
|
||||
- _BumpScale: 1
|
||||
- _ClearCoatMask: 0
|
||||
- _ClearCoatSmoothness: 0
|
||||
- _Cull: 2
|
||||
- _CullMode: 0
|
||||
- _CustomDissolve: 0
|
||||
- _CustomMainTex: 0
|
||||
- _Cutoff: 0.5
|
||||
- _DepthFade: 1
|
||||
- _DetailAlbedoMapScale: 1
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DissolveFactor: 0
|
||||
- _DissolveSoft: 0.1
|
||||
- _DissolveTexAR: 1
|
||||
- _DissolveTexClampU: 0
|
||||
- _DissolveTexClampV: 0
|
||||
- _DissolveTexRotate: 0
|
||||
- _DissolveTexUSpeed: 0
|
||||
- _DissolveTexUVS: 0
|
||||
- _DissolveTexVSpeed: 0
|
||||
- _DissolveWide: 0.05
|
||||
- _DistortDissolveTex: 0
|
||||
- _DistortFactor: 0
|
||||
- _DistortMainTex: 0
|
||||
- _DistortMaskTex: 0
|
||||
- _DistortTexAR: 1
|
||||
- _DistortTexClampU: 0
|
||||
- _DistortTexClampV: 0
|
||||
- _DistortTexRotate: 0
|
||||
- _DistortTexUSpeed: 0
|
||||
- _DistortTexUVS: 0
|
||||
- _DistortTexVSpeed: 0
|
||||
- _Dst: 1
|
||||
- _DstBlend: 0
|
||||
- _DstBlendAlpha: 0
|
||||
- _EnvironmentReflections: 1
|
||||
- _FDepth: 0
|
||||
- _FDissolveTex: 0
|
||||
- _FDistortTex: 0
|
||||
- _FFnl: 0
|
||||
- _FMaskTex: 0
|
||||
- _FnlPower: 1
|
||||
- _FnlScale: 0
|
||||
- _GlossMapScale: 0
|
||||
- _Glossiness: 0
|
||||
- _GlossyReflections: 0
|
||||
- _MainAlpha: 1
|
||||
- _MainTexAR: 0
|
||||
- _MainTexClampU: 0
|
||||
- _MainTexClampV: 0
|
||||
- _MainTexRotate: 0
|
||||
- _MainTexUSpeed: 0
|
||||
- _MainTexUVS: 0
|
||||
- _MainTexVSpeed: 0
|
||||
- _MaskTexAR: 1
|
||||
- _MaskTexClampU: 0
|
||||
- _MaskTexClampV: 0
|
||||
- _MaskTexRotate: 0
|
||||
- _MaskTexUSpeed: 0
|
||||
- _MaskTexUVS: 0
|
||||
- _MaskTexVSpeed: 0
|
||||
- _Metallic: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.005
|
||||
- _QueueOffset: 0
|
||||
- _ReFnl: 0
|
||||
- _ReceiveShadows: 1
|
||||
- _Scr: 1
|
||||
- _Smoothness: 0.5
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _SrcBlendAlpha: 1
|
||||
- _Surface: 0
|
||||
- _WorkflowMode: 1
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _DissolveColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _FnlColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _MainColor: {r: 2.0000002, g: 2.0000002, b: 2.0000002, a: 1}
|
||||
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
--- !u!114 &6085187289834300244
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 11
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
version: 9
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 210db5088cb0298479121e14abbb039d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -0,0 +1,21 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1714058caa22a3a478730e24f420b8fc
|
||||
IHVImageFormatImporter:
|
||||
externalObjects: {}
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
isReadable: 0
|
||||
sRGBTexture: 1
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
ignoreMipmapLimit: 0
|
||||
mipmapLimitGroupName:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:56de257a0dc137130cb44b00462bc5a346cf8f292d1178fb31e138075b1fdb8c
|
||||
size 137951
|
||||
oid sha256:d6a8ecae27ef44213a7965bfcb0e1cfcf30a013734f9c6fd14095d6440259005
|
||||
size 145407
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
using System.Collections.Generic;
|
||||
using BrewMonster.Scripts;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
public sealed class FadeOutGfx
|
||||
{
|
||||
public int m_dwTotalTTL;
|
||||
public int m_dwTTL;
|
||||
public GFX_BINDING m_pGfx;
|
||||
public float m_fAlpha;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queues skill/combined-action GFX for delayed stop (fade-out window), aligned with A3DGFXExMan::UpdateFadeOutGfxLst.
|
||||
/// </summary>
|
||||
public class A3DGfxMan : IAutoInitialize, ITickable
|
||||
{
|
||||
public const int DefaultFadeOutMs = 1000;
|
||||
|
||||
private static A3DGfxMan _instance;
|
||||
|
||||
readonly Dictionary<int, List<GFX_BINDING>> _releaseByModel = new Dictionary<int, List<GFX_BINDING>>();
|
||||
readonly List<FadeOutGfx> _fadeOutList = new List<FadeOutGfx>();
|
||||
readonly List<GFX_BINDING> _flushBuffer = new List<GFX_BINDING>();
|
||||
|
||||
public static A3DGfxMan Instance => _instance ??= new A3DGfxMan();
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_instance = this;
|
||||
TickInvoker.Instance.RegisterTickable(this);
|
||||
}
|
||||
|
||||
public bool Tick(uint dwDeltaTime)
|
||||
{
|
||||
if (_fadeOutList.Count == 0)
|
||||
return true;
|
||||
|
||||
int deltaTime = (int)dwDeltaTime;
|
||||
|
||||
for (int i = _fadeOutList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
FadeOutGfx entry = _fadeOutList[i];
|
||||
GFX_BINDING gfx = entry.m_pGfx;
|
||||
|
||||
if (gfx == null)
|
||||
{
|
||||
_fadeOutList.RemoveAt(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
entry.m_dwTTL -= deltaTime;
|
||||
if (entry.m_dwTTL > 0)
|
||||
{
|
||||
_fadeOutList[i] = entry;
|
||||
continue;
|
||||
}
|
||||
|
||||
gfx.Stop();
|
||||
_fadeOutList.RemoveAt(i);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_fadeOutList.Clear();
|
||||
_releaseByModel.Clear();
|
||||
_flushBuffer.Clear();
|
||||
}
|
||||
|
||||
public void AddReleaseGfx(int modelId, GFX_BINDING gfx)
|
||||
{
|
||||
if (gfx == null)
|
||||
return;
|
||||
|
||||
if (!_releaseByModel.TryGetValue(modelId, out List<GFX_BINDING> list))
|
||||
{
|
||||
list = new List<GFX_BINDING>(4);
|
||||
_releaseByModel[modelId] = list;
|
||||
}
|
||||
|
||||
list.Add(gfx);
|
||||
}
|
||||
|
||||
public int GetPendingReleaseCount(int modelId)
|
||||
{
|
||||
return _releaseByModel.TryGetValue(modelId, out List<GFX_BINDING> list) ? list.Count : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fade out the oldest <paramref name="maxCount"/> pending GFX for a model (cast/chant phase snapshot).
|
||||
/// 淡出该模型最早注册的 maxCount 个待释放特效(吟唱阶段快照)。
|
||||
/// </summary>
|
||||
public void FadeOutReleaseUpTo(int modelId, int maxCount, int fadeMs = DefaultFadeOutMs)
|
||||
{
|
||||
if (maxCount <= 0
|
||||
|| !_releaseByModel.TryGetValue(modelId, out List<GFX_BINDING> releaseList)
|
||||
|| releaseList.Count == 0)
|
||||
return;
|
||||
|
||||
int count = maxCount < releaseList.Count ? maxCount : releaseList.Count;
|
||||
QueueFadeOutFromReleaseList(releaseList, count, fadeMs);
|
||||
|
||||
if (releaseList.Count == 0)
|
||||
_releaseByModel.Remove(modelId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fade out every pending combined-action GFX registered for a model.
|
||||
/// 淡出该模型所有待释放的组合动作特效。
|
||||
/// </summary>
|
||||
public void FadeOutGfx(int modelId, int fadeMs = DefaultFadeOutMs)
|
||||
{
|
||||
if (!_releaseByModel.TryGetValue(modelId, out List<GFX_BINDING> releaseList)
|
||||
|| releaseList.Count == 0)
|
||||
return;
|
||||
|
||||
QueueFadeOutFromReleaseList(releaseList, releaseList.Count, fadeMs);
|
||||
_releaseByModel.Remove(modelId);
|
||||
}
|
||||
|
||||
void QueueFadeOutFromReleaseList(List<GFX_BINDING> releaseList, int count, int fadeMs)
|
||||
{
|
||||
_flushBuffer.Clear();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
GFX_BINDING gfx = releaseList[i];
|
||||
if (gfx != null)
|
||||
_flushBuffer.Add(gfx);
|
||||
}
|
||||
|
||||
releaseList.RemoveRange(0, count);
|
||||
|
||||
for (int i = 0; i < _flushBuffer.Count; i++)
|
||||
{
|
||||
GFX_BINDING gfx = _flushBuffer[i];
|
||||
if (gfx == null)
|
||||
continue;
|
||||
|
||||
_fadeOutList.Add(new FadeOutGfx
|
||||
{
|
||||
m_dwTotalTTL = fadeMs,
|
||||
m_dwTTL = fadeMs,
|
||||
m_pGfx = gfx,
|
||||
m_fAlpha = 1f,
|
||||
});
|
||||
}
|
||||
|
||||
_flushBuffer.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: befe34413c2133549ab038e380847780
|
||||
@@ -72,9 +72,15 @@ namespace BrewMonster
|
||||
[SerializeField] private Button channelCancelButton;
|
||||
|
||||
private Coroutine _channelingCoroutine;
|
||||
private Coroutine _fadeChantGfxCoroutine;
|
||||
private Coroutine _fadeAttackGfxCoroutine;
|
||||
private int _channelingSkillId;
|
||||
private bool _isChanneling;
|
||||
|
||||
private const float k_FadeChantGfxDelaySecs = 0.5f;
|
||||
private const float k_DefaultAttackGfxDurationSecs = 2f;
|
||||
private const float k_AttackGfxFadeBufferSecs = 0.25f;
|
||||
|
||||
/// <summary>
|
||||
/// World position of the draggable target marker, read by CECSkillGfxMan.get_pos_by_id.
|
||||
/// 可拖动目标标记的世界坐标,由 CECSkillGfxMan.get_pos_by_id 读取。
|
||||
@@ -100,6 +106,7 @@ namespace BrewMonster
|
||||
if (channelCancelButton != null)
|
||||
channelCancelButton.onClick.RemoveListener(CancelChanneling);
|
||||
StopChanneling();
|
||||
StopFadeGfxCoroutines();
|
||||
if (Instance == this)
|
||||
Instance = null;
|
||||
}
|
||||
@@ -480,6 +487,61 @@ namespace BrewMonster
|
||||
StopChanneling();
|
||||
}
|
||||
|
||||
private void StopFadeGfxCoroutines()
|
||||
{
|
||||
if (_fadeChantGfxCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_fadeChantGfxCoroutine);
|
||||
_fadeChantGfxCoroutine = null;
|
||||
}
|
||||
|
||||
if (_fadeAttackGfxCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_fadeAttackGfxCoroutine);
|
||||
_fadeAttackGfxCoroutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
private int GetPlayerModelId() => player?.GetPlayerModel()?.GetId() ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// CECModel path: release active channel FX into A3DGfxMan queue, then fade all pending GFX.
|
||||
/// CECModel 路径:先把仍挂在通道上的特效 Release 进 A3DGfxMan,再统一淡出。
|
||||
/// </summary>
|
||||
private void FinishPlayerSkillGfx()
|
||||
{
|
||||
player?.GetPlayerModel()?.ClearComActFlagAllRankNodes(true);
|
||||
}
|
||||
|
||||
private void FadeOutChantGfxUpTo(int maxCount, int fadeMs = A3DGfxMan.DefaultFadeOutMs)
|
||||
{
|
||||
int modelId = GetPlayerModelId();
|
||||
if (modelId != 0)
|
||||
A3DGfxMan.Instance.FadeOutReleaseUpTo(modelId, maxCount, fadeMs);
|
||||
}
|
||||
|
||||
private void ScheduleFadeChantGfxAfterCast()
|
||||
{
|
||||
if (_fadeChantGfxCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_fadeChantGfxCoroutine);
|
||||
_fadeChantGfxCoroutine = null;
|
||||
}
|
||||
|
||||
_fadeChantGfxCoroutine = StartCoroutine(FadeChantGfxAfterCastRoutine());
|
||||
}
|
||||
|
||||
private void ScheduleFadeAllGfxWhenAttackStopped(int attackTimeMs)
|
||||
{
|
||||
if (_fadeAttackGfxCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_fadeAttackGfxCoroutine);
|
||||
_fadeAttackGfxCoroutine = null;
|
||||
}
|
||||
|
||||
_fadeAttackGfxCoroutine = StartCoroutine(FadeOutAttackGfxAfterComplete(attackTimeMs));
|
||||
}
|
||||
|
||||
private void StopChanneling()
|
||||
{
|
||||
_isChanneling = false;
|
||||
@@ -491,11 +553,13 @@ namespace BrewMonster
|
||||
_channelingCoroutine = null;
|
||||
}
|
||||
|
||||
StopFadeGfxCoroutines();
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
player.StopSkillAttackAction();
|
||||
EventBus.PublishChannel(player.GetCharacterID(), new ClearComActFlagAllRankNodesEvent(true));
|
||||
FinishPlayerSkillGfx();
|
||||
|
||||
CECAttackerEvents attackerEvents =
|
||||
CECAttacksMan.Instance?.FindAttackByAttacker(player.GetPlayerInfo().cid);
|
||||
@@ -546,6 +610,8 @@ namespace BrewMonster
|
||||
if (_isChanneling)
|
||||
StopChanneling();
|
||||
|
||||
StopFadeGfxCoroutines();
|
||||
|
||||
logPanelAnimeScene.Reset();
|
||||
int skillId = skill.GetSkillID();
|
||||
logPanelAnimeScene.AddCopyTextButton("ID", skillId.ToString());
|
||||
@@ -564,6 +630,10 @@ namespace BrewMonster
|
||||
if (!animOk)
|
||||
Debug.LogWarning($"[SkillTriggerPanel] PlaySkillCastAction returned false for skill {skillId} — animation may not play.");
|
||||
|
||||
// 0.5s: fade chant GFX only (A3DGfxMan snapshot). Cast release + attack fade together when attack ends.
|
||||
// 0.5 秒:仅淡出吟唱特效;施法释放与攻击特效在攻击结束时同时淡出。
|
||||
ScheduleFadeChantGfxAfterCast();
|
||||
|
||||
// // 2. Trigger VFX via the GFX composer — bypasses network entirely
|
||||
// // 通过特效组合器触发特效,完全绕过网络
|
||||
// var composerMan = CECAttacksMan.Instance?.GetSkillGfxComposerMan();
|
||||
@@ -604,7 +674,7 @@ namespace BrewMonster
|
||||
if (!_isChanneling || hostPlayer == null)
|
||||
yield break;
|
||||
|
||||
TriggerLocalSkillAttack(hostPlayer, skillId, replayAttackAnim: false);
|
||||
TriggerLocalSkillAttack(hostPlayer, skillId, replayAttackAnim: true);
|
||||
|
||||
while (_isChanneling && hostPlayer != null)
|
||||
{
|
||||
@@ -631,6 +701,57 @@ namespace BrewMonster
|
||||
TriggerLocalSkillAttack(hostPlayer, skillId, replayAttackAnim);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 0.5s after cast: fade chant GFX only via <see cref="A3DGfxMan.FadeOutReleaseUpTo"/>.
|
||||
/// 施法 0.5 秒后:仅淡出已注册的吟唱特效。
|
||||
/// </summary>
|
||||
private IEnumerator FadeChantGfxAfterCastRoutine()
|
||||
{
|
||||
yield return null;
|
||||
|
||||
int modelId = GetPlayerModelId();
|
||||
if (modelId == 0)
|
||||
yield break;
|
||||
|
||||
yield return new WaitForSeconds(k_FadeChantGfxDelaySecs);
|
||||
_fadeChantGfxCoroutine = null;
|
||||
|
||||
if (player == null)
|
||||
yield break;
|
||||
|
||||
modelId = GetPlayerModelId();
|
||||
if (modelId == 0)
|
||||
yield break;
|
||||
|
||||
int chantGfxCount = A3DGfxMan.Instance.GetPendingReleaseCount(modelId);
|
||||
FadeOutChantGfxUpTo(chantGfxCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wait for attack duration, flush active FX via CECModel.Release, then A3DGfxMan fade-out.
|
||||
/// IsActionStopped() alone is unreliable here (empty channel reads as stopped before attack starts).
|
||||
/// 等待攻击时长,经 CECModel 释放仍活跃的特效,再由 A3DGfxMan 淡出。
|
||||
/// </summary>
|
||||
private IEnumerator FadeOutAttackGfxAfterComplete(int attackTimeMs)
|
||||
{
|
||||
yield return null;
|
||||
|
||||
float attackSecs = attackTimeMs > 0
|
||||
? attackTimeMs / 1000f
|
||||
: k_DefaultAttackGfxDurationSecs;
|
||||
|
||||
yield return new WaitForSeconds(attackSecs + k_AttackGfxFadeBufferSecs);
|
||||
|
||||
_fadeAttackGfxCoroutine = null;
|
||||
if (player == null)
|
||||
yield break;
|
||||
|
||||
// One frame for UpdateChannelActs → Stop() → Release() → AddReleaseGfx.
|
||||
yield return null;
|
||||
|
||||
FinishPlayerSkillGfx();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Local-only skill hit: mirrors <see cref="CECPlayer.PlayAttackEffect"/> for debug panel.
|
||||
/// When <paramref name="replayAttackAnim"/> is true (channeling tick), signal prior attack so anim replays.
|
||||
@@ -686,8 +807,8 @@ namespace BrewMonster
|
||||
if (!ok)
|
||||
BMLogger.LogWarning($"[SkillTriggerPanel] PlaySkillAttackAction returned false for skill {skillId} — attack anim may not play.");
|
||||
|
||||
if (attackTime != 0)
|
||||
attackTime = 0;
|
||||
if(!replayAttackAnim)
|
||||
ScheduleFadeAllGfxWhenAttackStopped(attackTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,12 @@ using BrewMonster.Scripts;
|
||||
using CSNetwork.GPDataType;
|
||||
using UnityEngine;
|
||||
using ModelViewer.Common;
|
||||
|
||||
using BrewMonster;
|
||||
using CombinedActMap = System.Collections.Generic.Dictionary<string, object>;
|
||||
using CoGfxMap = System.Collections.Generic.Dictionary<string, object>;
|
||||
using ConvexHullDataArray = System.Collections.Generic.List<object>;
|
||||
using ECModelHookMap = System.Collections.Generic.Dictionary<string, object>;
|
||||
using ActQueue = System.Collections.Generic.List<A3DCombActDynData>;
|
||||
using BrewMonster;
|
||||
using BrewMonster.Scripts.ECModel;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Unity.VisualScripting.FullSerializer;
|
||||
@@ -70,6 +69,7 @@ public class FX_BINDING_BASE
|
||||
public virtual bool IsStart() {return false;}
|
||||
public virtual void Stop() {}
|
||||
public virtual void Render() {}
|
||||
public virtual void Release() {}
|
||||
public virtual void UpdateParam(CECModel pECModel, int nDeltaTime) {}
|
||||
public void SetInfo(EVENT_INFO pInfo) { m_pInfo = pInfo; }
|
||||
public EVENT_INFO GetInfo() { return m_pInfo; }
|
||||
@@ -100,6 +100,10 @@ public class GFX_BINDING : FX_BINDING_BASE
|
||||
_destroyScheduled = true;
|
||||
DestroyAfterParticlesFinish().Forget();
|
||||
}
|
||||
public override void Release()
|
||||
{
|
||||
A3DGfxMan.Instance.AddReleaseGfx(m_pDynData.GetHostModel().GetId(), this);
|
||||
}
|
||||
|
||||
async UniTaskVoid DestroyAfterParticlesFinish()
|
||||
{
|
||||
@@ -414,7 +418,7 @@ public class A3DCombActDynData
|
||||
GFX:
|
||||
{
|
||||
path = "gfx/" + path;
|
||||
Debug.Log("[GFX_BINDING] LoadFXFromEventList: " + path);
|
||||
BMLogger.Log("[GFX_BINDING] LoadFXFromEventList: " + path);
|
||||
GameObject prefab = await AddressableManager.Instance.LoadPrefabAsync(path);
|
||||
GFX_BINDING fx = new GFX_BINDING(this);
|
||||
if(prefab != null && m_pECModel != null)
|
||||
@@ -427,7 +431,7 @@ public class A3DCombActDynData
|
||||
}
|
||||
else if (prefab == null)
|
||||
{
|
||||
Debug.LogWarning("Missing gfx prefab, using placeholder: " + path);
|
||||
BMLogger.LogWarning("Missing gfx prefab, using placeholder: " + path);
|
||||
string path2 = "gfx/人物/技能/妖兽/NullDefault.gfx";
|
||||
GameObject prefab2 = await AddressableManager.Instance.LoadPrefabAsync(path2);
|
||||
var gfx = GameObject.Instantiate(prefab2, m_pECModel.transform);
|
||||
@@ -507,8 +511,7 @@ public class A3DCombActDynData
|
||||
}
|
||||
public void Stop(bool bStopAct, bool bForceStopFx = false )
|
||||
{
|
||||
Debug.Log("[DefaultPolicy]Stop: " + m_pAct?.m_strName + " bStopAct: " + bStopAct + " bForceStopFx: " + bForceStopFx);
|
||||
RemoveAllActiveFx();
|
||||
RemoveAllActiveFx(bForceStopFx);
|
||||
if (ActiveAttackEvent != null)
|
||||
{
|
||||
ActiveAttackEvent.m_bSignaled = true;
|
||||
@@ -641,7 +644,7 @@ public class A3DCombActDynData
|
||||
|
||||
bool IsCurActFinished(ACTION_INFO pCur)
|
||||
{
|
||||
return !pCur.IsInfinite() || m_nCurActLoop >= m_arrActLoopNum[m_nCurActIndex].GetLoopNum();
|
||||
return !pCur.IsInfinite() && m_nCurActLoop >= m_arrActLoopNum[m_nCurActIndex].GetLoopNum();
|
||||
}
|
||||
bool IsAllEventFinished() { return m_ActFxArray.Count == 0 ; }
|
||||
public bool IsActionStopped()
|
||||
@@ -671,14 +674,17 @@ public class A3DCombActDynData
|
||||
Play(m_nChannel, m_fWeight, m_nTransTime, m_dwEventMask, false, m_bAbsTrack, m_bNoFx);
|
||||
}
|
||||
}
|
||||
public void RemoveAllActiveFx()
|
||||
public void RemoveAllActiveFx(bool bForceStopFx = false)
|
||||
{
|
||||
foreach(var fx in m_ActFxArray)
|
||||
{
|
||||
if(fx != null)
|
||||
{
|
||||
Debug.Log("RemoveAllActiveFx: " + fx.GetInfo()?.m_pAct?.m_strName);
|
||||
fx.Stop();
|
||||
if(bForceStopFx)
|
||||
{
|
||||
fx.Stop();
|
||||
}
|
||||
fx.Release();
|
||||
}
|
||||
}
|
||||
m_ActFxArray.Clear();
|
||||
@@ -1004,14 +1010,6 @@ public class CECModelStaticData
|
||||
|
||||
public IReadOnlyDictionary<int, uint> GetActionEventMaskSnapshot() => m_EventMasks;
|
||||
|
||||
public void OnScriptEndAction(CECModel pModel, int nChannel, string szActName)
|
||||
{
|
||||
if (!IsScriptEnabled(ECMScript.enumECMScriptEndActioin))
|
||||
return;
|
||||
|
||||
Debug.LogWarning($"CECModelStaticData.OnScriptEndAction invoked for {szActName}, scripting runtime not yet ported.");
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
m_OrgColor = 0xFFFFFFFF;
|
||||
@@ -1340,7 +1338,6 @@ public class CECModel
|
||||
if (!string.IsNullOrEmpty(hangerName) && childModel != null)
|
||||
{
|
||||
m_childModels[hangerName] = childModel;
|
||||
BMLogger.Log($"[CECModel] Registered child model '{hangerName}'");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1355,7 +1352,6 @@ public class CECModel
|
||||
{
|
||||
if (m_childModels.Remove(hangerName))
|
||||
{
|
||||
BMLogger.Log($"[CECModel] Unregistered child model '{hangerName}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1575,6 +1571,7 @@ public class CECModel
|
||||
{
|
||||
foreach (var ca in m_ChannelActs)
|
||||
ca?.Release();
|
||||
A3DGfxMan.Instance.FadeOutGfx(GetId());
|
||||
EventBus.PublishChannel(m_nId, new ClearComActFlagAllRankNodesEvent(bSignalCurrent));
|
||||
return false;
|
||||
}
|
||||
@@ -1626,9 +1623,9 @@ public class CECModel
|
||||
public void StopChannelAction(int nChannel, bool bStopAct, bool bStopFx = false)
|
||||
{
|
||||
ChannelAct ca = m_ChannelActs[nChannel];
|
||||
A3DGfxMan.Instance.FadeOutGfx(GetId());
|
||||
foreach (var node in ca.m_RankNodes)
|
||||
{
|
||||
Debug.Log("[DefaultPolicy]StopChannelAction: " + node.m_pActive?.GetComAct()?.m_strName);
|
||||
node.m_pActive.Stop(bStopAct, bStopFx);
|
||||
}
|
||||
ca.m_RankNodes.Clear();
|
||||
@@ -1671,12 +1668,10 @@ public class CECModel
|
||||
bool bActFinished = false;
|
||||
if (node.m_dwFlagMode == COMACT_FLAG_MODE_ONCE_IGNOREGFX || node.m_dwFlagMode == COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX)
|
||||
{
|
||||
BMLogger.Log("[DefaultPolicy] Checking IsActionStopped: " + node.m_pActive?.GetComAct()?.m_strName);
|
||||
bActFinished = node.m_pActive.IsActionStopped();
|
||||
}
|
||||
else
|
||||
{
|
||||
BMLogger.Log("[DefaultPolicy] Checking IsAllFinished: " + node.m_pActive?.GetComAct()?.m_strName);
|
||||
bActFinished = node.m_pActive.IsAllFinished();
|
||||
}
|
||||
if (bActFinished)
|
||||
|
||||
@@ -165,8 +165,6 @@ namespace BrewMonster
|
||||
|
||||
public void StopSkillAttackAction()
|
||||
{
|
||||
BMLogger.Log("[DefaultPolicy]StopSkillAttackAction: " + m_bSkillAttackActionPlayed);
|
||||
BMLogger.Log("[DefaultPolicy]IsPlayingCastingSkillAction: " + m_actionPlayPolicy.IsPlayingCastingSkillAction());
|
||||
if (m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction() && m_bSkillAttackActionPlayed)
|
||||
{
|
||||
m_actionPlayPolicy.StopSkillAction();
|
||||
|
||||
@@ -357,8 +357,6 @@ namespace BrewMonster
|
||||
&& GetModel().PlayActionByName(szActName, 1.0f, bRestart, nTransTime, true, (uint)iAction , bNoFx, attackEvent, dwFlagMode);
|
||||
if (!check)
|
||||
{
|
||||
// BMLogger.LogError($"Fall back to base implementation: {szActName} failed");
|
||||
//fallback to base implementation(which is non policy based)
|
||||
base.PlayNonSkillActionWithName(iAction, szActName, bRestart, nTransTime, bNoFx, attackEvent, dwFlagMode);
|
||||
}
|
||||
return check;
|
||||
@@ -369,8 +367,6 @@ namespace BrewMonster
|
||||
&& GetModel().QueueAction(szActName, nTransTime, (uint)iAction, bForceStopPrevAct, false, bNoFx, bResetSpeed, bResetActFlag, attackEvent, dwNewFlagMode);
|
||||
if (!check)
|
||||
{
|
||||
// BMLogger.LogError($"Fall back to base implementation: {szActName} failed");
|
||||
//fallback to base implementation(which is non policy based)
|
||||
base.QueueNonSkillActionWithName(iAction, szActName, nTransTime, bForceStopPrevAct, bNoFx, bResetSpeed, bResetActFlag, attackEvent, dwNewFlagMode);
|
||||
}
|
||||
return check;
|
||||
@@ -379,7 +375,6 @@ namespace BrewMonster
|
||||
if (IsMoving()){
|
||||
return false;
|
||||
}
|
||||
BMLogger.Log("[DefaultPolicy] PlaySkillCastActionWithName:" + szActName);
|
||||
ClearComActFlagAllRankNodes(true);
|
||||
bool check = GetModel()!=null
|
||||
&& GetModel().PlayActionByName(szActName, 1.0f, true, 200, true, (uint)PLAYER_ACTION_TYPE.ACT_CASTSKILL, bNoFX);
|
||||
@@ -389,7 +384,6 @@ namespace BrewMonster
|
||||
if (IsMoving()){
|
||||
return false;
|
||||
}
|
||||
BMLogger.Log("[DefaultPolicy] Checking PlaySkillAttackActionWithName:" + szActName);
|
||||
ClearComActFlagAllRankNodes(true);
|
||||
bool check = GetModel() != null
|
||||
&& GetModel().PlayActionByName(szActName, 1.0f, true, 200, true, (uint)PLAYER_ACTION_TYPE.ACT_CASTSKILL, bNoFX, attackEvent, dwFlagMode);
|
||||
@@ -415,14 +409,12 @@ namespace BrewMonster
|
||||
}
|
||||
public override void StopChannelAction(){
|
||||
if (GetModel()!=null){
|
||||
BMLogger.Log("[DefaultPolicy]StopChannelAction: " + GetModel().GetCurActionUserData());
|
||||
ClearComActFlagAllRankNodes(true);
|
||||
GetModel().StopChannelAction(0, true);
|
||||
}
|
||||
}
|
||||
public override void StopSkillAction(){
|
||||
if (GetModel()!=null && IsPlayingCastingSkillAction()){
|
||||
BMLogger.Log("[DefaultPolicy]StopSkillAction: " + GetModel().GetCurActionUserData());
|
||||
StopChannelAction();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user