diff --git a/Assets/Scripts/Streamingle/StreamingleControl/Controllers/AvatarOutfitController.cs b/Assets/Scripts/Streamingle/StreamingleControl/Controllers/AvatarOutfitController.cs index 0132940f1..4d3aaa951 100644 --- a/Assets/Scripts/Streamingle/StreamingleControl/Controllers/AvatarOutfitController.cs +++ b/Assets/Scripts/Streamingle/StreamingleControl/Controllers/AvatarOutfitController.cs @@ -92,22 +92,27 @@ public class AvatarOutfitController : MonoBehaviour, IController [Header("Transform Effect (이 의상으로 변경할 때 재생)")] public TransformEffectSettings transformEffect = new TransformEffectSettings(); + // NiloToon renderCharacter 경로는 GameObject 를 Active 로 유지하기 때문에 + // 하위 MagicaCloth / SkinnedMeshRenderer 가 계속 시뮬+스키닝을 돈다. + // 1회 수집 후 Apply/Remove 에서 .enabled 로 함께 토글. + [NonSerialized] private SkinnedMeshRenderer[][] _clothingSmrCache; + [NonSerialized] private SkinnedMeshRenderer[][] _hideSmrCache; #if MAGICACLOTH2 - // NiloToon renderCharacter 토글 시 GameObject 가 Active 유지되어 MagicaCloth 가 계속 시뮬되는 문제 방지. - // BuildSimulationCache 로 1회 수집 후 Apply/Remove 에서 cloth.enabled 토글. - [NonSerialized] private MagicaCloth[][] _clothingSimCache; - [NonSerialized] private MagicaCloth[][] _hideSimCache; - [NonSerialized] private bool _simCacheBuilt; + [NonSerialized] private MagicaCloth[][] _clothingClothCache; + [NonSerialized] private MagicaCloth[][] _hideClothCache; #endif + [NonSerialized] private bool _simCacheBuilt; public void BuildSimulationCache() { -#if MAGICACLOTH2 if (_simCacheBuilt) return; - _clothingSimCache = CollectCloths(clothingObjects); - _hideSimCache = CollectCloths(hideObjects); - _simCacheBuilt = true; + _clothingSmrCache = CollectChildren(clothingObjects); + _hideSmrCache = CollectChildren(hideObjects); +#if MAGICACLOTH2 + _clothingClothCache = CollectChildren(clothingObjects); + _hideClothCache = CollectChildren(hideObjects); #endif + _simCacheBuilt = true; } public void ApplyOutfit() @@ -127,13 +132,18 @@ public class AvatarOutfitController : MonoBehaviour, IController void ApplyArrayState(GameObject[] objs, bool value, bool clothingSide) { if (objs == null) return; + var smrCache = clothingSide ? _clothingSmrCache : _hideSmrCache; +#if MAGICACLOTH2 + var clothCache = clothingSide ? _clothingClothCache : _hideClothCache; +#endif for (int i = 0; i < objs.Length; i++) { SetRenderOrActive(objs[i], value); + if (smrCache != null && i < smrCache.Length) + SetRenderersEnabled(smrCache[i], value); #if MAGICACLOTH2 - var cache = clothingSide ? _clothingSimCache : _hideSimCache; - if (cache != null && i < cache.Length) - SetClothsEnabled(cache[i], value); + if (clothCache != null && i < clothCache.Length) + SetBehavioursEnabled(clothCache[i], value); #endif } } @@ -168,28 +178,36 @@ public class AvatarOutfitController : MonoBehaviour, IController obj.SetActive(value); } -#if MAGICACLOTH2 - static MagicaCloth[][] CollectCloths(GameObject[] objs) + static T[][] CollectChildren(GameObject[] objs) where T : Component { - if (objs == null) return Array.Empty(); - var arr = new MagicaCloth[objs.Length][]; + if (objs == null) return Array.Empty(); + var arr = new T[objs.Length][]; for (int i = 0; i < objs.Length; i++) arr[i] = objs[i] != null - ? objs[i].GetComponentsInChildren(true) - : Array.Empty(); + ? objs[i].GetComponentsInChildren(true) + : Array.Empty(); return arr; } - static void SetClothsEnabled(MagicaCloth[] cloths, bool value) + static void SetBehavioursEnabled(T[] behaviours, bool value) where T : Behaviour { - if (cloths == null) return; - foreach (var cloth in cloths) + if (behaviours == null) return; + foreach (var b in behaviours) { - if (cloth != null && cloth.enabled != value) - cloth.enabled = value; + if (b != null && b.enabled != value) + b.enabled = value; + } + } + + static void SetRenderersEnabled(T[] renderers, bool value) where T : Renderer + { + if (renderers == null) return; + foreach (var r in renderers) + { + if (r != null && r.enabled != value) + r.enabled = value; } } -#endif } #endregion