https://docs.vrchat.com/docs/avatar-performance-ranking-system
https://clustervr.gitbook.io/sdk/avatar_customization/avatar_limit
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEditor; | |
using System.Linq; | |
namespace Gatosyocora | |
{ | |
public class AvatarPerformance : EditorWindow | |
{ | |
private int objectCount = 0; | |
private int triangleCount = 0; // | |
private int boneCount = 0; // | |
private int skinnedRendererCount = 0; | |
private int materlaiSlotsCount = 0; | |
private int rendererCount = 0; // | |
private int dynamicBoneCount = 0; | |
private int dynamicBoneColliderCount = 0; // | |
private int lightCount = 0; | |
private int animatorCount = 0; | |
private int trailRendererCount = 0; | |
private int lineRendererCount = 0; | |
private int clothCount = 0; | |
private int colliderCount = 0; | |
private int rigidbodyCount = 0; | |
private int audioSourceCount = 0; | |
private GameObject avatar; | |
private enum PlatformType | |
{ | |
VRCHAT, CLUSTER, NONE | |
} | |
private PlatformType type = PlatformType.NONE; | |
[MenuItem("Avatar/Performance")] | |
private static void Open() | |
{ | |
GetWindow<AvatarPerformance>(); | |
} | |
private void OnGUI() | |
{ | |
using (var check = new EditorGUI.ChangeCheckScope()) | |
{ | |
avatar = EditorGUILayout.ObjectField( | |
"avatar", | |
avatar, | |
typeof(GameObject), | |
true | |
) as GameObject; | |
type = (PlatformType)EditorGUILayout.EnumPopup("Platform", type); | |
if (check.changed && avatar != null) | |
{ | |
if (type == PlatformType.VRCHAT) | |
CheckPerformanceForVRChat(); | |
else if (type == PlatformType.CLUSTER) | |
CheckPerformanceForCluster(); | |
} | |
} | |
if (type == PlatformType.VRCHAT) | |
PerformanceGUIForVRChat(); | |
else if (type == PlatformType.CLUSTER) | |
PerformanceGUIForCluster(); | |
} | |
private void CheckPerformanceForVRChat() | |
{ | |
triangleCount = GetAvatarTriangleCount(avatar, true); | |
boneCount = GetAvatarBoneCount(avatar, true); | |
skinnedRendererCount = GetAvatarComponentCount<SkinnedMeshRenderer>(avatar, true); | |
materlaiSlotsCount = GetAvatarMaterialSlotsCount(avatar, true); | |
rendererCount = GetAvatarComponentCount<MeshRenderer>(avatar, false); | |
dynamicBoneCount = GetAvatarComponentCount<DynamicBone>(avatar, true); | |
dynamicBoneColliderCount = GetAvatarComponentCount<DynamicBoneCollider>(avatar, false); | |
lightCount = GetAvatarComponentCount<Light>(avatar, false); | |
animatorCount = GetAvatarComponentCount<Animator>(avatar, true); | |
trailRendererCount = GetAvatarComponentCount<TrailRenderer>(avatar, true); | |
lineRendererCount = GetAvatarComponentCount<LineRenderer>(avatar, true); | |
clothCount = GetAvatarComponentCount<Cloth>(avatar, true); | |
colliderCount = GetAvatarComponentCount<Collider>(avatar, true); | |
rigidbodyCount = GetAvatarComponentCount<Rigidbody>(avatar, true); | |
audioSourceCount = GetAvatarComponentCount<AudioSource>(avatar, true); | |
} | |
private void PerformanceGUIForVRChat() | |
{ | |
EditorGUILayout.LabelField("Triangles", triangleCount + ""); | |
EditorGUILayout.LabelField("Bones", boneCount + ""); | |
EditorGUILayout.LabelField("Skinned Mesh Renderers", skinnedRendererCount + ""); | |
EditorGUILayout.LabelField("Material Slots", materlaiSlotsCount + ""); | |
EditorGUILayout.LabelField("Mesh Renderers", rendererCount + ""); | |
EditorGUILayout.LabelField("Dynamic Bones", dynamicBoneCount + ""); | |
EditorGUILayout.LabelField("Dynamic Bone Colliders", dynamicBoneColliderCount + ""); | |
EditorGUILayout.LabelField("Lights", lightCount + ""); | |
EditorGUILayout.LabelField("Animators", animatorCount + ""); | |
EditorGUILayout.LabelField("Trail Renderers", trailRendererCount + ""); | |
EditorGUILayout.LabelField("Line Renderers", lineRendererCount + ""); | |
EditorGUILayout.LabelField("Clothes", clothCount + ""); | |
EditorGUILayout.LabelField("Colliders", colliderCount + ""); | |
EditorGUILayout.LabelField("Rigidbodys", rigidbodyCount + ""); | |
EditorGUILayout.LabelField("Audio Sources", audioSourceCount + ""); | |
} | |
private void CheckPerformanceForCluster() | |
{ | |
objectCount = GetAvatarComponentCount<Transform>(avatar, true); | |
triangleCount = GetAvatarTriangleCount(avatar, true); | |
boneCount = GetAvatarBoneCount(avatar, true); | |
} | |
private void PerformanceGUIForCluster() | |
{ | |
EditorGUILayout.LabelField("Objects", objectCount + ""); | |
EditorGUILayout.LabelField("Triangles", triangleCount + ""); | |
EditorGUILayout.LabelField("Bones", boneCount + ""); | |
} | |
// ポリゴン数 | |
private static int GetAvatarTriangleCount(GameObject avatarRootObj, bool containDisableObject) | |
{ | |
return avatarRootObj | |
.GetComponentsInChildren<SkinnedMeshRenderer>(containDisableObject) | |
.Where(x => x.sharedMesh != null) | |
.Select(x => x.sharedMesh.triangles.Length / 3) | |
.Sum() | |
+ avatarRootObj | |
.GetComponentsInChildren<MeshFilter>(containDisableObject) | |
.Where(x => x.sharedMesh != null) | |
.Select(x => x.sharedMesh.triangles.Length / 3) | |
.Sum(); | |
} | |
// ボーン数 | |
private static int GetAvatarBoneCount(GameObject avatarRootObj, bool containDisableObject) | |
{ | |
return avatarRootObj | |
.GetComponentsInChildren<SkinnedMeshRenderer>(containDisableObject) | |
.Where(x => x.bones != null) | |
.SelectMany(x => x.bones) | |
.Distinct() | |
.Count(); | |
} | |
// 任意のコンポーネントの数 | |
private static int GetAvatarComponentCount<T>(GameObject avatarRootObj, bool containDisableObject) | |
{ | |
return avatarRootObj.GetComponentsInChildren<T>(containDisableObject).Count(); | |
} | |
// マテリアル, サブメッシュの数 | |
private static int GetAvatarMaterialSlotsCount(GameObject avatarRootObj, bool containDisableObject) | |
{ | |
return avatarRootObj | |
.GetComponentsInChildren<SkinnedMeshRenderer>(containDisableObject) | |
.Where(x => x.sharedMaterials != null) | |
.Select(x => x.sharedMaterials.Length) | |
.Sum() | |
+ avatarRootObj | |
.GetComponentsInChildren<MeshRenderer>(containDisableObject) | |
.Where(x => x.sharedMaterials != null) | |
.Select(x => x.sharedMaterials.Length) | |
.Sum(); | |
} | |
} | |
} |