Add VRChat and GitHub packages to Unity project

This commit is contained in:
gunnbr committed 2021-01-18 09:14:18 -08:00
1 parent 0334a52b21
commit 85538aaccc
3297 files changed
+847877

No files matched your search

@@ -0,0 +1,97 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
using VRCSDK2.Validation.Performance.Stats;
namespace VRCSDK2.Validation.Performance.Scanners
{
public abstract class AbstractPerformanceScanner : ScriptableObject
{
private const int MAXIMUM_COMPONENT_SCANS_PER_FRAME = 10;
private static int _componentScansThisFrame = 0;
private static int _componentScansFrameNumber = 0;
private readonly Stack<IEnumerator> _coroutines = new Stack<IEnumerator>();
private bool _limitComponentScansPerFrame = true;
public abstract IEnumerator RunPerformanceScanEnumerator(GameObject avatarObject, AvatarPerformanceStats perfStats, AvatarPerformance.IgnoreDelegate shouldIgnoreComponent);
public void RunPerformanceScan(GameObject avatarObject, AvatarPerformanceStats perfStats, AvatarPerformance.IgnoreDelegate shouldIgnoreComponent)
{
_limitComponentScansPerFrame = false;
try
{
_coroutines.Push(RunPerformanceScanEnumerator(avatarObject, perfStats, shouldIgnoreComponent));
while(_coroutines.Count > 0)
{
IEnumerator currentCoroutine = _coroutines.Peek();
if(currentCoroutine.MoveNext())
{
IEnumerator nestedCoroutine = currentCoroutine.Current as IEnumerator;
if(nestedCoroutine != null)
{
_coroutines.Push(nestedCoroutine);
}
}
else
{
_coroutines.Pop();
}
}
_coroutines.Clear();
}
finally
{
_limitComponentScansPerFrame = true;
}
}
protected IEnumerator ScanAvatarForComponentsOfType(Type componentType, GameObject avatarObject, List<Component> destinationBuffer)
{
yield return HandleComponentScansPerFrameLimit();
Profiler.BeginSample("Component Scan");
destinationBuffer.Clear();
destinationBuffer.AddRange(avatarObject.GetComponentsInChildren(componentType, true));
Profiler.EndSample();
}
protected IEnumerator ScanAvatarForComponentsOfType<T>(GameObject avatarObject, List<T> destinationBuffer)
{
yield return HandleComponentScansPerFrameLimit();
Profiler.BeginSample("Component Scan");
destinationBuffer.Clear();
avatarObject.GetComponentsInChildren(true, destinationBuffer);
Profiler.EndSample();
yield return null;
}
private IEnumerator HandleComponentScansPerFrameLimit()
{
if(!_limitComponentScansPerFrame)
{
yield break;
}
while(_componentScansThisFrame >= MAXIMUM_COMPONENT_SCANS_PER_FRAME)
{
if(Time.frameCount > _componentScansFrameNumber)
{
_componentScansFrameNumber = Time.frameCount;
_componentScansThisFrame = 0;
break;
}
yield return null;
}
_componentScansThisFrame++;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0bd0691a021844f49444a04a959d6328
timeCreated: 1561279121
@@ -0,0 +1,44 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRCSDK2.Validation.Performance.Stats;
namespace VRCSDK2.Validation.Performance.Scanners
{
#if VRC_CLIENT
[CreateAssetMenu(
fileName = "New AnimatorPerformanceScanner",
menuName = "VRC Scriptable Objects/Performance/Avatar/Scanners/AnimatorPerformanceScanner"
)]
#endif
public sealed class AnimatorPerformanceScanner : AbstractPerformanceScanner
{
public override IEnumerator RunPerformanceScanEnumerator(GameObject avatarObject, AvatarPerformanceStats perfStats, AvatarPerformance.IgnoreDelegate shouldIgnoreComponent)
{
int animatorCount = 0;
// Animators
List<Animator> animatorBuffer = new List<Animator>();
yield return ScanAvatarForComponentsOfType(avatarObject, animatorBuffer);
if(shouldIgnoreComponent != null)
{
animatorBuffer.RemoveAll(c => shouldIgnoreComponent(c));
}
// ReSharper disable once UselessBinaryOperation
animatorCount += animatorBuffer.Count;
// Animations
List<Animation> animationBuffer = new List<Animation>();
yield return ScanAvatarForComponentsOfType(avatarObject, animationBuffer);
if(shouldIgnoreComponent != null)
{
animationBuffer.RemoveAll(c => shouldIgnoreComponent(c));
}
animatorCount += animationBuffer.Count;
perfStats.animatorCount = animatorCount;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 08c8e931d0544866a0f626855d9c1841
timeCreated: 1561251363
@@ -0,0 +1,29 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRCSDK2.Validation.Performance.Stats;
namespace VRCSDK2.Validation.Performance.Scanners
{
#if VRC_CLIENT
[CreateAssetMenu(
fileName = "New AudioPerformanceScanner",
menuName = "VRC Scriptable Objects/Performance/Avatar/Scanners/AudioPerformanceScanner"
)]
#endif
public sealed class AudioPerformanceScanner : AbstractPerformanceScanner
{
public override IEnumerator RunPerformanceScanEnumerator(GameObject avatarObject, AvatarPerformanceStats perfStats, AvatarPerformance.IgnoreDelegate shouldIgnoreComponent)
{
// Audio Sources
List<AudioSource> audioSourceBuffer = new List<AudioSource>();
yield return ScanAvatarForComponentsOfType(avatarObject, audioSourceBuffer);
if(shouldIgnoreComponent != null)
{
audioSourceBuffer.RemoveAll(c => shouldIgnoreComponent(c));
}
perfStats.audioSourceCount = audioSourceBuffer.Count;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b3a8bba736414d1aaa9e766da27b56b5
timeCreated: 1561255618
@@ -0,0 +1,48 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
using VRCSDK2.Validation.Performance.Stats;
namespace VRCSDK2.Validation.Performance.Scanners
{
#if VRC_CLIENT
[CreateAssetMenu(
fileName = "New ClothPerformanceScanner",
menuName = "VRC Scriptable Objects/Performance/Avatar/Scanners/ClothPerformanceScanner"
)]
#endif
public sealed class ClothPerformanceScanner : AbstractPerformanceScanner
{
public override IEnumerator RunPerformanceScanEnumerator(GameObject avatarObject, AvatarPerformanceStats perfStats, AvatarPerformance.IgnoreDelegate shouldIgnoreComponent)
{
// Cloth
List<Cloth> clothBuffer = new List<Cloth>();
yield return ScanAvatarForComponentsOfType(avatarObject, clothBuffer);
if(shouldIgnoreComponent != null)
{
clothBuffer.RemoveAll(c => shouldIgnoreComponent(c));
}
int totalClothVertices = 0;
foreach(Cloth cloth in clothBuffer)
{
if(cloth == null)
{
continue;
}
Vector3[] clothVertices = cloth.vertices;
if(clothVertices == null)
{
continue;
}
totalClothVertices += clothVertices.Length;
}
perfStats.clothCount = clothBuffer.Count;
perfStats.clothMaxVertices = totalClothVertices;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0cec88b5a46f459195f10a2f11fddb2f
timeCreated: 1561255843
@@ -0,0 +1,191 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.Profiling;
using VRCSDK2.Validation.Performance.Stats;
namespace VRCSDK2.Validation.Performance.Scanners
{
#if VRC_CLIENT
[CreateAssetMenu(
fileName = "New DynamicBonePerformanceScanner",
menuName = "VRC Scriptable Objects/Performance/Avatar/Scanners/DynamicBonePerformanceScanner"
)]
#endif
public sealed class DynamicBonePerformanceScanner : AbstractPerformanceScanner
{
private Type _dynamicBoneType;
private FieldInfo _dynamicBoneRootFieldInfo;
private FieldInfo _dynamicBoneExclusionsFieldInfo;
private FieldInfo _dynamicBoneCollidersFieldInfo;
private FieldInfo _dynamicBoneEndLengthFieldInfo;
private FieldInfo _dynamicBoneEndOffsetFieldInfo;
private void Awake()
{
FindDynamicBoneTypes();
}
public override IEnumerator RunPerformanceScanEnumerator(GameObject avatarObject, AvatarPerformanceStats perfStats, AvatarPerformance.IgnoreDelegate shouldIgnoreComponent)
{
if(_dynamicBoneType == null)
{
yield break;
}
// Dynamic Bone as Component
List<Component> dynamicBoneComponentBuffer = new List<Component>();
List<object> dynamicBoneColliderObjectBuffer = new List<object>();
yield return ScanAvatarForComponentsOfType(_dynamicBoneType, avatarObject, dynamicBoneComponentBuffer);
if(shouldIgnoreComponent != null)
{
dynamicBoneComponentBuffer.RemoveAll(c => shouldIgnoreComponent(c));
}
int totalSimulatedBoneCount = 0;
int totalCollisionChecks = 0;
Profiler.BeginSample("Analyze Dynamic Bones");
foreach(Component dynamicBone in dynamicBoneComponentBuffer)
{
Profiler.BeginSample("Single Dynamic Bone Component");
int simulatedBones = 0;
// Add extra bones to the end of each chain if end bones are being used.
float endLength = (float)_dynamicBoneEndLengthFieldInfo.GetValue(dynamicBone);
Vector3 endOffset = (Vector3)_dynamicBoneEndOffsetFieldInfo.GetValue(dynamicBone);
bool hasEndBones = endLength > 0 || endOffset != Vector3.zero;
Transform root = (Transform)_dynamicBoneRootFieldInfo.GetValue(dynamicBone);
if(root != null)
{
List<Transform> exclusions = (List<Transform>)_dynamicBoneExclusionsFieldInfo.GetValue(dynamicBone);
// Calculate number of simulated bones for the hierarchy
simulatedBones = CountTransformsRecursively(root, exclusions, hasEndBones);
totalSimulatedBoneCount += simulatedBones;
}
int colliderListEntryCount = 0;
IList colliderList = (IList)_dynamicBoneCollidersFieldInfo.GetValue(dynamicBone);
if(colliderList != null)
{
foreach(object collider in colliderList)
{
colliderListEntryCount += 1;
if(collider != null && !dynamicBoneColliderObjectBuffer.Contains(collider))
{
dynamicBoneColliderObjectBuffer.Add(collider);
}
}
}
// The root bone is skipped in collision checks.
totalCollisionChecks += (simulatedBones - 1) * colliderListEntryCount;
Profiler.EndSample();
}
Profiler.EndSample();
yield return null;
perfStats.dynamicBoneComponentCount = dynamicBoneComponentBuffer.Count;
perfStats.dynamicBoneSimulatedBoneCount = totalSimulatedBoneCount;
perfStats.dynamicBoneColliderCount = dynamicBoneColliderObjectBuffer.Count;
perfStats.dynamicBoneCollisionCheckCount = totalCollisionChecks;
}
private void FindDynamicBoneTypes()
{
if(_dynamicBoneType != null)
{
return;
}
Type dyBoneType = ValidationUtils.GetTypeFromName("DynamicBone");
if(dyBoneType == null)
{
return;
}
Type dyBoneColliderType = ValidationUtils.GetTypeFromName("DynamicBoneColliderBase") ?? ValidationUtils.GetTypeFromName("DynamicBoneCollider");
if(dyBoneColliderType == null)
{
return;
}
FieldInfo rootFieldInfo = dyBoneType.GetField("m_Root", BindingFlags.Public | BindingFlags.Instance);
if(rootFieldInfo == null || rootFieldInfo.FieldType != typeof(Transform))
{
return;
}
FieldInfo exclusionsFieldInfo = dyBoneType.GetField("m_Exclusions", BindingFlags.Public | BindingFlags.Instance);
if(exclusionsFieldInfo == null || exclusionsFieldInfo.FieldType != typeof(List<Transform>))
{
return;
}
FieldInfo collidersFieldInfo = dyBoneType.GetField("m_Colliders", BindingFlags.Public | BindingFlags.Instance);
if(collidersFieldInfo == null || collidersFieldInfo.FieldType.GetGenericTypeDefinition() != typeof(List<>) ||
collidersFieldInfo.FieldType.GetGenericArguments().Single() != dyBoneColliderType)
{
return;
}
FieldInfo endLengthFieldInfo = dyBoneType.GetField("m_EndLength", BindingFlags.Public | BindingFlags.Instance);
if(endLengthFieldInfo == null || endLengthFieldInfo.FieldType != typeof(float))
{
return;
}
FieldInfo endOffsetFieldInfo = dyBoneType.GetField("m_EndOffset", BindingFlags.Public | BindingFlags.Instance);
if(endOffsetFieldInfo == null || endOffsetFieldInfo.FieldType != typeof(Vector3))
{
return;
}
_dynamicBoneType = dyBoneType;
_dynamicBoneRootFieldInfo = rootFieldInfo;
_dynamicBoneExclusionsFieldInfo = exclusionsFieldInfo;
_dynamicBoneCollidersFieldInfo = collidersFieldInfo;
_dynamicBoneEndLengthFieldInfo = endLengthFieldInfo;
_dynamicBoneEndOffsetFieldInfo = endOffsetFieldInfo;
}
// Like DynamicBone itself exclusions only apply to children of the current bone.
// This means the root bone itself never excluded.
private static int CountTransformsRecursively(Transform transform, List<Transform> exclusions, bool addEndBones)
{
if(transform == null)
{
return 0;
}
int count = 1;
int childCount = transform.childCount;
if(childCount > 0)
{
foreach(Transform child in transform)
{
if(exclusions == null || !exclusions.Contains(child))
{
count += CountTransformsRecursively(child, exclusions, addEndBones);
}
}
}
else
{
if(addEndBones)
{
count++;
}
}
return count;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a226df494ef04404a9a47c714822ab9f
timeCreated: 1561251560
@@ -0,0 +1,30 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
using VRCSDK2.Validation.Performance.Stats;
namespace VRCSDK2.Validation.Performance.Scanners
{
#if VRC_CLIENT
[CreateAssetMenu(
fileName = "New LightPerformanceScanner",
menuName = "VRC Scriptable Objects/Performance/Avatar/Scanners/LightPerformanceScanner"
)]
#endif
public sealed class LightPerformanceScanner : AbstractPerformanceScanner
{
public override IEnumerator RunPerformanceScanEnumerator(GameObject avatarObject, AvatarPerformanceStats perfStats, AvatarPerformance.IgnoreDelegate shouldIgnoreComponent)
{
// Lights
List<Light> lightBuffer = new List<Light>();
yield return ScanAvatarForComponentsOfType(avatarObject, lightBuffer);
if(shouldIgnoreComponent != null)
{
lightBuffer.RemoveAll(c => shouldIgnoreComponent(c));
}
perfStats.lightCount = lightBuffer.Count;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 405778fdc32c44c1bb9fdd0476fb0007
timeCreated: 1561256390
@@ -0,0 +1,32 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
using VRCSDK2.Validation.Performance.Stats;
namespace VRCSDK2.Validation.Performance.Scanners
{
#if VRC_CLIENT
[CreateAssetMenu(
fileName = "New LineRendererPerformanceScanner",
menuName = "VRC Scriptable Objects/Performance/Avatar/Scanners/LineRendererPerformanceScanner"
)]
#endif
public sealed class LineRendererPerformanceScanner : AbstractPerformanceScanner
{
public override IEnumerator RunPerformanceScanEnumerator(GameObject avatarObject, AvatarPerformanceStats perfStats, AvatarPerformance.IgnoreDelegate shouldIgnoreComponent)
{
// Line Renderers
List<LineRenderer> lineRendererBuffer = new List<LineRenderer>();
yield return ScanAvatarForComponentsOfType(avatarObject, lineRendererBuffer);
if(shouldIgnoreComponent != null)
{
lineRendererBuffer.RemoveAll(c => shouldIgnoreComponent(c));
}
int numLineRenderers = lineRendererBuffer.Count;
perfStats.lineRendererCount = numLineRenderers;
perfStats.materialCount = perfStats.materialCount.GetValueOrDefault() + numLineRenderers;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ec87392b85844f7bb526a48ec866a8f0
timeCreated: 1561253047
@@ -0,0 +1,266 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
using VRCSDK2.Validation.Performance.Stats;
namespace VRCSDK2.Validation.Performance.Scanners
{
#if VRC_CLIENT
[CreateAssetMenu(
fileName = "New MeshPerformanceScanner",
menuName = "VRC Scriptable Objects/Performance/Avatar/Scanners/MeshPerformanceScanner"
)]
#endif
public sealed class MeshPerformanceScanner : AbstractPerformanceScanner
{
public override IEnumerator RunPerformanceScanEnumerator(GameObject avatarObject, AvatarPerformanceStats perfStats, AvatarPerformance.IgnoreDelegate shouldIgnoreComponent)
{
// Renderers
List<Renderer> rendererBuffer = new List<Renderer>(16);
yield return ScanAvatarForComponentsOfType(avatarObject, rendererBuffer);
if(shouldIgnoreComponent != null)
{
rendererBuffer.RemoveAll(c => shouldIgnoreComponent(c));
}
yield return AnalyzeGeometry(avatarObject, rendererBuffer, perfStats);
AnalyzeMeshRenderers(rendererBuffer, perfStats);
AnalyzeSkinnedMeshRenderers(rendererBuffer, perfStats);
yield return null;
}
private static uint CalculateRendererPolyCount(Renderer renderer)
{
Mesh sharedMesh = null;
SkinnedMeshRenderer skinnedMeshRenderer = renderer as SkinnedMeshRenderer;
if(skinnedMeshRenderer != null)
{
sharedMesh = skinnedMeshRenderer.sharedMesh;
}
if(sharedMesh == null)
{
MeshRenderer meshRenderer = renderer as MeshRenderer;
if(meshRenderer != null)
{
MeshFilter meshFilter = meshRenderer.GetComponent<MeshFilter>();
if(meshFilter != null)
{
sharedMesh = meshFilter.sharedMesh;
}
}
}
if(sharedMesh == null)
{
return 0;
}
return MeshUtils.GetMeshTriangleCount(sharedMesh);
}
private static bool RendererHasMesh(Renderer renderer)
{
MeshRenderer meshRenderer = renderer as MeshRenderer;
if(meshRenderer != null)
{
MeshFilter meshFilter = meshRenderer.GetComponent<MeshFilter>();
if(meshFilter == null)
{
return false;
}
return meshFilter.sharedMesh != null;
}
SkinnedMeshRenderer skinnedMeshRenderer = renderer as SkinnedMeshRenderer;
if(skinnedMeshRenderer != null)
{
return skinnedMeshRenderer.sharedMesh != null;
}
return false;
}
private IEnumerator AnalyzeGeometry(GameObject avatarObject, IEnumerable<Renderer> renderers, AvatarPerformanceStats perfStats)
{
List<Renderer> lodGroupRendererIgnoreBuffer = new List<Renderer>(16);
List<LODGroup> lodBuffer = new List<LODGroup>(16);
ulong polyCount = 0;
Bounds bounds = new Bounds(avatarObject.transform.position, Vector3.zero);
yield return ScanAvatarForComponentsOfType(avatarObject, lodBuffer);
try
{
foreach(LODGroup lodGroup in lodBuffer)
{
LOD[] lodLevels = lodGroup.GetLODs();
ulong highestLodPolyCount = 0;
foreach(LOD lod in lodLevels)
{
uint thisLodPolyCount = 0;
foreach(Renderer renderer in lod.renderers)
{
lodGroupRendererIgnoreBuffer.Add(renderer);
checked
{
thisLodPolyCount += CalculateRendererPolyCount(renderer);
}
}
if(thisLodPolyCount > highestLodPolyCount)
{
highestLodPolyCount = thisLodPolyCount;
}
}
checked
{
polyCount += highestLodPolyCount;
}
}
}
catch(OverflowException e)
{
VRC.Core.Logger.Log("Overflow exception while analyzing geometry, assuming max value:" + e.ToString(), VRC.Core.DebugLevel.All);
polyCount = uint.MaxValue;
}
Profiler.BeginSample("Calculate Total Polygon Count and Bounds");
foreach(Renderer renderer in renderers)
{
Profiler.BeginSample("Single Renderer");
if(renderer is MeshRenderer || renderer is SkinnedMeshRenderer)
{
if(!RendererHasMesh(renderer))
{
Profiler.EndSample();
continue;
}
bounds.Encapsulate(renderer.bounds);
}
if(lodGroupRendererIgnoreBuffer.Contains(renderer))
{
Profiler.EndSample();
continue;
}
polyCount += CalculateRendererPolyCount(renderer);
Profiler.EndSample();
}
Profiler.EndSample();
bounds.center -= avatarObject.transform.position;
lodGroupRendererIgnoreBuffer.Clear();
lodBuffer.Clear();
perfStats.polyCount = polyCount > int.MaxValue ? int.MaxValue : (int)polyCount;
perfStats.aabb = bounds;
}
private static void AnalyzeSkinnedMeshRenderers(IEnumerable<Renderer> renderers, AvatarPerformanceStats perfStats)
{
Profiler.BeginSample("AnalyzeSkinnedMeshRenderers");
int count = 0;
int materialSlots = 0;
int skinnedBoneCount = 0;
HashSet<Transform> transformIgnoreBuffer = new HashSet<Transform>();
foreach(Renderer renderer in renderers)
{
Profiler.BeginSample("Analyze SkinnedMeshRenderer");
SkinnedMeshRenderer skinnedMeshRenderer = renderer as SkinnedMeshRenderer;
if(skinnedMeshRenderer == null)
{
Profiler.EndSample();
continue;
}
count++;
Mesh sharedMesh = skinnedMeshRenderer.sharedMesh;
if(sharedMesh != null)
{
materialSlots += sharedMesh.subMeshCount;
}
// bone count
Profiler.BeginSample("Count Bones");
Transform[] bones = skinnedMeshRenderer.bones;
foreach(Transform bone in bones)
{
Profiler.BeginSample("Count Bone");
if(bone == null || transformIgnoreBuffer.Contains(bone))
{
Profiler.EndSample();
continue;
}
transformIgnoreBuffer.Add(bone);
skinnedBoneCount++;
Profiler.EndSample();
}
Profiler.EndSample();
Profiler.EndSample();
}
transformIgnoreBuffer.Clear();
Profiler.EndSample();
perfStats.skinnedMeshCount = count;
perfStats.boneCount = skinnedBoneCount;
perfStats.materialCount = perfStats.materialCount.GetValueOrDefault() + materialSlots;
}
private static void AnalyzeMeshRenderers(IEnumerable<Renderer> renderers, AvatarPerformanceStats perfStats)
{
Profiler.BeginSample("AnalyzeMeshRenderers");
int count = 0;
int materialSlots = 0;
foreach(Renderer renderer in renderers)
{
Profiler.BeginSample("Analyze MeshRenderer");
MeshRenderer meshRenderer = renderer as MeshRenderer;
if(meshRenderer == null)
{
Profiler.EndSample();
continue;
}
count++;
Profiler.BeginSample("Get MeshFilter");
MeshFilter meshFilter = meshRenderer.GetComponent<MeshFilter>();
Profiler.EndSample();
if(meshFilter == null)
{
Profiler.EndSample();
continue;
}
Mesh sharedMesh = meshFilter.sharedMesh;
if(sharedMesh != null)
{
materialSlots += sharedMesh.subMeshCount;
}
}
Profiler.EndSample();
perfStats.meshCount = count;
perfStats.materialCount = perfStats.materialCount.GetValueOrDefault() + materialSlots;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 38bca10261df4ddfa10cff3b3bbb9428
timeCreated: 1561249198
@@ -0,0 +1,114 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
using VRCSDK2.Validation.Performance.Stats;
namespace VRCSDK2.Validation.Performance.Scanners
{
#if VRC_CLIENT
[CreateAssetMenu(
fileName = "New ParticlePerformanceScanner",
menuName = "VRC Scriptable Objects/Performance/Avatar/Scanners/ParticlePerformanceScanner"
)]
#endif
public sealed class ParticlePerformanceScanner : AbstractPerformanceScanner
{
public override IEnumerator RunPerformanceScanEnumerator(GameObject avatarObject, AvatarPerformanceStats perfStats, AvatarPerformance.IgnoreDelegate shouldIgnoreComponent)
{
// Particle Systems
List<ParticleSystem> particleSystemBuffer = new List<ParticleSystem>();
yield return ScanAvatarForComponentsOfType(avatarObject, particleSystemBuffer);
if(shouldIgnoreComponent != null)
{
particleSystemBuffer.RemoveAll(c => shouldIgnoreComponent(c));
}
AnalyzeParticleSystemRenderers(particleSystemBuffer, perfStats);
yield return null;
}
private static void AnalyzeParticleSystemRenderers(IEnumerable<ParticleSystem> particleSystems, AvatarPerformanceStats perfStats)
{
int particleSystemCount = 0;
ulong particleTotalCount = 0;
ulong particleTotalMaxMeshPolyCount = 0;
bool particleTrailsEnabled = false;
bool particleCollisionEnabled = false;
int materialSlots = 0;
Profiler.BeginSample("AnalyzeParticleSystemRenderers");
foreach(ParticleSystem particleSystem in particleSystems)
{
Profiler.BeginSample("Single Particle System");
int particleCount = particleSystem.main.maxParticles;
if(particleCount <= 0)
{
Profiler.EndSample();
continue;
}
particleSystemCount++;
particleTotalCount += (uint)particleCount;
ParticleSystemRenderer particleSystemRenderer = particleSystem.GetComponent<ParticleSystemRenderer>();
if(particleSystemRenderer == null)
{
Profiler.EndSample();
continue;
}
materialSlots++;
// mesh particles
if(particleSystemRenderer.renderMode == ParticleSystemRenderMode.Mesh && particleSystemRenderer.meshCount > 0)
{
uint highestPolyCount = 0;
Mesh[] meshes = new Mesh[particleSystemRenderer.meshCount];
int particleRendererMeshCount = particleSystemRenderer.GetMeshes(meshes);
for(int meshIndex = 0; meshIndex < particleRendererMeshCount; meshIndex++)
{
Mesh mesh = meshes[meshIndex];
if(mesh == null)
{
continue;
}
uint polyCount = MeshUtils.GetMeshTriangleCount(mesh);
if(polyCount > highestPolyCount)
{
highestPolyCount = polyCount;
}
}
ulong maxMeshParticlePolyCount = (uint)particleCount * highestPolyCount;
particleTotalMaxMeshPolyCount += maxMeshParticlePolyCount;
}
if(particleSystem.trails.enabled)
{
particleTrailsEnabled = true;
materialSlots++;
}
if(particleSystem.collision.enabled)
{
particleCollisionEnabled = true;
}
Profiler.EndSample();
}
Profiler.EndSample();
perfStats.particleSystemCount = particleSystemCount;
perfStats.particleTotalCount = particleTotalCount > int.MaxValue ? int.MaxValue : (int)particleTotalCount;
perfStats.particleMaxMeshPolyCount = particleTotalMaxMeshPolyCount > int.MaxValue ? int.MaxValue : (int)particleTotalMaxMeshPolyCount;
perfStats.particleTrailsEnabled = particleTrailsEnabled;
perfStats.particleCollisionEnabled = particleCollisionEnabled;
perfStats.materialCount = perfStats.materialCount.GetValueOrDefault() + materialSlots;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 10723e354ff14f98a49ab797b3f005e6
timeCreated: 1561250267
@@ -0,0 +1,64 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
using VRCSDK2.Validation.Performance.Stats;
namespace VRCSDK2.Validation.Performance.Scanners
{
#if VRC_CLIENT
[CreateAssetMenu(
fileName = "New PhysicsPerformanceScanner",
menuName = "VRC Scriptable Objects/Performance/Avatar/Scanners/PhysicsPerformanceScanner"
)]
#endif
public sealed class PhysicsPerformanceScanner : AbstractPerformanceScanner
{
public override IEnumerator RunPerformanceScanEnumerator(GameObject avatarObject, AvatarPerformanceStats perfStats, AvatarPerformance.IgnoreDelegate shouldIgnoreComponent)
{
// Colliders
List<Collider> colliderBuffer = new List<Collider>();
yield return ScanAvatarForComponentsOfType(avatarObject, colliderBuffer);
colliderBuffer.RemoveAll(
o =>
{
if(shouldIgnoreComponent != null && shouldIgnoreComponent(o))
{
return true;
}
if(o.GetComponent<VRC.SDKBase.VRCStation>() != null)
{
return true;
}
return false;
}
);
perfStats.physicsColliderCount = colliderBuffer.Count;
// Rigidbodies
List<Rigidbody> rigidbodyBuffer = new List<Rigidbody>();
yield return ScanAvatarForComponentsOfType(avatarObject, rigidbodyBuffer);
rigidbodyBuffer.RemoveAll(
o =>
{
if(shouldIgnoreComponent != null && shouldIgnoreComponent(o))
{
return true;
}
if(o.GetComponent<VRC.SDKBase.VRCStation>() != null)
{
return true;
}
return false;
}
);
perfStats.physicsRigidbodyCount = rigidbodyBuffer.Count;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6a94ecdeecd04f85824cc3244be5712a
timeCreated: 1561256481
@@ -0,0 +1,32 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
using VRCSDK2.Validation.Performance.Stats;
namespace VRCSDK2.Validation.Performance.Scanners
{
#if VRC_CLIENT
[CreateAssetMenu(
fileName = "New TrailRendererPerformanceScanner",
menuName = "VRC Scriptable Objects/Performance/Avatar/Scanners/TrailRendererPerformanceScanner"
)]
#endif
public sealed class TrailRendererPerformanceScanner : AbstractPerformanceScanner
{
public override IEnumerator RunPerformanceScanEnumerator(GameObject avatarObject, AvatarPerformanceStats perfStats, AvatarPerformance.IgnoreDelegate shouldIgnoreComponent)
{
// Trail Renderers
List<TrailRenderer> trailRendererBuffer = new List<TrailRenderer>();
yield return ScanAvatarForComponentsOfType(avatarObject, trailRendererBuffer);
if(shouldIgnoreComponent != null)
{
trailRendererBuffer.RemoveAll(c => shouldIgnoreComponent(c));
}
int numTrailRenderers = trailRendererBuffer.Count;
perfStats.trailRendererCount = numTrailRenderers;
perfStats.materialCount = perfStats.materialCount.GetValueOrDefault() + numTrailRenderers;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2efd714b564547b4be1ebd1f2700668b
timeCreated: 1561251810