Fix : 옷 변경 최적화 로직 추가

This commit is contained in:
qsxft258@gmail.com 2026-04-16 23:29:24 +09:00
parent 860be78b34
commit c92b7af0a6

View File

@ -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<SkinnedMeshRenderer>(clothingObjects);
_hideSmrCache = CollectChildren<SkinnedMeshRenderer>(hideObjects);
#if MAGICACLOTH2
_clothingClothCache = CollectChildren<MagicaCloth>(clothingObjects);
_hideClothCache = CollectChildren<MagicaCloth>(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<T>(GameObject[] objs) where T : Component
{
if (objs == null) return Array.Empty<MagicaCloth[]>();
var arr = new MagicaCloth[objs.Length][];
if (objs == null) return Array.Empty<T[]>();
var arr = new T[objs.Length][];
for (int i = 0; i < objs.Length; i++)
arr[i] = objs[i] != null
? objs[i].GetComponentsInChildren<MagicaCloth>(true)
: Array.Empty<MagicaCloth>();
? objs[i].GetComponentsInChildren<T>(true)
: Array.Empty<T>();
return arr;
}
static void SetClothsEnabled(MagicaCloth[] cloths, bool value)
static void SetBehavioursEnabled<T>(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>(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