added package SceneProfiler

This commit is contained in:
Dominik Gut 2025-05-08 10:30:32 +02:00
parent 14fa4fb4ee
commit 5b3290f486
61 changed files with 5189 additions and 0 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1e9de99891353f047bfc293d0de6b9fa
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6fa52901a83eb5948a65c9837a1590fb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,885 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 9
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 0
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 12
m_GIWorkflowMode: 1
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 1
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 12
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_ExtractAmbientOcclusion: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 256
m_ReflectionCompression: 2
m_MixedBakeMode: 2
m_BakeBackend: 1
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 512
m_PVRBounces: 2
m_PVREnvironmentSampleCount: 256
m_PVREnvironmentReferencePointCount: 2048
m_PVRFilteringMode: 1
m_PVRDenoiserTypeDirect: 1
m_PVRDenoiserTypeIndirect: 1
m_PVRDenoiserTypeAO: 1
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVREnvironmentMIS: 1
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0}
m_LightingSettings: {fileID: 0}
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 3
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
buildHeightMesh: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &307962993
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 307962995}
- component: {fileID: 307962994}
m_Layer: 0
m_Name: Directional Light
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!108 &307962994
Light:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 307962993}
m_Enabled: 1
serializedVersion: 10
m_Type: 1
m_Shape: 0
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
m_Intensity: 1
m_Range: 10
m_SpotAngle: 30
m_InnerSpotAngle: 21.80208
m_CookieSize: 10
m_Shadows:
m_Type: 2
m_Resolution: -1
m_CustomResolution: -1
m_Strength: 1
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
m_CullingMatrixOverride:
e00: 1
e01: 0
e02: 0
e03: 0
e10: 0
e11: 1
e12: 0
e13: 0
e20: 0
e21: 0
e22: 1
e23: 0
e30: 0
e31: 0
e32: 0
e33: 1
m_UseCullingMatrixOverride: 0
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
m_RenderMode: 0
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingLayerMask: 1
m_Lightmapping: 4
m_LightShadowCasterMode: 0
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
m_UseBoundingSphereOverride: 0
m_UseViewFrustumForShadowCasterCull: 1
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &307962995
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 307962993}
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: 0, y: 3, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!1 &1214143739
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1214143742}
- component: {fileID: 1214143741}
- component: {fileID: 1214143740}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &1214143740
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1214143739}
m_Enabled: 1
--- !u!20 &1214143741
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1214143739}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 0
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 1
m_AllowMSAA: 1
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &1214143742
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1214143739}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 5
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1498584708
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1498584712}
- component: {fileID: 1498584711}
- component: {fileID: 1498584710}
- component: {fileID: 1498584709}
m_Layer: 5
m_Name: Canvas
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1498584709
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1498584708}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreReversedGraphics: 1
m_BlockingObjects: 0
m_BlockingMask:
serializedVersion: 2
m_Bits: 4294967295
--- !u!114 &1498584710
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1498584708}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier:
m_UiScaleMode: 0
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 800, y: 600}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 3
m_FallbackScreenDPI: 96
m_DefaultSpriteDPI: 96
m_DynamicPixelsPerUnit: 1
m_PresetInfoIsWorld: 0
--- !u!223 &1498584711
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1498584708}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 0
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_AdditionalShaderChannelsFlag: 25
m_UpdateRectTransformForStandalone: 0
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
--- !u!224 &1498584712
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1498584708}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0, y: 0, z: 0}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1643728717}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!1 &1643728716
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1643728717}
- component: {fileID: 1643728720}
- component: {fileID: 1643728719}
- component: {fileID: 1643728718}
m_Layer: 5
m_Name: Button
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1643728717
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1643728716}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1498584712}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 160, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1643728718
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1643728716}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 1643728719}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &1643728719
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1643728716}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &1643728720
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1643728716}
m_CullTransparentMesh: 1
--- !u!1 &1954325613
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1954325619}
- component: {fileID: 1954325618}
- component: {fileID: 1954325617}
- component: {fileID: 1954325614}
m_Layer: 0
m_Name: GameObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!82 &1954325614
AudioSource:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1954325613}
m_Enabled: 1
serializedVersion: 4
OutputAudioMixerGroup: {fileID: 0}
m_audioClip: {fileID: 0}
m_PlayOnAwake: 1
m_Volume: 1
m_Pitch: 1
Loop: 0
Mute: 0
Spatialize: 0
SpatializePostEffects: 0
Priority: 128
DopplerLevel: 1
MinDistance: 1
MaxDistance: 500
Pan2D: 0
rolloffMode: 0
BypassEffects: 0
BypassListenerEffects: 0
BypassReverbZones: 0
rolloffCustomCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
panLevelCustomCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
spreadCustomCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
reverbZoneMixCustomCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
--- !u!65 &1954325617
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1954325613}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 2, y: 2, z: 2}
m_Center: {x: 0, y: 0, z: 0}
--- !u!54 &1954325618
Rigidbody:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1954325613}
serializedVersion: 4
m_Mass: 1
m_Drag: 0
m_AngularDrag: 0.05
m_CenterOfMass: {x: 0, y: 0, z: 0}
m_InertiaTensor: {x: 1, y: 1, z: 1}
m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_ImplicitCom: 1
m_ImplicitTensor: 1
m_UseGravity: 1
m_IsKinematic: 0
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
--- !u!4 &1954325619
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1954325613}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0.0026460872, y: -0.017538406, z: -0.013090232}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 4
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &2059176174
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2059176177}
- component: {fileID: 2059176176}
- component: {fileID: 2059176175}
m_Layer: 0
m_Name: EventSystem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &2059176175
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2059176174}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
m_Name:
m_EditorClassIdentifier:
m_SendPointerHoverToParent: 1
m_HorizontalAxis: Horizontal
m_VerticalAxis: Vertical
m_SubmitButton: Submit
m_CancelButton: Cancel
m_InputActionsPerSecond: 10
m_RepeatDelay: 0.5
m_ForceModuleActive: 0
--- !u!114 &2059176176
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2059176174}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 10
--- !u!4 &2059176177
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2059176174}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &2140946533
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2140946537}
- component: {fileID: 2140946536}
- component: {fileID: 2140946535}
- component: {fileID: 2140946534}
m_Layer: 0
m_Name: Cube
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!65 &2140946534
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2140946533}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 2, y: 2, z: 2}
m_Center: {x: 0, y: 0, z: 0}
--- !u!23 &2140946535
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2140946533}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!33 &2140946536
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2140946533}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!4 &2140946537
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2140946533}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0.0026460872, y: -0.017538406, z: -0.013090232}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: cea2d3a219a6e874ea94c6a8429b627a
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9abfc7197cb58a44580c0b3d6cc74d5d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3b1288a3b080c504189b7bdaff6fe754
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 24dcc9709443c854bad681b97c28d767
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,106 @@
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace SceneProfiler.Editor
{
public class CollectAudioClipData
{
private SceneProfiler _sceneProfiler;
public CollectAudioClipData(SceneProfiler sceneProfiler)
{
_sceneProfiler = sceneProfiler;
}
public void CheckSelectedFolder()
{
if (!_sceneProfiler.IncludeSelectedFolder || Selection.objects.Length == 0) return;
var folders = new List<string>();
foreach (var obj in Selection.objects)
{
if (obj.GetType() != typeof(DefaultAsset)) continue;
var path = AssetDatabase.GetAssetPath(obj);
folders.Add(path);
}
if (folders.Count != 0)
{
var guids = AssetDatabase.FindAssets("t:AudioClip", folders.ToArray());
if (guids.Length != 0)
{
foreach (var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
var item = AssetDatabase.LoadAssetAtPath<AudioClip>(path);
var tClipDetails = FindClipDetails(item);
if (tClipDetails == null)
{
tClipDetails = new AudioClipDetails { clip = item };
_sceneProfiler.ActiveClipDetails.Add(tClipDetails);
}
}
}
}
}
AudioClipDetails FindClipDetails(AudioClip tClip)
{
foreach (AudioClipDetails tClipDetails in _sceneProfiler.ActiveClipDetails)
{
if (tClipDetails.clip == tClip) return tClipDetails;
}
return null;
}
public void CheckAudioSources()
{
AudioSource[] AudioSources = _sceneProfiler.FindObjects<AudioSource>();
foreach (AudioSource tAudioSource in AudioSources)
{
AudioClip tClip = tAudioSource.clip;
if (tClip != null)
{
AudioClipDetails tClipDetails = FindClipDetails(tClip);
if (tClipDetails == null)
{
tClipDetails = new AudioClipDetails { clip = tClip };
_sceneProfiler.ActiveClipDetails.Add(tClipDetails);
}
tClipDetails.FoundInAudioSources.Add(tAudioSource);
}
else
{
Missing tMissing = new Missing
{
Object = tAudioSource.transform,
type = "audio clip",
name = tAudioSource.transform.name
};
_sceneProfiler.MissingObjects.Add(tMissing);
_sceneProfiler.thingsMissing = true;
}
}
}
public void CheckAudioClipReferences(FieldInfo field, MonoBehaviour script)
{
if (field.FieldType == typeof(AudioClip))
{
AudioClip tClip = field.GetValue(script) as AudioClip;
if (tClip != null)
{
AudioClipDetails tClipDetails = FindClipDetails(tClip);
if (tClipDetails == null)
{
tClipDetails = new AudioClipDetails { clip = tClip };
_sceneProfiler.ActiveClipDetails.Add(tClipDetails);
}
}
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c325a9bb57aa25d4193e3fe4e6dfe6ec
timeCreated: 1720311294

View File

@ -0,0 +1,92 @@
using System.Collections.Generic;
using UnityEngine;
namespace SceneProfiler.Editor
{
public class CollectExpensiveObject
{
private SceneProfiler _sceneProfiler;
private const int HierarchyDepthThreshold = 7;
private const int ComponentCountThreshold = 5;
public CollectExpensiveObject(SceneProfiler sceneProfiler)
{
_sceneProfiler = sceneProfiler;
}
public void CollectData()
{
_sceneProfiler.ActiveExpensiveObjects.Clear();
List<GameObject> allObjects = _sceneProfiler.FindAllGameObjects();
foreach (GameObject obj in allObjects)
{
if (obj == null) continue;
if (obj.transform.localScale != Vector3.one)
{
AddExpensiveObjectDetails(obj, "Scale");
}
}
foreach (GameObject obj in allObjects)
{
if (obj == null) continue;
if (GetHierarchyDepth(obj.transform) > HierarchyDepthThreshold)
{
AddExpensiveObjectDetails(obj, "Hierarchy");
}
}
foreach (GameObject obj in allObjects)
{
if (obj == null) continue;
if (obj.GetComponents<Component>().Length > ComponentCountThreshold)
{
AddExpensiveObjectDetails(obj, "Components");
}
}
}
private void AddExpensiveObjectDetails(GameObject obj, string type)
{
ExpensiveObjectDetails details = new ExpensiveObjectDetails(obj);
switch (type)
{
case "Scale":
details.scaleType = IsUniformScale(obj.transform.localScale) ? "Uniform" : "NonUniform";
details.scale = obj.transform.localScale;
break;
case "Hierarchy":
details.hierarchyDepth = GetHierarchyDepth(obj.transform);
break;
case "Components":
details.componentCount = obj.GetComponents<Component>().Length;
break;
}
if (!_sceneProfiler.ActiveExpensiveObjects.Contains(details))
{
_sceneProfiler.ActiveExpensiveObjects.Add(details);
}
}
private bool IsUniformScale(Vector3 scale)
{
return Mathf.Approximately(scale.x, scale.y) && Mathf.Approximately(scale.y, scale.z);
}
private int GetHierarchyDepth(Transform transform)
{
int depth = 0;
while (transform.parent != null)
{
depth++;
transform = transform.parent;
}
return depth;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 514c097f73434943a73f5c56b63d1802
timeCreated: 1720990995

View File

@ -0,0 +1,60 @@
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace SceneProfiler.Editor
{
public class CollectLightData
{
private SceneProfiler _sceneProfiler;
public CollectLightData(SceneProfiler sceneProfiler)
{
_sceneProfiler = sceneProfiler;
}
public void CheckLights()
{
Light[] lights = _sceneProfiler.FindObjects<Light>();
foreach (Light light in lights)
{
if (!_sceneProfiler.ActiveLights.Any(l => l.light == light))
{
LightDetails lightDetails = new LightDetails
{
light = light,
isEnabled = light.enabled,
shadowType = light.shadows,
isActive = light.gameObject.activeInHierarchy
};
_sceneProfiler.ActiveLights.Add(lightDetails);
}
}
}
public void CheckLightReferences(FieldInfo field, MonoBehaviour script)
{
if (field.FieldType == typeof(Light))
{
Light tLight = field.GetValue(script) as Light;
if (tLight != null)
{
LightDetails tLightDetails = new LightDetails
{
light = tLight,
isEnabled = tLight.enabled,
shadowType = tLight.shadows,
isActive = tLight.gameObject.activeInHierarchy
};
if (!_sceneProfiler.ActiveLights.Any(l => l.light == tLight))
{
_sceneProfiler.ActiveLights.Add(tLightDetails);
}
}
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 92feb30e3e103ce48b181a06940a1bc5
timeCreated: 1720314016

View File

@ -0,0 +1,102 @@
using UnityEngine;
using UnityEngine.UI;
namespace SceneProfiler.Editor
{
public class CollectMaterialsData
{
private SceneProfiler _sceneProfiler;
public CollectMaterialsData(SceneProfiler sceneProfiler)
{
_sceneProfiler = sceneProfiler;
}
MaterialDetails FindMaterialDetails(Material tMaterial)
{
foreach (MaterialDetails tMaterialDetails in _sceneProfiler.ActiveMaterials)
{
if (tMaterialDetails.material == tMaterial) return tMaterialDetails;
}
return null;
}
public void CheckRenderers()
{
Renderer[] renderers = _sceneProfiler.FindObjects<Renderer>();
AddSkyboxMaterial();
foreach (Renderer renderer in renderers)
{
AddMaterialDetails(renderer);
}
}
private void AddSkyboxMaterial()
{
MaterialDetails skyMat = new MaterialDetails
{
material = RenderSettings.skybox,
isSky = true
};
_sceneProfiler.ActiveMaterials.Add(skyMat);
}
private void AddMaterialDetails(Renderer renderer)
{
foreach (Material material in renderer.sharedMaterials)
{
MaterialDetails tMaterialDetails = FindMaterialDetails(material);
if (tMaterialDetails == null)
{
tMaterialDetails = new MaterialDetails
{
material = material
};
_sceneProfiler.ActiveMaterials.Add(tMaterialDetails);
}
tMaterialDetails.FoundInRenderers.Add(renderer);
}
}
public void CheckGUIElements()
{
if (!_sceneProfiler.IncludeGuiElements) return;
Graphic[] graphics = _sceneProfiler.FindObjects<Graphic>();
foreach (Graphic graphic in graphics)
{
if (graphic.materialForRendering)
{
MaterialDetails tMaterialDetails = FindMaterialDetails(graphic.materialForRendering);
if (tMaterialDetails == null)
{
tMaterialDetails = new MaterialDetails();
tMaterialDetails.material = graphic.materialForRendering;
tMaterialDetails.isgui = true;
_sceneProfiler.ActiveMaterials.Add(tMaterialDetails);
}
tMaterialDetails.FoundInGraphics.Add(graphic);
}
}
}
public void AddMaterialDetails(Material tMaterial)
{
MaterialDetails tMatDetails = FindMaterialDetails(tMaterial);
if (tMatDetails == null)
{
tMatDetails = new MaterialDetails();
tMatDetails.instance = true;
tMatDetails.material = tMaterial;
if (!_sceneProfiler.ActiveMaterials.Contains(tMatDetails))
{
_sceneProfiler.ActiveMaterials.Add(tMatDetails);
}
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: db2818977c3239a4e832391ae76f9b07
timeCreated: 1720308073

View File

@ -0,0 +1,156 @@
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace SceneProfiler.Editor
{
public class CollectMeshData
{
private SceneProfiler _sceneProfiler;
public CollectMeshData(SceneProfiler sceneProfiler)
{
_sceneProfiler = sceneProfiler;
}
public void CheckMeshFilters()
{
MeshFilter[] meshFilters = _sceneProfiler.FindObjects<MeshFilter>();
foreach (MeshFilter tMeshFilter in meshFilters)
{
Mesh tMesh = tMeshFilter.sharedMesh;
if (tMesh != null)
{
MeshDetails tMeshDetails = FindMeshDetails(tMesh);
if (tMeshDetails == null)
{
tMeshDetails = new MeshDetails();
tMeshDetails.mesh = tMesh;
_sceneProfiler.ActiveMeshDetails.Add(tMeshDetails);
}
tMeshDetails.FoundInMeshFilters.Add(tMeshFilter);
if (GameObjectUtility.AreStaticEditorFlagsSet(tMeshFilter.gameObject, StaticEditorFlags.BatchingStatic))
{
tMeshDetails.StaticBatchingEnabled.Add(tMeshFilter.gameObject);
}
}
else if (tMesh == null && tMeshFilter.transform.GetComponent("TextContainer") == null)
{
Missing tMissing = new Missing();
tMissing.Object = tMeshFilter.transform;
tMissing.type = "mesh";
tMissing.name = tMeshFilter.transform.name;
_sceneProfiler.MissingObjects.Add(tMissing);
_sceneProfiler.thingsMissing = true;
}
var meshRenderrer = tMeshFilter.transform.GetComponent<MeshRenderer>();
if (meshRenderrer == null || meshRenderrer.sharedMaterial == null)
{
Missing tMissing = new Missing();
tMissing.Object = tMeshFilter.transform;
tMissing.type = "material";
tMissing.name = tMeshFilter.transform.name;
_sceneProfiler.MissingObjects.Add(tMissing);
_sceneProfiler.thingsMissing = true;
}
}
}
public void CheckSkinnedMeshRenderers()
{
SkinnedMeshRenderer[] skinnedMeshRenderers = _sceneProfiler.FindObjects<SkinnedMeshRenderer>();
foreach (SkinnedMeshRenderer tSkinnedMeshRenderer in skinnedMeshRenderers)
{
Mesh tMesh = tSkinnedMeshRenderer.sharedMesh;
if (tMesh != null)
{
MeshDetails tMeshDetails = FindMeshDetails(tMesh);
if (tMeshDetails == null)
{
tMeshDetails = new MeshDetails();
tMeshDetails.mesh = tMesh;
_sceneProfiler.ActiveMeshDetails.Add(tMeshDetails);
}
tMeshDetails.FoundInSkinnedMeshRenderer.Add(tSkinnedMeshRenderer);
}
else if (tMesh == null)
{
Missing tMissing = new Missing();
tMissing.Object = tSkinnedMeshRenderer.transform;
tMissing.type = "mesh";
tMissing.name = tSkinnedMeshRenderer.transform.name;
_sceneProfiler.MissingObjects.Add(tMissing);
_sceneProfiler.thingsMissing = true;
}
if (tSkinnedMeshRenderer.sharedMaterial == null)
{
Missing tMissing = new Missing();
tMissing.Object = tSkinnedMeshRenderer.transform;
tMissing.type = "material";
tMissing.name = tSkinnedMeshRenderer.transform.name;
_sceneProfiler.MissingObjects.Add(tMissing);
_sceneProfiler.thingsMissing = true;
}
}
}
public void CheckLODGroups()
{
LODGroup[] lodGroups = _sceneProfiler.FindObjects<LODGroup>();
if (lodGroups != null)
{
foreach (var group in lodGroups)
{
var lods = group.GetLODs();
for (int i = 0, l = lods.Length; i < l; i++)
{
if (lods[i].renderers.Length == 0)
{
Missing tMissing = new Missing();
tMissing.Object = group.transform;
tMissing.type = "lod";
tMissing.name = group.transform.name;
_sceneProfiler.MissingObjects.Add(tMissing);
_sceneProfiler.thingsMissing = true;
}
}
}
}
}
public void CheckMeshReferences(FieldInfo field, MonoBehaviour script)
{
if (field.FieldType == typeof(Mesh))
{
Mesh tMesh = field.GetValue(script) as Mesh;
if (tMesh != null)
{
MeshDetails tMeshDetails = FindMeshDetails(tMesh);
if (tMeshDetails == null)
{
tMeshDetails = new MeshDetails();
tMeshDetails.mesh = tMesh;
tMeshDetails.instance = true;
_sceneProfiler.ActiveMeshDetails.Add(tMeshDetails);
}
}
}
}
MeshDetails FindMeshDetails(Mesh tMesh)
{
foreach (MeshDetails tMeshDetails in _sceneProfiler.ActiveMeshDetails)
{
if (tMeshDetails.mesh == tMesh) return tMeshDetails;
}
return null;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 187312d40d8d09b42ac7110b61d091f0
timeCreated: 1720313934

View File

@ -0,0 +1,70 @@
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace SceneProfiler.Editor
{
public class CollectParticleSystemData
{
private SceneProfiler _sceneProfiler;
public CollectParticleSystemData(SceneProfiler sceneProfiler)
{
_sceneProfiler = sceneProfiler;
}
public void CheckParticleSystems()
{
ParticleSystem[] particleSystems = _sceneProfiler.FindObjects<ParticleSystem>();
foreach (ParticleSystem ps in particleSystems)
{
if (ps == null) continue;
if (!_sceneProfiler.ActiveParticleSystems.Any(p => p.particleSystem == ps))
{
ParticleSystemDetails psDetails = new ParticleSystemDetails
{
particleSystem = ps
};
psDetails.FoundInGameObjects.Add(ps.gameObject);
var renderer = ps.GetComponent<ParticleSystemRenderer>();
if (renderer != null)
{
psDetails.material = renderer.sharedMaterial;
}
var main = ps.main;
psDetails.maxParticles = main.maxParticles;
psDetails.activeParticles = ps.particleCount;
_sceneProfiler.ActiveParticleSystems.Add(psDetails);
}
}
_sceneProfiler.ActiveParticleSystems.Sort((a, b) => b.activeParticles.CompareTo(a.activeParticles));
}
public void CheckParticleSystemReferences(FieldInfo field, MonoBehaviour script)
{
if (field.FieldType == typeof(ParticleSystem))
{
ParticleSystem tParticleSystem = field.GetValue(script) as ParticleSystem;
if (tParticleSystem != null)
{
if (!_sceneProfiler.ActiveParticleSystems.Any(p => p.particleSystem == tParticleSystem))
{
ParticleSystemDetails tParticleSystemDetails = new ParticleSystemDetails
{
particleSystem = tParticleSystem
};
_sceneProfiler.ActiveParticleSystems.Add(tParticleSystemDetails);
}
}
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d5f0b0a5daf9d8d4583a188fcae57a97
timeCreated: 1720314048

View File

@ -0,0 +1,48 @@
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace SceneProfiler.Editor
{
public class CollectPhysicsData
{
private SceneProfiler _sceneProfiler;
public CollectPhysicsData(SceneProfiler sceneProfiler)
{
_sceneProfiler = sceneProfiler;
}
public void CheckPhysicsObjects()
{
Rigidbody[] rigidbodies = _sceneProfiler.FindObjects<Rigidbody>();
foreach (var rb in rigidbodies)
{
if (rb != null)
{
if (!_sceneProfiler.ActivePhysicsObjects.Any(p => p.rigidbody == rb))
{
_sceneProfiler.ActivePhysicsObjects.Add(new PhysicsObjectDetails(rb));
}
}
}
}
public void CheckRigidbodyReferences(FieldInfo field, MonoBehaviour script)
{
if (field.FieldType == typeof(Rigidbody))
{
Rigidbody tRigidbody = field.GetValue(script) as Rigidbody;
if (tRigidbody != null)
{
if (!_sceneProfiler.ActivePhysicsObjects.Any(r => r.rigidbody == tRigidbody))
{
PhysicsObjectDetails tPhysicsObjectDetails = new PhysicsObjectDetails(tRigidbody);
_sceneProfiler.ActivePhysicsObjects.Add(tPhysicsObjectDetails);
}
}
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b107f598f38069c49883a6dbd40867e8
timeCreated: 1720314064

View File

@ -0,0 +1,514 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace SceneProfiler.Editor
{
public class CollectTextureData
{
private SceneProfiler _sceneProfiler;
public CollectTextureData(SceneProfiler sceneProfiler)
{
_sceneProfiler = sceneProfiler;
}
float GetBitsPerPixel(TextureFormat format)
{
switch (format)
{
case TextureFormat.Alpha8: return 8;
case TextureFormat.ARGB4444: return 16;
case TextureFormat.RGBA4444: return 16;
case TextureFormat.RGB24: return 24;
case TextureFormat.RGBA32: return 32;
case TextureFormat.ARGB32: return 32;
case TextureFormat.RGB565: return 16;
case TextureFormat.DXT1: return 4;
case TextureFormat.DXT1Crunched: return 4;
case TextureFormat.DXT5: return 8;
case TextureFormat.DXT5Crunched: return 8;
case TextureFormat.BC4: return 4;
case TextureFormat.BC7: return 8;
case TextureFormat.PVRTC_RGB2: return 2;
case TextureFormat.PVRTC_RGBA2: return 2;
case TextureFormat.PVRTC_RGB4: return 4;
case TextureFormat.PVRTC_RGBA4: return 4;
case TextureFormat.ETC_RGB4: return 4;
case TextureFormat.ETC_RGB4Crunched: return 4;
case TextureFormat.ETC2_RGBA8: return 8;
case TextureFormat.ETC2_RGB: return 4;
case TextureFormat.ETC2_RGBA8Crunched: return 4;
case TextureFormat.EAC_R: return 4;
case TextureFormat.BGRA32: return 32;
case TextureFormat.ASTC_4x4: return 8;
case TextureFormat.ASTC_5x5: return 5.12f;
case TextureFormat.ASTC_6x6: return 3.56f;
case TextureFormat.ASTC_8x8: return 2;
case TextureFormat.ASTC_10x10: return 1.28f;
case TextureFormat.ASTC_12x12: return 0.89f;
}
return 0;
}
float CalculateTextureSizeBytes(Texture tTexture)
{
int tWidth = tTexture.width;
int tHeight = tTexture.height;
float tSize = 0;
if (tTexture is Texture2D)
{
Texture2D tTex2D = tTexture as Texture2D;
float bitsPerPixel = GetBitsPerPixel(tTex2D.format);
int mipMapCount = tTex2D.mipmapCount;
int mipLevel = 1;
while (mipLevel <= mipMapCount)
{
tSize += tWidth * tHeight * bitsPerPixel / 8;
tWidth = Mathf.Max(1, tWidth / 2);
tHeight = Mathf.Max(1, tHeight / 2);
mipLevel++;
}
}
else if (tTexture is Texture2DArray)
{
Texture2DArray tTex2DArray = tTexture as Texture2DArray;
float bitsPerPixel = GetBitsPerPixel(tTex2DArray.format);
int mipMapCount = 10; // Assuming a fixed mip map count for Texture2DArray
int mipLevel = 1;
while (mipLevel <= mipMapCount)
{
tSize += tWidth * tHeight * bitsPerPixel / 8;
tWidth = Mathf.Max(1, tWidth / 2);
tHeight = Mathf.Max(1, tHeight / 2);
mipLevel++;
}
tSize *= tTex2DArray.depth;
}
else if (tTexture is Cubemap)
{
Cubemap tCubemap = tTexture as Cubemap;
float bitsPerPixel = GetBitsPerPixel(tCubemap.format);
tSize = tWidth * tHeight * 6 * bitsPerPixel / 8;
}
return tSize;
}
TextureDetails FindTextureDetails(Texture tTexture)
{
foreach (TextureDetails tTextureDetails in _sceneProfiler.ActiveTextures)
{
if (tTextureDetails.texture == tTexture) return tTextureDetails;
}
return null;
}
public void CheckRenderers()
{
Renderer[] renderers = _sceneProfiler.FindObjects<Renderer>();
foreach (Renderer renderer in renderers)
{
CheckSpriteRenderer(renderer);
}
}
private void CheckSpriteRenderer(Renderer renderer)
{
if (renderer is SpriteRenderer tSpriteRenderer)
{
if (tSpriteRenderer.sprite != null)
{
AddSpriteTextureDetails(tSpriteRenderer, renderer);
}
else
{
_sceneProfiler.AddMissingSprite(tSpriteRenderer);
}
}
}
private void AddSpriteTextureDetails(SpriteRenderer tSpriteRenderer, Renderer renderer)
{
var tSpriteTextureDetail = GetTextureDetail(tSpriteRenderer.sprite.texture, renderer);
if (!_sceneProfiler.ActiveTextures.Contains(tSpriteTextureDetail))
{
_sceneProfiler.ActiveTextures.Add(tSpriteTextureDetail);
}
var secondarySpriteTextureResult = new SecondarySpriteTexture[tSpriteRenderer.sprite.GetSecondaryTextureCount()];
tSpriteRenderer.sprite.GetSecondaryTextures(secondarySpriteTextureResult);
foreach (var sst in secondarySpriteTextureResult)
{
var tSpriteSecondaryTextureDetail = GetTextureDetail(sst.texture, renderer);
if (!_sceneProfiler.ActiveTextures.Contains(tSpriteSecondaryTextureDetail))
{
_sceneProfiler.ActiveTextures.Add(tSpriteSecondaryTextureDetail);
}
}
if (!_sceneProfiler.ActiveTextures.Contains(tSpriteTextureDetail))
{
_sceneProfiler.ActiveTextures.Add(tSpriteTextureDetail);
}
}
public void CheckLightmaps()
{
if (!_sceneProfiler.IncludeLightmapTextures) return;
LightmapData[] lightmapTextures = LightmapSettings.lightmaps;
foreach (LightmapData lightmapData in lightmapTextures)
{
if (lightmapData.lightmapColor != null)
{
var textureDetail = GetTextureDetail(lightmapData.lightmapColor);
if (!_sceneProfiler.ActiveTextures.Contains(textureDetail))
_sceneProfiler.ActiveTextures.Add(textureDetail);
}
if (lightmapData.lightmapDir != null)
{
var textureDetail = GetTextureDetail(lightmapData.lightmapDir);
if (!_sceneProfiler.ActiveTextures.Contains(textureDetail))
_sceneProfiler.ActiveTextures.Add(textureDetail);
}
if (lightmapData.shadowMask != null)
{
var textureDetail = GetTextureDetail(lightmapData.shadowMask);
if (!_sceneProfiler.ActiveTextures.Contains(textureDetail))
_sceneProfiler.ActiveTextures.Add(textureDetail);
}
}
}
public void CheckGUIElements()
{
if (!_sceneProfiler.IncludeGuiElements) return;
Graphic[] graphics = _sceneProfiler.FindObjects<Graphic>();
foreach (Graphic graphic in graphics)
{
if (graphic.mainTexture)
{
var tSpriteTextureDetail = GetTextureDetail(graphic.mainTexture, graphic);
if (!_sceneProfiler.ActiveTextures.Contains(tSpriteTextureDetail))
{
_sceneProfiler.ActiveTextures.Add(tSpriteTextureDetail);
}
}
}
Button[] buttons = _sceneProfiler.FindObjects<Button>();
foreach (Button button in buttons)
{
CheckButtonSpriteState(button, button.spriteState.disabledSprite);
CheckButtonSpriteState(button, button.spriteState.highlightedSprite);
CheckButtonSpriteState(button, button.spriteState.pressedSprite);
}
}
public void CheckMaterials()
{
foreach (MaterialDetails tMaterialDetails in _sceneProfiler.ActiveMaterials)
{
Material tMaterial = tMaterialDetails.material;
if (tMaterial != null)
{
var dependencies = EditorUtility.CollectDependencies(new UnityEngine.Object[] { tMaterial });
foreach (Object obj in dependencies)
{
if (obj is Texture)
{
Texture tTexture = obj as Texture;
var tTextureDetail = GetTextureDetail(tTexture, tMaterial, tMaterialDetails);
tTextureDetail.isSky = tMaterialDetails.isSky;
tTextureDetail.instance = tMaterialDetails.instance;
tTextureDetail.isgui = tMaterialDetails.isgui;
_sceneProfiler.ActiveTextures.Add(tTextureDetail);
}
}
if (tMaterial.HasProperty("_MainTex"))
{
if (tMaterial.mainTexture != null && !dependencies.Contains(tMaterial.mainTexture))
{
var tTextureDetail = GetTextureDetail(tMaterial.mainTexture, tMaterial, tMaterialDetails);
_sceneProfiler.ActiveTextures.Add(tTextureDetail);
}
}
}
}
}
public void CheckSelectedFolder()
{
if (!_sceneProfiler.IncludeSelectedFolder || Selection.objects.Length == 0) return;
var folders = new List<string>();
foreach (var obj in Selection.objects)
{
if (obj.GetType() != typeof(DefaultAsset)) continue;
var path = AssetDatabase.GetAssetPath(obj);
folders.Add(path);
}
if (folders.Count != 0)
{
var guids = AssetDatabase.FindAssets("t:Texture", folders.ToArray());
if (guids.Length != 0)
{
foreach (var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
var item = AssetDatabase.LoadAssetAtPath<Texture>(path);
var textureDetail = GetTextureDetail(item);
if (!_sceneProfiler.ActiveTextures.Contains(textureDetail))
_sceneProfiler.ActiveTextures.Add(textureDetail);
}
}
}
}
public void CheckSpriteAnimations()
{
if (!_sceneProfiler.IncludeSpriteAnimations) return;
Animator[] animators = _sceneProfiler.FindObjects<Animator>();
foreach (Animator anim in animators)
{
if (!anim.gameObject.activeInHierarchy || !anim.enabled || anim.runtimeAnimatorController == null)
continue;
UnityEditor.Animations.AnimatorController ac = anim.runtimeAnimatorController as UnityEditor.Animations.AnimatorController;
if (ac == null || ac.layers == null || ac.layers.Length == 0)
continue;
for (int x = 0; x < anim.layerCount; x++)
{
UnityEditor.Animations.AnimatorStateMachine sm = ac.layers[x].stateMachine;
if (sm == null)
continue;
int cnt = sm.states.Length;
for (int i = 0; i < cnt; i++)
{
UnityEditor.Animations.AnimatorState state = sm.states[i].state;
if (state == null)
continue;
Motion m = state.motion;
if (m != null)
{
AnimationClip clip = m as AnimationClip;
if (clip != null)
{
EditorCurveBinding[] ecbs = AnimationUtility.GetObjectReferenceCurveBindings(clip);
foreach (EditorCurveBinding ecb in ecbs)
{
if (ecb.propertyName == "m_Sprite")
{
foreach (ObjectReferenceKeyframe keyframe in AnimationUtility.GetObjectReferenceCurve(clip, ecb))
{
Sprite tSprite = keyframe.value as Sprite;
if (tSprite != null)
{
var tTextureDetail = GetTextureDetail(tSprite.texture, anim);
if (!_sceneProfiler.ActiveTextures.Contains(tTextureDetail))
{
_sceneProfiler.ActiveTextures.Add(tTextureDetail);
}
}
}
}
}
}
}
}
}
}
}
public void CheckMaterialTextures(Material tMaterial)
{
if (tMaterial.mainTexture)
{
var tSpriteTextureDetail = GetTextureDetail(tMaterial.mainTexture);
if (!_sceneProfiler.ActiveTextures.Contains(tSpriteTextureDetail))
{
_sceneProfiler.ActiveTextures.Add(tSpriteTextureDetail);
}
}
}
public void CheckMaterialDependencies(Material tMaterial)
{
var dependencies = EditorUtility.CollectDependencies(new UnityEngine.Object[] { tMaterial });
foreach (Object obj in dependencies)
{
if (obj is Texture)
{
Texture tTexture = obj as Texture;
var tTextureDetail = GetTextureDetail(tTexture, tMaterial, FindMaterialDetails(tMaterial));
if (!_sceneProfiler.ActiveTextures.Contains(tTextureDetail))
{
_sceneProfiler.ActiveTextures.Add(tTextureDetail);
}
}
}
}
public void CheckSpriteReferences(FieldInfo field, MonoBehaviour script)
{
if (field.FieldType == typeof(Sprite))
{
Sprite tSprite = field.GetValue(script) as Sprite;
if (tSprite != null)
{
var tSpriteTextureDetail = GetTextureDetail(tSprite.texture, script);
if (!_sceneProfiler.ActiveTextures.Contains(tSpriteTextureDetail))
{
_sceneProfiler.ActiveTextures.Add(tSpriteTextureDetail);
}
}
}
}
MaterialDetails FindMaterialDetails(Material tMaterial)
{
foreach (MaterialDetails tMaterialDetails in _sceneProfiler.ActiveMaterials)
{
if (tMaterialDetails.material == tMaterial) return tMaterialDetails;
}
return null;
}
private void CheckButtonSpriteState(Button button, Sprite sprite)
{
if (sprite == null) return;
var texture = sprite.texture;
var tButtonTextureDetail = GetTextureDetail(texture, button);
if (!_sceneProfiler.ActiveTextures.Contains(tButtonTextureDetail))
{
_sceneProfiler.ActiveTextures.Add(tButtonTextureDetail);
}
}
private TextureDetails GetTextureDetail(Texture tTexture, Material tMaterial, MaterialDetails tMaterialDetails)
{
TextureDetails tTextureDetails = GetTextureDetail(tTexture);
tTextureDetails.FoundInMaterials.Add(tMaterial);
foreach (Renderer renderer in tMaterialDetails.FoundInRenderers)
{
if (!tTextureDetails.FoundInRenderers.Contains(renderer)) tTextureDetails.FoundInRenderers.Add(renderer);
}
foreach (Graphic graphic in tMaterialDetails.FoundInGraphics)
{
if (!tTextureDetails.FoundInGraphics.Contains(graphic)) tTextureDetails.FoundInGraphics.Add(graphic);
}
return tTextureDetails;
}
private TextureDetails GetTextureDetail(Texture tTexture, Renderer renderer)
{
TextureDetails tTextureDetails = GetTextureDetail(tTexture);
tTextureDetails.FoundInRenderers.Add(renderer);
return tTextureDetails;
}
private TextureDetails GetTextureDetail(Texture tTexture, Animator animator)
{
TextureDetails tTextureDetails = GetTextureDetail(tTexture);
tTextureDetails.FoundInAnimators.Add(animator);
return tTextureDetails;
}
private TextureDetails GetTextureDetail(Texture tTexture, Graphic graphic)
{
TextureDetails tTextureDetails = GetTextureDetail(tTexture);
tTextureDetails.FoundInGraphics.Add(graphic);
return tTextureDetails;
}
private TextureDetails GetTextureDetail(Texture tTexture, MonoBehaviour script)
{
TextureDetails tTextureDetails = GetTextureDetail(tTexture);
tTextureDetails.FoundInScripts.Add(script);
return tTextureDetails;
}
private TextureDetails GetTextureDetail(Texture tTexture, Button button)
{
TextureDetails tTextureDetails = GetTextureDetail(tTexture);
if (!tTextureDetails.FoundInButtons.Contains(button))
{
tTextureDetails.FoundInButtons.Add(button);
}
return tTextureDetails;
}
private TextureDetails GetTextureDetail(Texture tTexture)
{
TextureDetails tTextureDetails = FindTextureDetails(tTexture);
if (tTextureDetails == null)
{
tTextureDetails = new TextureDetails();
tTextureDetails.texture = tTexture;
tTextureDetails.isCubeMap = tTexture is Cubemap;
float memSize = CalculateTextureSizeBytes(tTexture);
TextureFormat tFormat = TextureFormat.RGBA32;
int tMipMapCount = 1;
if (tTexture is Texture2D)
{
tFormat = (tTexture as Texture2D).format;
tMipMapCount = (tTexture as Texture2D).mipmapCount;
}
if (tTexture is Cubemap)
{
tFormat = (tTexture as Cubemap).format;
memSize = 8 * tTexture.height * tTexture.width;
}
if(tTexture is Texture2DArray){
tFormat = (tTexture as Texture2DArray).format;
tMipMapCount = 10;
}
tTextureDetails.memSizeKB = memSize / 1024;
tTextureDetails.format = tFormat;
tTextureDetails.mipMapCount = tMipMapCount;
}
return tTextureDetails;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bea7598fc76f9564aa4e5dffefc7cbed
timeCreated: 1720303184

View File

@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace SceneProfiler.Editor
{
public class CollectWarningsData
{
private SceneProfiler _sceneProfiler;
public CollectWarningsData(SceneProfiler sceneProfiler)
{
_sceneProfiler = sceneProfiler;
}
public float GetSceneFileSize()
{
float totalSize = 0;
string scenePath = SceneManager.GetActiveScene().path;
if (!string.IsNullOrEmpty(scenePath))
{
totalSize = new FileInfo(scenePath).Length;
}
return totalSize / (1024f * 1024f);
}
public int CountObjectsInScene()
{
GameObject[] allObjects = _sceneProfiler.GetAllRootGameObjects();
int objectCount = 0;
foreach (GameObject go in allObjects)
{
objectCount += go.GetComponentsInChildren<Transform>(true).Length;
}
return objectCount;
}
public int CountCanvasComponentsInScene()
{
Canvas[] canvases = _sceneProfiler.GetAllRootGameObjects()
.SelectMany(go => go.GetComponentsInChildren<Canvas>(true))
.ToArray();
return canvases.Length;
}
public List<string> GetPlatformsWithoutStaticBatching()
{
var platformsWithoutStaticBatching = new List<string>();
var buildTargets = new BuildTarget[]
{
BuildTarget.StandaloneWindows,
BuildTarget.StandaloneWindows64,
BuildTarget.StandaloneOSX,
BuildTarget.StandaloneLinux64,
BuildTarget.Android,
BuildTarget.iOS,
BuildTarget.PS4,
BuildTarget.XboxOne,
BuildTarget.Switch
};
var playerSettingsType = typeof(PlayerSettings);
var method = playerSettingsType.GetMethod("GetBatchingForPlatform", BindingFlags.NonPublic | BindingFlags.Static);
if (method == null)
{
Debug.LogError("GetBatchingForPlatform method not found!");
return platformsWithoutStaticBatching;
}
foreach (var buildTarget in buildTargets)
{
try
{
object[] parameters = new object[] { buildTarget, 0, 0 };
method.Invoke(null, parameters);
int staticBatchingFlags = (int)parameters[1];
if ((staticBatchingFlags & 1) == 0)
{
platformsWithoutStaticBatching.Add(buildTarget.ToString());
}
}
catch (Exception e)
{
Debug.LogError($"Error checking static batching for platform {buildTarget}: {e.Message}");
}
}
return platformsWithoutStaticBatching;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6ac737456afebb64e89505e705c10c94
timeCreated: 1720793279

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9165728f3120b3b4b93c515135983b09
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,203 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace SceneProfiler.Editor.GUI
{
public class AudioClipsProfilerGUI : ProfilerGUI<AudioClipDetails>
{
private Func<float> _getRowHeight;
public AudioClipsProfilerGUI(SceneProfiler profiler, Color defColor, Func<float> getRowHeight)
: base(profiler, defColor)
{
_getRowHeight = getRowHeight;
InitializeColumns();
InitializeColumnHeader();
}
protected override void InitializeColumns()
{
var columnDefinitions = new (string, float, bool)[]
{
("Thumbnail", 70, false),
("Name", 150, false),
("Channels", 60, false),
("Frequency", 70, false),
("Length", 60, false),
("Load Type", 130, false),
("File Size", 80, false),
("GameObjects", 90, false),
("Asset Path", 300, true)
};
columns = columnDefinitions.Select(def => CreateColumn(def.Item1, def.Item2, def.Item3)).ToArray();
}
protected override List<AudioClipDetails> GetProfilerItems()
{
return profiler.ActiveClipDetails;
}
protected override int CompareItems(AudioClipDetails a, AudioClipDetails b, int columnIndex)
{
switch (columnIndex)
{
case 0: return 0; // Thumbnails are not comparable
case 1: return string.Compare(a.clip.name, b.clip.name);
case 2: return a.clip.channels.CompareTo(b.clip.channels);
case 3: return a.clip.frequency.CompareTo(b.clip.frequency);
case 4: return a.clip.length.CompareTo(b.clip.length);
case 5: return a.clip.loadType.CompareTo(b.clip.loadType);
case 6: return GetFileSize(a).CompareTo(GetFileSize(b));
case 7: return a.FoundInAudioSources.Count.CompareTo(b.FoundInAudioSources.Count);
case 8: return string.Compare(AssetDatabase.GetAssetPath(a.clip), AssetDatabase.GetAssetPath(b.clip));
default: return 0;
}
}
public void ListAudioClips()
{
if (buttonStyle == null || labelStyle == null)
{
InitializeStyles();
}
var headerRect = GUILayoutUtility.GetRect(0, columnHeader.height, GUILayout.ExpandWidth(true));
columnHeader.OnGUI(headerRect, scrollPosition.x);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
foreach (AudioClipDetails aDetails in profiler.ActiveClipDetails)
{
if (aDetails.clip == null) continue;
EditorGUILayout.BeginHorizontal();
for (int visibleColumnIndex = 0; visibleColumnIndex < columnHeader.state.visibleColumns.Length; visibleColumnIndex++)
{
int columnIndex = columnHeader.state.visibleColumns[visibleColumnIndex];
Rect cellRect = EditorGUILayout.GetControlRect(GUILayout.Width(columns[columnIndex].width - 3), GUILayout.Height(_getRowHeight()));
cellRect.x += headerRect.x;
Color originalColor = UnityEngine.GUI.color;
switch (columnIndex)
{
case 0:
DrawThumbnail(aDetails, cellRect);
break;
case 1:
DrawName(aDetails, cellRect);
break;
case 2:
DrawChannels(aDetails, cellRect);
break;
case 3:
DrawFrequency(aDetails, cellRect);
break;
case 4:
DrawLength(aDetails, cellRect);
break;
case 5:
DrawLoadType(aDetails, cellRect);
break;
case 6:
DrawFileSize(aDetails, cellRect);
break;
case 7:
DrawGameObjectsButton(aDetails, cellRect);
break;
case 8:
DrawAssetPath(aDetails, cellRect);
break;
}
UnityEngine.GUI.color = originalColor;
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
}
private void DrawThumbnail(AudioClipDetails aDetails, Rect cellRect)
{
var previewTexture = AssetPreview.GetAssetPreview(aDetails.clip);
if (previewTexture == null)
{
previewTexture = AssetPreview.GetMiniThumbnail(aDetails.clip);
}
if (previewTexture != null)
{
UnityEngine.GUI.DrawTexture(cellRect, previewTexture, ScaleMode.ScaleToFit);
}
else
{
EditorGUI.LabelField(cellRect, "No Preview", labelStyle);
}
}
private void DrawName(AudioClipDetails aDetails, Rect cellRect)
{
if (UnityEngine.GUI.Button(cellRect, aDetails.clip.name, buttonStyle))
{
profiler.SelectObject(aDetails.clip, profiler.ctrlPressed);
}
}
private void DrawChannels(AudioClipDetails aDetails, Rect cellRect)
{
EditorGUI.LabelField(cellRect, aDetails.clip.channels.ToString(), labelStyle);
}
private void DrawFrequency(AudioClipDetails aDetails, Rect cellRect)
{
EditorGUI.LabelField(cellRect, aDetails.clip.frequency.ToString(), labelStyle);
}
private void DrawLength(AudioClipDetails aDetails, Rect cellRect)
{
EditorGUI.LabelField(cellRect, aDetails.clip.length.ToString("F2") + " s", labelStyle);
}
private void DrawLoadType(AudioClipDetails aDetails, Rect cellRect)
{
EditorGUI.LabelField(cellRect, aDetails.clip.loadType.ToString(), labelStyle);
}
private void DrawFileSize(AudioClipDetails aDetails, Rect cellRect)
{
EditorGUI.LabelField(cellRect, GetFileSize(aDetails).ToString("F2") + " MB", labelStyle);
}
private void DrawGameObjectsButton(AudioClipDetails aDetails, Rect cellRect)
{
if (UnityEngine.GUI.Button(cellRect, aDetails.FoundInAudioSources.Count + " GO", buttonStyle))
{
HashSet<Object> foundObjects = new HashSet<Object>();
foreach (AudioSource source in aDetails.FoundInAudioSources)
foundObjects.Add(source.gameObject);
profiler.SelectObjects(new List<Object>(foundObjects), profiler.ctrlPressed);
}
}
private void DrawAssetPath(AudioClipDetails aDetails, Rect cellRect)
{
EditorGUI.LabelField(cellRect, AssetDatabase.GetAssetPath(aDetails.clip), labelStyle);
}
private float GetFileSize(AudioClipDetails aDetails)
{
var path = AssetDatabase.GetAssetPath(aDetails.clip);
var fileInfo = new System.IO.FileInfo(path);
return fileInfo.Length / (1024f * 1024f);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 06427f57560f09d4a9708dff8969264d
timeCreated: 1720202265

View File

@ -0,0 +1,165 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace SceneProfiler.Editor.GUI
{
public class ExpensiveProfilerGUI : ProfilerGUI<ExpensiveObjectDetails>
{
public ExpensiveProfilerGUI(SceneProfiler profiler, Color defColor)
: base(profiler, defColor)
{
InitializeColumns();
InitializeColumnHeader();
}
protected override void InitializeColumns()
{
var columnDefinitions = new (string, float, bool)[]
{
("GameObject", 200, false),
("Scale", 200, false),
("Scale Type", 80, false),
("Hierarchy Depth", 110, false),
("Component Count", 110, false)
};
columns = columnDefinitions.Select(def => CreateColumn(def.Item1, def.Item2, def.Item3)).ToArray();
}
protected override List<ExpensiveObjectDetails> GetProfilerItems()
{
return profiler.ActiveExpensiveObjects;
}
protected override int CompareItems(ExpensiveObjectDetails a, ExpensiveObjectDetails b, int columnIndex)
{
if (a == null && b == null) return 0;
if (a == null) return -1;
if (b == null) return 1;
switch (columnIndex)
{
case 0: return string.Compare(a.gameObject.name, b.gameObject.name);
case 1: return a.scale.sqrMagnitude.CompareTo(b.scale.sqrMagnitude);
case 2: return string.Compare(a.scaleType, b.scaleType);
case 3: return a.hierarchyDepth.CompareTo(b.hierarchyDepth);
case 4: return a.componentCount.CompareTo(b.componentCount);
default: return 0;
}
}
public void ListExpensiveObjects()
{
if (buttonStyle == null || labelStyle == null)
{
InitializeStyles();
}
var headerRect = GUILayoutUtility.GetRect(0, columnHeader.height, GUILayout.ExpandWidth(true));
columnHeader.OnGUI(headerRect, scrollPosition.x);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
int displayedObjects = 0;
foreach (var details in profiler.ActiveExpensiveObjects)
{
if (displayedObjects >= profiler.currentObjectsInColumnCount) break;
if (details.gameObject == null) continue;
EditorGUILayout.BeginHorizontal();
for (int visibleColumnIndex = 0; visibleColumnIndex < columnHeader.state.visibleColumns.Length; visibleColumnIndex++)
{
int columnIndex = columnHeader.state.visibleColumns[visibleColumnIndex];
Rect cellRect = EditorGUILayout.GetControlRect(GUILayout.Width(columns[columnIndex].width - 4), GUILayout.Height(EditorGUIUtility.singleLineHeight));
cellRect.x += headerRect.x;
switch (columnIndex)
{
case 0:
DrawObjectButton(details, cellRect);
break;
case 1:
DrawScale(details, cellRect);
break;
case 2:
DrawScaleType(details, cellRect);
break;
case 3:
DrawHierarchyDepth(details, cellRect);
break;
case 4:
DrawComponentCount(details, cellRect);
break;
}
}
EditorGUILayout.EndHorizontal();
displayedObjects++;
}
if (profiler.currentObjectsInColumnCount < profiler.ActiveExpensiveObjects.Count)
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Load More", GUILayout.Width(150)))
{
profiler.currentObjectsInColumnCount += 100;
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
}
private void DrawObjectButton(ExpensiveObjectDetails details, Rect cellRect)
{
if (UnityEngine.GUI.Button(cellRect, details.gameObject.name, buttonStyle))
{
Selection.activeObject = details.gameObject;
}
}
private void DrawScale(ExpensiveObjectDetails details, Rect cellRect)
{
float componentWidth = cellRect.width / 3;
Rect xLabelRect = new Rect(cellRect.x, cellRect.y, 15, EditorGUIUtility.singleLineHeight);
Rect xRect = new Rect(cellRect.x + 15, cellRect.y, componentWidth - 20, EditorGUIUtility.singleLineHeight);
Rect yLabelRect = new Rect(cellRect.x + componentWidth, cellRect.y, 15, EditorGUIUtility.singleLineHeight);
Rect yRect = new Rect(cellRect.x + componentWidth + 15, cellRect.y, componentWidth - 20, EditorGUIUtility.singleLineHeight);
Rect zLabelRect = new Rect(cellRect.x + 2 * componentWidth, cellRect.y, 15, EditorGUIUtility.singleLineHeight);
Rect zRect = new Rect(cellRect.x + 2 * componentWidth + 15, cellRect.y, componentWidth - 20, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(xLabelRect, "X");
details.scale.x = EditorGUI.FloatField(xRect, details.scale.x);
EditorGUI.LabelField(yLabelRect, "Y");
details.scale.y = EditorGUI.FloatField(yRect, details.scale.y);
EditorGUI.LabelField(zLabelRect, "Z");
details.scale.z = EditorGUI.FloatField(zRect, details.scale.z);
}
private void DrawScaleType(ExpensiveObjectDetails details, Rect cellRect)
{
EditorGUI.LabelField(cellRect, details.scaleType, labelStyle);
}
private void DrawHierarchyDepth(ExpensiveObjectDetails details, Rect cellRect)
{
EditorGUI.LabelField(cellRect, details.hierarchyDepth.ToString(), labelStyle);
}
private void DrawComponentCount(ExpensiveObjectDetails details, Rect cellRect)
{
EditorGUI.LabelField(cellRect, details.componentCount.ToString(), labelStyle);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5c8e88ce5a9744e7b58d1eabde4987e3
timeCreated: 1720991327

View File

@ -0,0 +1,96 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace SceneProfiler.Editor.GUI
{
public class LightsProfilerGUI : ProfilerGUI<LightDetails>
{
public LightsProfilerGUI(SceneProfiler profiler, Color defColor)
: base(profiler, defColor)
{
InitializeColumns();
InitializeColumnHeader();
}
protected override void InitializeColumns()
{
var columnDefinitions = new (string, float, bool)[]
{
("Light", 150, false),
("Enabled", 100, false),
("Active", 100, false),
("Shadows", 100, false)
};
columns = columnDefinitions.Select(def => CreateColumn(def.Item1, def.Item2, def.Item3)).ToArray();
}
protected override List<LightDetails> GetProfilerItems()
{
return profiler.ActiveLights;
}
protected override int CompareItems(LightDetails a, LightDetails b, int columnIndex)
{
switch (columnIndex)
{
case 0: return string.Compare(a.light.name, b.light.name);
case 1: return a.isEnabled.CompareTo(b.isEnabled);
case 2: return a.isActive.CompareTo(b.isActive);
case 3: return string.Compare(a.shadowType.ToString(), b.shadowType.ToString());
default: return 0;
}
}
public void ListLights()
{
if (buttonStyle == null || labelStyle == null)
{
InitializeStyles();
}
var headerRect = GUILayoutUtility.GetRect(0, columnHeader.height, GUILayout.ExpandWidth(true));
columnHeader.OnGUI(headerRect, scrollPosition.x);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
foreach (LightDetails lightDetails in profiler.ActiveLights)
{
if (lightDetails.light == null) continue;
EditorGUILayout.BeginHorizontal();
for (int i = 0; i < columns.Length; i++)
{
Rect cellRect = EditorGUILayout.GetControlRect(GUILayout.Width(columns[i].width - 2));
switch (i)
{
case 0:
if (UnityEngine.GUI.Button(cellRect, lightDetails.light.name, buttonStyle))
{
profiler.SelectObject(lightDetails.light, profiler.ctrlPressed);
}
break;
case 1:
EditorGUI.LabelField(cellRect, lightDetails.isEnabled ? "Yes" : "No", labelStyle);
break;
case 2:
EditorGUI.LabelField(cellRect, lightDetails.isActive ? "Yes" : "No", labelStyle);
break;
case 3:
EditorGUI.LabelField(cellRect, lightDetails.shadowType.ToString(), labelStyle);
break;
}
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d3149fdc30ae8db4080148f195468750
timeCreated: 1720116329

View File

@ -0,0 +1,221 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace SceneProfiler.Editor.GUI
{
public class MaterialsProfilerGUI : ProfilerGUI<MaterialDetails>
{
private Func<float> _getRowHeight;
private Dictionary<Material, Texture2D> materialPreviewCache = new Dictionary<Material, Texture2D>();
public MaterialsProfilerGUI(SceneProfiler profiler, Color defColor, Func<float> getRowHeight)
: base(profiler, defColor)
{
_getRowHeight = getRowHeight;
InitializeColumns();
InitializeColumnHeader();
}
protected override void InitializeColumns()
{
var columnDefinitions = new (string, float, bool)[]
{
("Thumbnail", 70, false),
("Material", 150, false),
("Shader", 250, false),
("GameObjects", 100, false),
("Render Queue", 100, false),
("Asset Path", 350, true)
};
columns = columnDefinitions.Select(def => CreateColumn(def.Item1, def.Item2, def.Item3)).ToArray();
}
protected override List<MaterialDetails> GetProfilerItems()
{
return profiler.ActiveMaterials;
}
protected override int CompareItems(MaterialDetails a, MaterialDetails b, int columnIndex)
{
if (a == null && b == null) return 0;
if (a == null) return -1;
if (b == null) return 1;
switch (columnIndex)
{
case 0: return 0;
case 1: return string.Compare(a.material?.name, b.material?.name);
case 2: return string.Compare(a.material?.shader?.name, b.material?.shader?.name);
case 3:
int aCount = (a.FoundInRenderers?.Count ?? 0) + (a.FoundInGraphics?.Count ?? 0);
int bCount = (b.FoundInRenderers?.Count ?? 0) + (b.FoundInGraphics?.Count ?? 0);
return aCount.CompareTo(bCount);
case 4: return a.material?.renderQueue.CompareTo(b.material?.renderQueue) ?? 0;
case 5: return string.Compare(AssetDatabase.GetAssetPath(a.material), AssetDatabase.GetAssetPath(b.material));
default: return 0;
}
}
public void ListMaterials()
{
if (buttonStyle == null || labelStyle == null)
{
InitializeStyles();
}
var headerRect = GUILayoutUtility.GetRect(0, columnHeader.height, GUILayout.ExpandWidth(true));
columnHeader.OnGUI(headerRect, scrollPosition.x);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
int displayedMaterials = 0;
foreach (MaterialDetails tDetails in profiler.ActiveMaterials)
{
if (displayedMaterials >= profiler.currentObjectsInColumnCount) break;
if (tDetails.material == null) continue;
EditorGUILayout.BeginHorizontal();
for (int visibleColumnIndex = 0; visibleColumnIndex < columnHeader.state.visibleColumns.Length; visibleColumnIndex++)
{
int columnIndex = columnHeader.state.visibleColumns[visibleColumnIndex];
Rect cellRect = EditorGUILayout.GetControlRect(GUILayout.Width(columns[columnIndex].width - 3), GUILayout.Height(_getRowHeight()));
cellRect.x += headerRect.x;
Color originalColor = UnityEngine.GUI.color;
switch (columnIndex)
{
case 0:
DrawThumbnail(tDetails, cellRect);
break;
case 1:
DrawMaterialName(tDetails, cellRect);
break;
case 2:
DrawShader(tDetails, cellRect);
break;
case 3:
DrawGameObjectsButton(tDetails, cellRect);
break;
case 4:
DrawRenderQueue(tDetails, cellRect);
break;
case 5:
DrawAssetPath(tDetails, cellRect);
break;
}
UnityEngine.GUI.color = originalColor;
}
EditorGUILayout.EndHorizontal();
displayedMaterials++;
}
if (profiler.currentObjectsInColumnCount < profiler.ActiveMaterials.Count)
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Load More", GUILayout.Width(150)))
{
profiler.currentObjectsInColumnCount += 100;
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
}
private void DrawThumbnail(MaterialDetails tDetails, Rect cellRect)
{
if (!materialPreviewCache.TryGetValue(tDetails.material, out var previewTexture) || previewTexture == null)
{
previewTexture = AssetPreview.GetAssetPreview(tDetails.material);
if (previewTexture == null)
{
previewTexture = AssetPreview.GetMiniThumbnail(tDetails.material);
}
materialPreviewCache[tDetails.material] = previewTexture;
}
if (previewTexture != null)
{
UnityEngine.GUI.DrawTexture(cellRect, previewTexture, ScaleMode.ScaleToFit);
}
else
{
EditorGUI.LabelField(cellRect, "No Preview", labelStyle);
}
}
private void DrawMaterialName(MaterialDetails tDetails, Rect cellRect)
{
if (tDetails.instance)
UnityEngine.GUI.color = new Color(0.8f, 0.8f, defColor.b, 1.0f);
if (tDetails.isgui)
UnityEngine.GUI.color = new Color(defColor.r, 0.95f, 0.8f, 1.0f);
if (tDetails.isSky)
UnityEngine.GUI.color = new Color(0.9f, defColor.g, defColor.b, 1.0f);
if (UnityEngine.GUI.Button(cellRect, tDetails.material.name, buttonStyle))
{
profiler.SelectObject(tDetails.material, profiler.ctrlPressed);
}
UnityEngine.GUI.color = defColor;
}
private void DrawShader(MaterialDetails tDetails, Rect cellRect)
{
string shaderLabel = tDetails.material.shader != null ? tDetails.material.shader.name : "no shader";
EditorGUI.LabelField(cellRect, shaderLabel, labelStyle);
}
private void DrawGameObjectsButton(MaterialDetails tDetails, Rect cellRect)
{
if (UnityEngine.GUI.Button(cellRect, (tDetails.FoundInRenderers.Count + tDetails.FoundInGraphics.Count) + " GO", buttonStyle))
{
List<Object> foundObjects = new List<Object>();
foreach (Renderer renderer in tDetails.FoundInRenderers)
foundObjects.Add(renderer.gameObject);
foreach (Graphic graphic in tDetails.FoundInGraphics)
foundObjects.Add(graphic.gameObject);
profiler.SelectObjects(foundObjects, profiler.ctrlPressed);
}
}
private void DrawRenderQueue(MaterialDetails tDetails, Rect cellRect)
{
GUIStyle customStyle = new GUIStyle(EditorStyles.numberField)
{
alignment = TextAnchor.MiddleCenter,
fontSize = 12,
normal = { textColor = Color.gray },
focused = { textColor = Color.white }
};
EditorGUI.BeginChangeCheck();
int renderQueue = EditorGUI.DelayedIntField(cellRect, tDetails.material.renderQueue, customStyle);
if (EditorGUI.EndChangeCheck())
{
tDetails.material.renderQueue = renderQueue;
profiler.ActiveMaterials.Sort((a, b) => CompareItems(a, b, 4));
}
}
private void DrawAssetPath(MaterialDetails tDetails, Rect cellRect)
{
EditorGUI.LabelField(cellRect, AssetDatabase.GetAssetPath(tDetails.material), labelStyle);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 47a46b43a4143e14d81cefd929fab1ce
timeCreated: 1720200382

View File

@ -0,0 +1,195 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace SceneProfiler.Editor.GUI
{
public class MeshesProfilerGUI : ProfilerGUI<MeshDetails>
{
public MeshesProfilerGUI(SceneProfiler profiler, Color defColor)
: base(profiler, defColor)
{
InitializeColumns();
InitializeColumnHeader();
}
protected override void InitializeColumns()
{
var columnDefinitions = new (string, float, bool)[]
{
("Name", 150, false),
("Vertex Count", 100, false),
("GameObjects", 120, false),
("Skinned Meshes", 120, false),
("Static Batching", 140, false),
("Asset Path", 300, true)
};
columns = columnDefinitions.Select(def => CreateColumn(def.Item1, def.Item2, def.Item3)).ToArray();
}
protected override List<MeshDetails> GetProfilerItems()
{
return profiler.ActiveMeshDetails;
}
protected override int CompareItems(MeshDetails a, MeshDetails b, int columnIndex)
{
switch (columnIndex)
{
case 0: return string.Compare(a.mesh.name, b.mesh.name);
case 1: return a.mesh.vertexCount.CompareTo(b.mesh.vertexCount);
case 2: return a.FoundInMeshFilters.Count.CompareTo(b.FoundInMeshFilters.Count);
case 3: return a.FoundInSkinnedMeshRenderer.Count.CompareTo(b.FoundInSkinnedMeshRenderer.Count);
case 4: return a.StaticBatchingEnabled.Count.CompareTo(b.StaticBatchingEnabled.Count);
case 5: return string.Compare(AssetDatabase.GetAssetPath(a.mesh), AssetDatabase.GetAssetPath(b.mesh));
default: return 0;
}
}
public void ListMeshes()
{
if (buttonStyle == null || labelStyle == null)
{
InitializeStyles();
}
var headerRect = GUILayoutUtility.GetRect(0, columnHeader.height, GUILayout.ExpandWidth(true));
columnHeader.OnGUI(headerRect, scrollPosition.x);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
int displayedMeshes = 0;
foreach (MeshDetails tDetails in profiler.ActiveMeshDetails)
{
if (displayedMeshes >= profiler.currentObjectsInColumnCount) break;
if (tDetails.mesh == null) continue;
EditorGUILayout.BeginHorizontal();
for (int visibleColumnIndex = 0; visibleColumnIndex < columnHeader.state.visibleColumns.Length; visibleColumnIndex++)
{
int columnIndex = columnHeader.state.visibleColumns[visibleColumnIndex];
Rect cellRect = EditorGUILayout.GetControlRect(GUILayout.Width(columns[columnIndex].width - 3));
cellRect.x += headerRect.x;
Color originalColor = UnityEngine.GUI.color;
switch (columnIndex)
{
case 0:
DrawMeshName(tDetails, cellRect);
break;
case 1:
DrawVertexCount(tDetails, cellRect);
break;
case 2:
DrawGameObjectsButton(tDetails, cellRect);
break;
case 3:
DrawSkinnedMeshButton(tDetails, cellRect);
break;
case 4:
DrawStaticBatchingButton(tDetails, cellRect);
break;
case 5:
DrawAssetPath(tDetails, cellRect);
break;
}
UnityEngine.GUI.color = originalColor;
}
EditorGUILayout.EndHorizontal();
displayedMeshes++;
}
if (profiler.currentObjectsInColumnCount < profiler.ActiveMeshDetails.Count)
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Load More", GUILayout.Width(150)))
{
profiler.currentObjectsInColumnCount += 100;
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
}
private void DrawMeshName(MeshDetails tDetails, Rect cellRect)
{
if (string.IsNullOrEmpty(tDetails.mesh.name))
tDetails.mesh.name = tDetails.FoundInMeshFilters[0].gameObject.name;
if (UnityEngine.GUI.Button(cellRect, tDetails.mesh.name, buttonStyle))
{
profiler.SelectObject(tDetails.mesh, profiler.ctrlPressed);
}
}
private void DrawVertexCount(MeshDetails tDetails, Rect cellRect)
{
EditorGUI.LabelField(cellRect, tDetails.mesh.vertexCount.ToString(), labelStyle);
}
private void DrawGameObjectsButton(MeshDetails tDetails, Rect cellRect)
{
if (UnityEngine.GUI.Button(cellRect, tDetails.FoundInMeshFilters.Count + " GO", buttonStyle))
{
List<Object> foundObjects = new List<Object>();
foreach (MeshFilter meshFilter in tDetails.FoundInMeshFilters)
foundObjects.Add(meshFilter.gameObject);
profiler.SelectObjects(foundObjects, profiler.ctrlPressed);
}
}
private void DrawSkinnedMeshButton(MeshDetails tDetails, Rect cellRect)
{
if (tDetails.FoundInSkinnedMeshRenderer.Count > 0)
{
if (UnityEngine.GUI.Button(cellRect, tDetails.FoundInSkinnedMeshRenderer.Count + " skinned mesh GO", buttonStyle))
{
List<Object> foundObjects = new List<Object>();
foreach (SkinnedMeshRenderer skinnedMeshRenderer in tDetails.FoundInSkinnedMeshRenderer)
foundObjects.Add(skinnedMeshRenderer.gameObject);
profiler.SelectObjects(foundObjects, profiler.ctrlPressed);
}
}
else
{
UnityEngine.GUI.color = new Color(defColor.r, defColor.g, defColor.b, 0.5f);
EditorGUI.LabelField(cellRect, "0 skinned mesh", labelStyle);
UnityEngine.GUI.color = defColor;
}
}
private void DrawStaticBatchingButton(MeshDetails tDetails, Rect cellRect)
{
if (tDetails.StaticBatchingEnabled.Count > 0)
{
if (UnityEngine.GUI.Button(cellRect, tDetails.StaticBatchingEnabled.Count + " Static Batching", buttonStyle))
{
List<Object> foundObjects = new List<Object>();
foreach (var obj in tDetails.StaticBatchingEnabled)
foundObjects.Add(obj);
profiler.SelectObjects(foundObjects, profiler.ctrlPressed);
}
}
else
{
UnityEngine.GUI.color = new Color(defColor.r, defColor.g, defColor.b, 0.8f);
EditorGUI.LabelField(cellRect, "0 static batching", labelStyle);
UnityEngine.GUI.color = defColor;
}
}
private void DrawAssetPath(MeshDetails tDetails, Rect cellRect)
{
EditorGUI.LabelField(cellRect, AssetDatabase.GetAssetPath(tDetails.mesh), labelStyle);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d6f96b880d4802a4ca8e8dc321974c45
timeCreated: 1720199301

View File

@ -0,0 +1,123 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace SceneProfiler.Editor.GUI
{
public class MissingProfilerGUI : ProfilerGUI<Missing>
{
public MissingProfilerGUI(SceneProfiler profiler, Color defColor)
: base(profiler, defColor)
{
InitializeColumns();
InitializeColumnHeader();
}
protected override void InitializeColumns()
{
var columnDefinitions = new (string, float, bool)[]
{
("Name", 150, false),
("Type", 100, false),
};
columns = columnDefinitions.Select(def => CreateColumn(def.Item1, def.Item2, def.Item3)).ToArray();
}
protected override List<Missing> GetProfilerItems()
{
return profiler.MissingObjects;
}
protected override int CompareItems(Missing a, Missing b, int columnIndex)
{
switch (columnIndex)
{
case 0: return string.Compare(a.name, b.name);
case 1: return string.Compare(a.type, b.type);
default: return 0;
}
}
public void ListMissing()
{
if (buttonStyle == null || labelStyle == null)
{
InitializeStyles();
}
var headerRect = GUILayoutUtility.GetRect(0, columnHeader.height, GUILayout.ExpandWidth(true));
columnHeader.OnGUI(headerRect, scrollPosition.x);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
foreach (Missing dMissing in profiler.MissingObjects)
{
if (dMissing == null || dMissing.Object == null) continue;
EditorGUILayout.BeginHorizontal();
for (int visibleColumnIndex = 0; visibleColumnIndex < columnHeader.state.visibleColumns.Length; visibleColumnIndex++)
{
int columnIndex = columnHeader.state.visibleColumns[visibleColumnIndex];
Rect cellRect = EditorGUILayout.GetControlRect(GUILayout.Width(columns[columnIndex].width - 3));
cellRect.x += headerRect.x;
Color originalColor = UnityEngine.GUI.color;
switch (columnIndex)
{
case 0:
DrawMissingName(dMissing, cellRect);
break;
case 1:
DrawMissingType(dMissing, cellRect);
break;
}
UnityEngine.GUI.color = originalColor;
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
}
private void DrawMissingName(Missing dMissing, Rect cellRect)
{
if (UnityEngine.GUI.Button(cellRect, dMissing.name, buttonStyle))
{
profiler.SelectObject(dMissing.Object, profiler.ctrlPressed);
}
}
private void DrawMissingType(Missing dMissing, Rect cellRect)
{
Color originalColor = UnityEngine.GUI.color;
switch (dMissing.type)
{
case "lod":
UnityEngine.GUI.color = UnityEngine.GUI.color;
break;
case "mesh":
UnityEngine.GUI.color = UnityEngine.GUI.color;
break;
case "sprite":
UnityEngine.GUI.color = UnityEngine.GUI.color;
break;
case "material":
UnityEngine.GUI.color = UnityEngine.GUI.color;
break;
case "missing script":
UnityEngine.GUI.color = Color.red;
break;
}
EditorGUI.LabelField(cellRect, dMissing.type, labelStyle);
UnityEngine.GUI.color = originalColor;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8c8674e0cbb3eff4483aeee3ab3b6bff
timeCreated: 1720201687

View File

@ -0,0 +1,105 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace SceneProfiler.Editor.GUI
{
public class ParticleSystemsProfilerGUI : ProfilerGUI<ParticleSystemDetails>
{
public ParticleSystemsProfilerGUI(SceneProfiler profiler, Color defColor)
: base(profiler, defColor)
{
InitializeColumns();
InitializeColumnHeader();
}
protected override void InitializeColumns()
{
var columnDefinitions = new (string, float, bool)[]
{
("Particle System", 120, false),
("Material", 120, false),
("Max Particles", 100, false),
("Active Particles", 100, false)
};
columns = columnDefinitions.Select(def => CreateColumn(def.Item1, def.Item2, def.Item3)).ToArray();
}
protected override List<ParticleSystemDetails> GetProfilerItems()
{
return profiler.ActiveParticleSystems;
}
public void ListParticleSystems()
{
if (buttonStyle == null || labelStyle == null)
{
InitializeStyles();
}
var headerRect = GUILayoutUtility.GetRect(0, columnHeader.height, GUILayout.ExpandWidth(true));
columnHeader.OnGUI(headerRect, scrollPosition.x);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
foreach (ParticleSystemDetails psDetails in profiler.ActiveParticleSystems)
{
if (psDetails.particleSystem == null) continue;
EditorGUILayout.BeginHorizontal();
for (int i = 0; i < columns.Length; i++)
{
Rect cellRect = EditorGUILayout.GetControlRect(GUILayout.Width(columns[i].width - 2));
switch (i)
{
case 0:
if (UnityEngine.GUI.Button(cellRect, psDetails.particleSystem.name, buttonStyle))
{
profiler.SelectObject(psDetails.particleSystem, profiler.ctrlPressed);
}
break;
case 1:
if (psDetails.material != null)
{
if (UnityEngine.GUI.Button(cellRect, psDetails.material.name, buttonStyle))
{
profiler.SelectObject(psDetails.material, profiler.ctrlPressed);
}
}
else
{
EditorGUI.LabelField(cellRect, "Material: None");
}
break;
case 2:
EditorGUI.LabelField(cellRect, psDetails.maxParticles.ToString(), labelStyle);
break;
case 3:
EditorGUI.LabelField(cellRect, psDetails.activeParticles.ToString(), labelStyle);
break;
}
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
}
protected override int CompareItems(ParticleSystemDetails a, ParticleSystemDetails b, int columnIndex)
{
switch (columnIndex)
{
case 0: return string.Compare(a.particleSystem.name, b.particleSystem.name);
case 1: return string.Compare(a.material?.name ?? "", b.material?.name ?? "");
case 2: return a.maxParticles.CompareTo(b.maxParticles);
case 3: return a.activeParticles.CompareTo(b.activeParticles);
default: return 0;
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8ea8a0e27b0987f41acaf50aef9f5015
timeCreated: 1720115365

View File

@ -0,0 +1,241 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace SceneProfiler.Editor.GUI
{
public class PhysicsProfilerGUI : ProfilerGUI<PhysicsObjectDetails>
{
public PhysicsProfilerGUI(SceneProfiler profiler, Color defColor)
: base(profiler, defColor)
{
InitializeColumns();
InitializeColumnHeader();
}
protected override void InitializeColumns()
{
var columnDefinitions = new (string, float, bool)[]
{
("Rigidbody", 150, false),
("IsActive", 80, false),
("Mass", 60, false),
("Drag", 60, false),
("Angular Drag", 100, false),
("Kinematic", 100, false),
("Interpolation", 100, false),
("Collision Detection", 150, false),
("Collider Type", 100, false)
};
columns = columnDefinitions.Select(def => CreateColumn(def.Item1, def.Item2, def.Item3)).ToArray();
}
protected override List<PhysicsObjectDetails> GetProfilerItems()
{
return profiler.ActivePhysicsObjects;
}
protected override int CompareItems(PhysicsObjectDetails a, PhysicsObjectDetails b, int columnIndex)
{
switch (columnIndex)
{
case 0: return string.Compare(a.rigidbody.name, b.rigidbody.name);
case 1: return CompareState(a, b);
case 2: return a.mass.CompareTo(b.mass);
case 3: return a.drag.CompareTo(b.drag);
case 4: return a.angularDrag.CompareTo(b.angularDrag);
case 5: return a.isKinematic.CompareTo(b.isKinematic);
case 6: return a.interpolation.CompareTo(b.interpolation);
case 7: return a.collisionDetectionMode.CompareTo(b.collisionDetectionMode);
case 8: return string.Compare(a.colliderType, b.colliderType);
default: return 0;
}
}
private int CompareState(PhysicsObjectDetails a, PhysicsObjectDetails b)
{
int aState = (a.isActive ? 1 : 0) + (!a.isKinematic ? 1 : 0);
int bState = (b.isActive ? 1 : 0) + (!b.isKinematic ? 1 : 0);
return aState.CompareTo(bState);
}
public void ListPhysicsObjects()
{
if (buttonStyle == null || labelStyle == null)
{
InitializeStyles();
}
var headerRect = GUILayoutUtility.GetRect(0, columnHeader.height, GUILayout.ExpandWidth(true));
columnHeader.OnGUI(headerRect, scrollPosition.x);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
foreach (PhysicsObjectDetails obj in profiler.ActivePhysicsObjects)
{
if (obj == null || obj.gameObject == null) continue;
EditorGUILayout.BeginHorizontal();
for (int visibleColumnIndex = 0; visibleColumnIndex < columnHeader.state.visibleColumns.Length; visibleColumnIndex++)
{
int columnIndex = columnHeader.state.visibleColumns[visibleColumnIndex];
Rect cellRect = EditorGUILayout.GetControlRect(GUILayout.Width(columns[columnIndex].width - 3));
cellRect.x += headerRect.x;
switch (columnIndex)
{
case 0:
DrawRigidbodyName(obj, cellRect);
break;
case 1:
DrawIsActive(obj, cellRect);
break;
case 2:
DrawMass(obj, cellRect);
break;
case 3:
DrawDrag(obj, cellRect);
break;
case 4:
DrawAngularDrag(obj, cellRect);
break;
case 5:
DrawKinematic(obj, cellRect);
break;
case 6:
DrawInterpolation(obj, cellRect);
break;
case 7:
DrawCollisionDetection(obj, cellRect);
break;
case 8:
DrawColliderType(obj, cellRect);
break;
}
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
}
private void DrawRigidbodyName(PhysicsObjectDetails obj, Rect cellRect)
{
if (UnityEngine.GUI.Button(cellRect, obj.rigidbody.name, buttonStyle))
{
profiler.SelectObject(obj.gameObject, profiler.ctrlPressed);
}
}
private void DrawIsActive(PhysicsObjectDetails obj, Rect cellRect)
{
EditorGUI.LabelField(cellRect, obj.isActive ? "Enabled" : "Disabled", labelStyle);
}
private void DrawMass(PhysicsObjectDetails obj, Rect cellRect)
{
EditorGUI.LabelField(cellRect, obj.mass.ToString(), labelStyle);
}
private void DrawDrag(PhysicsObjectDetails obj, Rect cellRect)
{
EditorGUI.LabelField(cellRect, obj.drag.ToString(), labelStyle);
}
private void DrawAngularDrag(PhysicsObjectDetails obj, Rect cellRect)
{
EditorGUI.LabelField(cellRect, obj.angularDrag.ToString(), labelStyle);
}
private void DrawKinematic(PhysicsObjectDetails obj, Rect cellRect)
{
var color = obj.isKinematic ? Color.white : new Color(1f, 0.5f, 0f);
var originalColor = UnityEngine.GUI.color;
UnityEngine.GUI.color = color;
EditorGUI.LabelField(cellRect, obj.isKinematic ? "Is Kinematic" : "Not Kinematic", labelStyle);
UnityEngine.GUI.color = originalColor;
}
private void DrawInterpolation(PhysicsObjectDetails obj, Rect cellRect)
{
var color = GetInterpolationColor(obj.rigidbody);
var originalColor = UnityEngine.GUI.color;
UnityEngine.GUI.color = color;
EditorGUI.LabelField(cellRect, obj.interpolation.ToString(), labelStyle);
UnityEngine.GUI.color = originalColor;
}
private void DrawCollisionDetection(PhysicsObjectDetails obj, Rect cellRect)
{
var color = GetCollisionDetectionColor(obj.rigidbody);
var originalColor = UnityEngine.GUI.color;
UnityEngine.GUI.color = color;
EditorGUI.LabelField(cellRect, obj.collisionDetectionMode.ToString(), labelStyle);
UnityEngine.GUI.color = originalColor;
}
private void DrawColliderType(PhysicsObjectDetails obj, Rect cellRect)
{
var color = GetColliderColor(obj.rigidbody);
var originalColor = UnityEngine.GUI.color;
UnityEngine.GUI.color = color;
EditorGUI.LabelField(cellRect, obj.colliderType, labelStyle);
UnityEngine.GUI.color = originalColor;
}
private Color GetInterpolationColor(Rigidbody rb)
{
switch (rb.interpolation)
{
case RigidbodyInterpolation.None:
return Color.white;
case RigidbodyInterpolation.Interpolate:
return new Color(1f, 0.5f, 0f);
case RigidbodyInterpolation.Extrapolate:
return Color.red;
default:
return Color.white;
}
}
private Color GetCollisionDetectionColor(Rigidbody rb)
{
switch (rb.collisionDetectionMode)
{
case CollisionDetectionMode.Discrete:
return Color.white;
case CollisionDetectionMode.Continuous:
return Color.yellow;
case CollisionDetectionMode.ContinuousSpeculative:
return new Color(1f, 0.65f, 0f);
case CollisionDetectionMode.ContinuousDynamic:
return Color.red;
default:
return Color.white;
}
}
private Color GetColliderColor(Rigidbody rb)
{
Collider collider = rb.GetComponent<Collider>();
if (collider is BoxCollider || collider is SphereCollider || collider is CapsuleCollider)
{
return Color.white;
}
else if (collider is MeshCollider)
{
return Color.red;
}
else
{
return new Color(1f, 0.5f, 0f);
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 03816b9027d0ec44aa6aec7f1fd3ed01
timeCreated: 1720188472

View File

@ -0,0 +1,99 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace SceneProfiler.Editor.GUI
{
public abstract class ProfilerGUI<T>
{
protected SceneProfiler profiler;
protected Vector2 scrollPosition;
protected GUIStyle buttonStyle;
protected GUIStyle labelStyle;
protected MultiColumnHeader columnHeader;
protected MultiColumnHeaderState.Column[] columns;
protected Color defColor;
protected Vector2 horizontalScrollPosition;
protected ProfilerGUI(SceneProfiler profiler, Color defColor)
{
this.profiler = profiler;
this.defColor = defColor;
}
protected abstract void InitializeColumns();
protected abstract List<T> GetProfilerItems();
protected void InitializeStyles()
{
buttonStyle = new GUIStyle(UnityEngine.GUI.skin.button)
{
padding = new RectOffset(2, 2, 2, 2),
margin = new RectOffset(0, 0, 0, 0),
alignment = TextAnchor.MiddleCenter
};
labelStyle = new GUIStyle(EditorStyles.label)
{
alignment = TextAnchor.MiddleLeft
};
}
protected abstract int CompareItems(T a, T b, int columnIndex);
protected MultiColumnHeaderState.Column CreateColumn(string headerText, float width, bool autoResize)
{
return new MultiColumnHeaderState.Column
{
headerContent = new GUIContent(headerText),
width = width,
minWidth = width / 4,
maxWidth = width * 2,
headerTextAlignment = TextAlignment.Left,
sortingArrowAlignment = TextAlignment.Right,
autoResize = autoResize,
allowToggleVisibility = true
};
}
protected void InitializeColumnHeader()
{
columnHeader = new MultiColumnHeader(new MultiColumnHeaderState(columns))
{
height = 20,
canSort = true
};
columnHeader.sortingChanged += OnSortingChanged;
columnHeader.visibleColumnsChanged += OnVisibleColumnsChanged;
}
protected void OnSortingChanged(MultiColumnHeader multiColumnHeader)
{
var sortColumnIndex = multiColumnHeader.sortedColumnIndex;
var sortAscending = multiColumnHeader.IsSortedAscending(sortColumnIndex);
var items = GetProfilerItems();
items.Sort((a, b) => CompareItems(a, b, sortColumnIndex));
if (!sortAscending)
{
items.Reverse();
}
}
protected void OnVisibleColumnsChanged(MultiColumnHeader multiColumnHeader)
{
SceneView.RepaintAll();
}
public static Color AdjustBrightness(Color color, float adjustment)
{
float r = Mathf.Clamp01(color.r + adjustment);
float g = Mathf.Clamp01(color.g + adjustment);
float b = Mathf.Clamp01(color.b + adjustment);
return new Color(r, g, b, color.a);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2dd439b49e79e7c4990370dbcd8c8922
timeCreated: 1720118705

View File

@ -0,0 +1,273 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace SceneProfiler.Editor.GUI
{
public class SceneProfilerGUI
{
private SceneProfiler _profiler;
private Color _defColor;
private Vector2 _scrollPosition;
private Vector2 _particleSystemScrollPosition;
private Vector2 _warningsScrollPosition;
private GUIStyle _evenRowStyle;
private GUIStyle _oddRowStyle;
private GUIStyle _headerStyle;
private GUIStyle _buttonStyle;
private readonly float buttonHeight = 50f;
private bool _showWarnings = false;
private float _rowHeight = 20f;
private ParticleSystemsProfilerGUI _particleSystemsProfilerGUI;
private LightsProfilerGUI _lightsProfilerGUI;
private TexturesProfilerGUI _texturesProfilerGUI;
private PhysicsProfilerGUI _physicsProfilerGUI;
private MeshesProfilerGUI _meshesProfilerGUI;
private MaterialsProfilerGUI _materialsProfilerGUI;
private MissingProfilerGUI _missingProfilerGUI;
private AudioClipsProfilerGUI _audioClipsProfilerGUI;
private WarningsGUI _warningsGUI;
private ExpensiveProfilerGUI _expensiveProfilerGUI;
private Dictionary<SceneProfiler.InspectType, bool> _moduleStates = new Dictionary<SceneProfiler.InspectType, bool>();
public SceneProfilerGUI(SceneProfiler profiler)
{
this._profiler = profiler;
_particleSystemsProfilerGUI = new ParticleSystemsProfilerGUI(profiler, _defColor);
_lightsProfilerGUI = new LightsProfilerGUI(profiler, _defColor);
_texturesProfilerGUI = new TexturesProfilerGUI(profiler, _defColor, () => _rowHeight);
_physicsProfilerGUI = new PhysicsProfilerGUI(profiler, _defColor);
_meshesProfilerGUI = new MeshesProfilerGUI(profiler, _defColor);
_materialsProfilerGUI = new MaterialsProfilerGUI(profiler, _defColor, () => _rowHeight);
_missingProfilerGUI = new MissingProfilerGUI(profiler, _defColor);
_audioClipsProfilerGUI = new AudioClipsProfilerGUI(profiler, _defColor, () => _rowHeight);
_expensiveProfilerGUI = new ExpensiveProfilerGUI(profiler, _defColor);
_warningsGUI = new WarningsGUI(profiler);
_moduleStates = new Dictionary<SceneProfiler.InspectType, bool>
{
{ SceneProfiler.InspectType.Textures, true },
{ SceneProfiler.InspectType.Materials, true },
{ SceneProfiler.InspectType.Meshes, true },
{ SceneProfiler.InspectType.AudioClips, true },
{ SceneProfiler.InspectType.Particles, true },
{ SceneProfiler.InspectType.Lights, true },
{ SceneProfiler.InspectType.Physics, true },
{ SceneProfiler.InspectType.Missing, true },
{ SceneProfiler.InspectType.Expensive, true }
};
}
public SceneProfiler Profiler => _profiler;
private GUIStyle ButtonStyle
{
get
{
if (_buttonStyle == null)
{
_buttonStyle = new GUIStyle(EditorStyles.toolbarButton)
{
fixedHeight = buttonHeight
};
}
return _buttonStyle;
}
}
public void DrawGUI()
{
_defColor = UnityEngine.GUI.color;
GUILayout.BeginHorizontal(EditorStyles.toolbar);
UnityEngine.GUI.color = new Color(1.4f, 1.4f, 1.4f);
if (GUILayout.Button(new GUIContent("Collect Data", "Collects data from all objects in the current scene"), EditorStyles.toolbarButton))
{
_profiler.CollectData();
}
UnityEngine.GUI.color = _defColor;
if (GUILayout.Button(new GUIContent("Clear", "Clears the collected data and refreshes the interface"), EditorStyles.toolbarButton))
{
_profiler.ClearAndRepaint();
}
DrawModuleDropdownMenu();
GUILayout.FlexibleSpace();
if (_profiler.ActiveInspectType == SceneProfiler.InspectType.Textures && _texturesProfilerGUI != null && _profiler.ActiveTextures.Count > 0 ||
_profiler.ActiveInspectType == SceneProfiler.InspectType.Materials && _materialsProfilerGUI != null && _profiler.ActiveMaterials.Count > 0 ||
_profiler.ActiveInspectType == SceneProfiler.InspectType.AudioClips && _audioClipsProfilerGUI != null && _profiler.ActiveClipDetails.Count > 0)
{
_rowHeight = GUILayout.HorizontalSlider(_rowHeight, 20, 200, GUILayout.Width(100));
}
Rect settingsButtonRect = GUILayoutUtility.GetRect(new GUIContent("Settings", "Opens the settings menu for the profiler"), EditorStyles.toolbarButton);
if (UnityEngine.GUI.Button(settingsButtonRect, new GUIContent("Settings", "Opens the settings menu for the profiler"), EditorStyles.toolbarButton))
{
ShowSettingsMenu(settingsButtonRect);
}
DrawWarningButton();
GUILayout.EndHorizontal();
UnityEngine.GUI.color = new Color(1.4f, 1.4f, 1.4f);
GUILayout.BeginHorizontal();
float windowWidth = EditorGUIUtility.currentViewWidth;
int activeButtonCount = 0;
foreach (var state in _moduleStates.Values)
{
if (state) activeButtonCount++;
}
float buttonWidth = windowWidth / activeButtonCount;
GUILayoutOption buttonHeightOption = GUILayout.Height(buttonHeight + 1);
GUILayoutOption buttonWidthOption = GUILayout.Width(buttonWidth);
string[] toolbarLabels = {
$"Textures ({_profiler.ActiveTextures.Count})\n{_profiler.FormatSizeString(_profiler.TotalTextureMemory)}",
$"Materials ({_profiler.ActiveMaterials.Count})\n{_profiler.UniqueShadersCount} shaders",
$"Meshes ({_profiler.ActiveMeshDetails.Count})\n{_profiler.TotalMeshVertices} vertices",
$"Audio ({_profiler.ActiveClipDetails.Count})",
$"Missing ({_profiler.MissingObjects.Count})",
$"Particles ({_profiler.ActiveParticleSystems.Count})",
$"Lights ({_profiler.ActiveLights.Count})",
$"Physics ({_profiler.ActivePhysicsObjects.Count})",
$"Expensive ({_profiler.ActiveExpensiveObjects.Count})"
};
for (int i = 0; i < toolbarLabels.Length; i++)
{
if (_moduleStates[(SceneProfiler.InspectType)i])
{
if (GUILayout.Toggle(_profiler.ActiveInspectType == (SceneProfiler.InspectType)i, toolbarLabels[i], ButtonStyle, buttonWidthOption, buttonHeightOption))
{
_profiler.ActiveInspectType = (SceneProfiler.InspectType)i;
}
}
}
UnityEngine.GUI.color = _defColor;
GUILayout.EndHorizontal();
_profiler.ctrlPressed = Event.current.control || Event.current.command;
if (_showWarnings)
{
_warningsGUI.DrawWarnings(ref _warningsScrollPosition);
}
switch (_profiler.ActiveInspectType)
{
case SceneProfiler.InspectType.Textures:
_texturesProfilerGUI.ListTextures();
break;
case SceneProfiler.InspectType.Materials:
_materialsProfilerGUI.ListMaterials();
break;
case SceneProfiler.InspectType.Meshes:
_meshesProfilerGUI.ListMeshes();
break;
case SceneProfiler.InspectType.Missing:
_missingProfilerGUI.ListMissing();
break;
case SceneProfiler.InspectType.AudioClips:
_audioClipsProfilerGUI.ListAudioClips();
break;
case SceneProfiler.InspectType.Particles:
_particleSystemsProfilerGUI.ListParticleSystems();
break;
case SceneProfiler.InspectType.Lights:
_lightsProfilerGUI.ListLights();
break;
case SceneProfiler.InspectType.Physics:
_physicsProfilerGUI.ListPhysicsObjects();
break;
case SceneProfiler.InspectType.Expensive:
_expensiveProfilerGUI.ListExpensiveObjects();
break;
}
}
private void ShowSettingsMenu(Rect buttonRect)
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Include disabled objects"), _profiler.includeDisabledObjects, () => _profiler.includeDisabledObjects = !_profiler.includeDisabledObjects);
menu.AddItem(new GUIContent("Look in sprite animations (Textures)"), _profiler.IncludeSpriteAnimations, () => _profiler.IncludeSpriteAnimations = !_profiler.IncludeSpriteAnimations);
menu.AddItem(new GUIContent("Look in behavior fields (Textures, mats, meshes)"), _profiler.IncludeScriptReferences, () => _profiler.IncludeScriptReferences = !_profiler.IncludeScriptReferences);
menu.AddItem(new GUIContent("Look in GUI elements (Textures, mats)"), _profiler.IncludeGuiElements, () => _profiler.IncludeGuiElements = !_profiler.IncludeGuiElements);
menu.AddItem(new GUIContent("Look in Lightmap textures"), _profiler.IncludeLightmapTextures, () => _profiler.IncludeLightmapTextures = !_profiler.IncludeLightmapTextures);
menu.AddItem(new GUIContent("Look in Selected Folders (Textures, Audio)"), _profiler.IncludeSelectedFolder, () => _profiler.IncludeSelectedFolder = !_profiler.IncludeSelectedFolder);
menu.DropDown(new Rect(buttonRect.x, buttonRect.yMax, 0, 0));
}
private void DrawWarningButton()
{
GUIContent warningButtonContent = new GUIContent
{
image = _warningsGUI.GetWarningButtonIcon(),
tooltip = "Toggle the display of warning messages"
};
if (GUILayout.Button(warningButtonContent, EditorStyles.toolbarButton))
{
_showWarnings = !_showWarnings;
}
}
private void DrawModuleDropdownMenu()
{
if (GUILayout.Button(new GUIContent("Modules", "Toggle the display of modules"), EditorStyles.toolbarDropDown))
{
Rect dropdownRect = GUILayoutUtility.GetLastRect();
GenericMenu menu = new GenericMenu();
foreach (SceneProfiler.InspectType type in System.Enum.GetValues(typeof(SceneProfiler.InspectType)))
{
SceneProfiler.InspectType localType = type;
menu.AddItem(new GUIContent(type.ToString()), _moduleStates[type], () => ToggleModuleState(localType));
}
menu.DropDown(new Rect(120, 20, 0, 0));
}
}
private void ToggleModuleState(SceneProfiler.InspectType type)
{
if (_moduleStates[type])
{
int activeCount = 0;
foreach (var state in _moduleStates.Values)
{
if (state) activeCount++;
}
if (activeCount <= 1) return;
}
_moduleStates[type] = !_moduleStates[type];
if (!_moduleStates[_profiler.ActiveInspectType])
{
foreach (var key in _moduleStates.Keys)
{
if (_moduleStates[key])
{
_profiler.ActiveInspectType = key;
break;
}
}
}
_profiler.ClearAndRepaint();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 14b216fd6ddd1f548a71cbe57b73f424
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,262 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace SceneProfiler.Editor.GUI
{
public class TexturesProfilerGUI : ProfilerGUI<TextureDetails>
{
private Func<float> _getRowHeight;
private Dictionary<Texture, Texture2D> texturePreviewCache = new Dictionary<Texture, Texture2D>();
public TexturesProfilerGUI(SceneProfiler profiler, Color defColor, Func<float> getRowHeight)
: base(profiler, defColor)
{
_getRowHeight = getRowHeight;
InitializeColumns();
InitializeColumnHeader();
}
protected override void InitializeColumns()
{
var columnDefinitions = new (string, float, bool)[]
{
("Thumbnail", 70, false),
("Texture", 150, false),
("Resolution", 80, false),
("Size", 60, false),
("Mipmap", 50, false),
("Format", 100, false),
("Materials", 60, false),
("GameObjects", 100, false),
("Path", 500, true)
};
columns = columnDefinitions.Select(def => CreateColumn(def.Item1, def.Item2, def.Item3)).ToArray();
}
protected override List<TextureDetails> GetProfilerItems()
{
return profiler.ActiveTextures;
}
protected override int CompareItems(TextureDetails a, TextureDetails b, int columnIndex)
{
if (a == null && b == null) return 0;
if (a == null) return -1;
if (b == null) return 1;
switch (columnIndex)
{
case 0: return 0;
case 1: return string.Compare(a.texture?.name, b.texture?.name);
case 2: return (a.texture?.width * a.texture?.height ?? 0).CompareTo(b.texture?.width * b.texture?.height ?? 0); // Resolution
case 3: return a.memSizeKB.CompareTo(b.memSizeKB); // Size
case 4: return a.mipMapCount.CompareTo(b.mipMapCount); // Mipmap
case 5: return string.Compare(a.format.ToString(), b.format.ToString()); // Format
case 6: return a.FoundInMaterials.Count.CompareTo(b.FoundInMaterials.Count);
case 7:
int aCount = (a.FoundInRenderers?.Count ?? 0) + (a.FoundInAnimators?.Count ?? 0) +
(a.FoundInGraphics?.Count ?? 0) + (a.FoundInButtons?.Count ?? 0) +
(a.FoundInScripts?.Count ?? 0);
int bCount = (b.FoundInRenderers?.Count ?? 0) + (b.FoundInAnimators?.Count ?? 0) +
(b.FoundInGraphics?.Count ?? 0) + (b.FoundInButtons?.Count ?? 0) +
(b.FoundInScripts?.Count ?? 0);
return aCount.CompareTo(bCount);
case 8: return string.Compare(AssetDatabase.GetAssetPath(a.texture), AssetDatabase.GetAssetPath(b.texture));
default: return 0;
}
}
public void ListTextures()
{
if (buttonStyle == null || labelStyle == null)
{
InitializeStyles();
}
var headerRect = GUILayoutUtility.GetRect(0, columnHeader.height, GUILayout.ExpandWidth(true));
columnHeader.OnGUI(headerRect, scrollPosition.x);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
int displayedTextures = 0;
foreach (TextureDetails tDetails in profiler.ActiveTextures)
{
if (displayedTextures >= profiler.currentObjectsInColumnCount) break;
if (tDetails.texture == null) continue;
EditorGUILayout.BeginHorizontal();
for (int visibleColumnIndex = 0; visibleColumnIndex < columnHeader.state.visibleColumns.Length; visibleColumnIndex++)
{
int columnIndex = columnHeader.state.visibleColumns[visibleColumnIndex];
Rect cellRect = EditorGUILayout.GetControlRect(GUILayout.Width(columns[columnIndex].width - 4), GUILayout.Height(_getRowHeight()));
cellRect.x += headerRect.x;
switch (columnIndex)
{
case 0:
DrawThumbnail(tDetails, cellRect);
break;
case 1:
DrawTextureName(tDetails, cellRect);
break;
case 2:
DrawResolution(tDetails, cellRect);
break;
case 3:
DrawTextureSize(tDetails, cellRect);
break;
case 4:
DrawMipmap(tDetails, cellRect);
break;
case 5:
DrawTextureFormat(tDetails, cellRect);
break;
case 6:
DrawMaterialsButton(tDetails, cellRect);
break;
case 7:
DrawGameObjectsButton(tDetails, cellRect);
break;
case 8:
DrawTexturePath(tDetails, cellRect);
break;
}
}
EditorGUILayout.EndHorizontal();
displayedTextures++;
}
if (profiler.currentObjectsInColumnCount < profiler.ActiveTextures.Count)
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Load More", GUILayout.Width(150)))
{
profiler.currentObjectsInColumnCount += 100;
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
}
private void DrawThumbnail(TextureDetails tDetails, Rect cellRect)
{
if (!texturePreviewCache.TryGetValue(tDetails.texture, out var previewTexture) || previewTexture == null)
{
if (tDetails.texture.GetType() == typeof(Texture2DArray) || tDetails.texture.GetType() == typeof(Cubemap))
{
previewTexture = AssetPreview.GetMiniThumbnail(tDetails.texture);
}
else
{
previewTexture = AssetPreview.GetAssetPreview(tDetails.texture);
}
if (previewTexture == null)
{
previewTexture = AssetPreview.GetMiniThumbnail(tDetails.texture);
}
texturePreviewCache[tDetails.texture] = previewTexture;
}
if (previewTexture != null)
{
UnityEngine.GUI.DrawTexture(cellRect, previewTexture, ScaleMode.ScaleToFit);
}
else
{
EditorGUI.LabelField(cellRect, "No Preview", labelStyle);
}
}
private void DrawTextureName(TextureDetails tDetails, Rect cellRect)
{
if (UnityEngine.GUI.Button(cellRect, tDetails.texture.name, buttonStyle))
{
profiler.SelectObject(tDetails.texture, profiler.ctrlPressed);
}
}
private void DrawResolution(TextureDetails tDetails, Rect cellRect)
{
string resolution = $"{tDetails.texture.width}x{tDetails.texture.height}";
if (tDetails.isCubeMap) resolution += "x6";
if (tDetails.texture.GetType() == typeof(Texture2DArray))
resolution += "[]\n" + ((Texture2DArray)tDetails.texture).depth + " depths";
EditorGUI.LabelField(cellRect, resolution, labelStyle);
}
private void DrawTextureSize(TextureDetails tDetails, Rect cellRect)
{
double roundedSizeKB = Math.Round(tDetails.memSizeKB, 1);
string size = profiler.FormatSizeString((float)roundedSizeKB);
EditorGUI.LabelField(cellRect, size, labelStyle);
}
private void DrawMipmap(TextureDetails tDetails, Rect cellRect)
{
string mipmap = tDetails.mipMapCount.ToString();
EditorGUI.LabelField(cellRect, mipmap, labelStyle);
}
private void DrawTextureFormat(TextureDetails tDetails, Rect cellRect)
{
string format = tDetails.format.ToString();
EditorGUI.LabelField(cellRect, format, labelStyle);
}
private void DrawMaterialsButton(TextureDetails tDetails, Rect cellRect)
{
if (UnityEngine.GUI.Button(cellRect, tDetails.FoundInMaterials.Count + " Mat", buttonStyle))
{
profiler.SelectObjects(tDetails.FoundInMaterials, profiler.ctrlPressed);
}
}
private void DrawGameObjectsButton(TextureDetails tDetails, Rect cellRect)
{
HashSet<Object> FoundObjects = new HashSet<Object>();
foreach (Renderer renderer in tDetails.FoundInRenderers)
{
if (renderer != null) FoundObjects.Add(renderer.gameObject);
}
foreach (Animator animator in tDetails.FoundInAnimators)
{
if (animator != null) FoundObjects.Add(animator.gameObject);
}
foreach (Graphic graphic in tDetails.FoundInGraphics)
{
if (graphic != null) FoundObjects.Add(graphic.gameObject);
}
foreach (Button button in tDetails.FoundInButtons)
{
if (button != null) FoundObjects.Add(button.gameObject);
}
foreach (MonoBehaviour script in tDetails.FoundInScripts)
{
if (script != null) FoundObjects.Add(script.gameObject);
}
if (UnityEngine.GUI.Button(cellRect, FoundObjects.Count + " GO", buttonStyle))
{
profiler.SelectObjects(new List<Object>(FoundObjects), profiler.ctrlPressed);
}
}
private void DrawTexturePath(TextureDetails tDetails, Rect cellRect)
{
EditorGUI.LabelField(cellRect, AssetDatabase.GetAssetPath(tDetails.texture), labelStyle);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fa5bd73e452f4404d94210de608dad94
timeCreated: 1720123653

View File

@ -0,0 +1,85 @@
using UnityEditor;
using UnityEngine;
namespace SceneProfiler.Editor.GUI
{
public class WarningsGUI
{
private SceneProfiler _profiler;
public WarningsGUI(SceneProfiler profiler)
{
_profiler = profiler;
}
public void DrawWarnings(ref Vector2 scrollPosition)
{
if (_profiler.Warnings == null || _profiler.Warnings.Count == 0)
return;
float contentHeight = GetWarningsContentHeight();
float windowHeight = EditorGUIUtility.currentViewWidth;
float scrollViewHeight = Mathf.Min(contentHeight, windowHeight / 2);
scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Height(scrollViewHeight));
GUILayout.BeginVertical("box");
foreach (var warning in _profiler.Warnings)
{
EditorGUILayout.HelpBox(warning.Message, warning.Type);
}
GUILayout.EndVertical();
GUILayout.EndScrollView();
}
public Texture GetWarningButtonIcon()
{
if (_profiler.Warnings == null || _profiler.Warnings.Count == 0)
{
return EditorGUIUtility.IconContent("console.infoicon.sml").image;
}
bool hasErrors = false;
bool hasWarnings = false;
bool hasInfo = false;
foreach (var warning in _profiler.Warnings)
{
switch (warning.Type)
{
case MessageType.Error:
hasErrors = true;
break;
case MessageType.Warning:
hasWarnings = true;
break;
case MessageType.Info:
hasInfo = true;
break;
}
}
if (hasErrors)
{
return EditorGUIUtility.IconContent("console.erroricon.sml").image;
}
if (hasWarnings)
{
return EditorGUIUtility.IconContent("console.warnicon.sml").image;
}
if (hasInfo)
{
return EditorGUIUtility.IconContent("console.infoicon.sml").image;
}
return EditorGUIUtility.IconContent("console.infoicon.sml").image;
}
private float GetWarningsContentHeight()
{
int messageCount = _profiler.Warnings?.Count ?? 0;
return messageCount * EditorGUIUtility.singleLineHeight * 2.5f;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a5e96b3818982d64c8db4a30859b2245
timeCreated: 1720279199

View File

@ -0,0 +1,475 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using SceneProfiler.Editor.GUI;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
using Application = UnityEngine.Application;
using Object = UnityEngine.Object;
namespace SceneProfiler.Editor
{
public class SceneProfiler : EditorWindow
{
public enum InspectType
{
Textures, Materials, Meshes, AudioClips, Missing, Particles, Lights, Physics, Expensive
};
public bool includeDisabledObjects = true;
public bool IncludeSpriteAnimations = true;
public bool IncludeScriptReferences = true;
public bool IncludeGuiElements = true;
public bool IncludeLightmapTextures = true;
public bool IncludeSelectedFolder = false;
public bool thingsMissing = false;
public InspectType ActiveInspectType = InspectType.Textures;
public List<TextureDetails> ActiveTextures = new List<TextureDetails>();
public List<MaterialDetails> ActiveMaterials = new List<MaterialDetails>();
public List<MeshDetails> ActiveMeshDetails = new List<MeshDetails>();
public List<AudioClipDetails> ActiveClipDetails = new List<AudioClipDetails>();
public List<ParticleSystemDetails> ActiveParticleSystems = new List<ParticleSystemDetails>();
public List<Missing> MissingObjects = new List<Missing>();
public List<LightDetails> ActiveLights = new List<LightDetails>();
public List<PhysicsObjectDetails> ActivePhysicsObjects = new List<PhysicsObjectDetails>();
public List<SceneWarningDetails> Warnings = new List<SceneWarningDetails>();
public List<ExpensiveObjectDetails> ActiveExpensiveObjects = new List<ExpensiveObjectDetails>();
public float TotalTextureMemory = 0;
public int TotalMeshVertices = 0;
public bool ctrlPressed = false;
private static int _minWidth = 800;
public int currentObjectsInColumnCount = 100;
private SceneProfilerGUI _sceneProfilerGUI;
private CollectTextureData _collectTextureData;
private CollectMaterialsData _collectMaterialsData;
private CollectAudioClipData _collectAudioClipData;
private CollectMeshData _collectMeshData;
private CollectParticleSystemData _сollectParticleSystemData;
private CollectLightData _collectLightData;
private CollectPhysicsData _collectPhysicsData;
private CollectWarningsData _collectWarningsData;
private CollectExpensiveObject _collectExpensiveObject;
[MenuItem("Window/Analysis/Scene Profiler")]
public static void Init()
{
SceneProfiler window = (SceneProfiler)EditorWindow.GetWindow(typeof(SceneProfiler));
GUIContent titleContent = EditorGUIUtility.IconContent("UnityEditor.SceneView");
titleContent.text = "Scene Profiler";
window.titleContent = titleContent;
window.minSize = new Vector2(_minWidth, 400);
}
private void OnEnable()
{
_sceneProfilerGUI = new SceneProfilerGUI(this);
_collectTextureData = new CollectTextureData(this);
_collectMaterialsData = new CollectMaterialsData(this);
_collectAudioClipData = new CollectAudioClipData(this);
_collectMeshData = new CollectMeshData(this);
_сollectParticleSystemData = new CollectParticleSystemData(this);
_collectLightData = new CollectLightData(this);
_collectPhysicsData = new CollectPhysicsData(this);
_collectWarningsData = new CollectWarningsData(this);
_collectExpensiveObject = new CollectExpensiveObject(this);
EditorSceneManager.sceneOpened += OnSceneOpened;
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
SceneManager.sceneUnloaded += OnSceneUnloaded;
SceneManager.sceneLoaded += OnSceneLoaded;
ClearAndRepaint();
}
private void OnDisable()
{
EditorSceneManager.sceneOpened -= OnSceneOpened;
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
}
private void OnSceneOpened(Scene scene, OpenSceneMode mode)
{
ClearAndRepaint();
}
private void OnSceneUnloaded(Scene scene)
{
ClearAndRepaint();
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
ClearAndRepaint();
}
private void OnPlayModeStateChanged(PlayModeStateChange state)
{
if (state == PlayModeStateChange.EnteredPlayMode || state == PlayModeStateChange.ExitingPlayMode)
{
ClearAndRepaint();
}
}
public void ClearAndRepaint()
{
ActiveTextures.Clear();
ActiveMaterials.Clear();
ActiveMeshDetails.Clear();
ActiveClipDetails.Clear();
MissingObjects.Clear();
ActiveParticleSystems.Clear();
ActiveLights.Clear();
ActivePhysicsObjects.Clear();
ActiveExpensiveObjects.Clear();
Warnings.Clear();
TotalTextureMemory = 0;
TotalMeshVertices = 0;
thingsMissing = false;
Repaint();
}
void OnGUI()
{
_sceneProfilerGUI.DrawGUI();
}
public int UniqueShadersCount
{
get
{
return ActiveMaterials
.Where(mat => mat.material != null && mat.material.shader != null)
.Select(mat => mat.material.shader)
.Distinct()
.Count();
}
}
public void SelectObject(Object selectedObject, bool append)
{
if (append)
{
List<Object> currentSelection = new List<Object>(Selection.objects);
if (currentSelection.Contains(selectedObject)) currentSelection.Remove(selectedObject);
else currentSelection.Add(selectedObject);
Selection.objects = currentSelection.ToArray();
}
else Selection.activeObject = selectedObject;
}
public void SelectObjects(List<Object> selectedObjects, bool append)
{
if (append)
{
List<Object> currentSelection = new List<Object>(Selection.objects);
currentSelection.AddRange(selectedObjects);
Selection.objects = currentSelection.ToArray();
}
else Selection.objects = selectedObjects.ToArray();
}
private static int MaterialSorter(MaterialDetails first, MaterialDetails second)
{
var firstIsNull = first.material == null;
var secondIsNull = second.material == null;
if (firstIsNull && secondIsNull) return 0;
if (firstIsNull) return int.MaxValue;
if (secondIsNull) return int.MinValue;
return first.material.renderQueue - second.material.renderQueue;
}
public string FormatSizeString(float memSizeKB)
{
if (memSizeKB < 1024) return "" + memSizeKB + "k";
else
{
float memSizeMB = ((float)memSizeKB) / 1024.0f;
return memSizeMB.ToString("0.00") + "Mb";
}
}
// Main method
public void CollectData()
{
ActiveTextures.Clear();
ActiveMaterials.Clear();
ActiveMeshDetails.Clear();
MissingObjects.Clear();
ActiveClipDetails.Clear();
ActiveParticleSystems.Clear();
ActiveLights.Clear();
ActivePhysicsObjects.Clear();
ActiveExpensiveObjects.Clear();
thingsMissing = false;
_collectExpensiveObject.CollectData();
_сollectParticleSystemData.CheckParticleSystems();
_collectLightData.CheckLights();
_collectPhysicsData.CheckPhysicsObjects();
_collectMaterialsData.CheckRenderers();
_collectTextureData.CheckRenderers();
_collectTextureData.CheckLightmaps();
_collectMaterialsData.CheckGUIElements();
_collectTextureData.CheckGUIElements();
_collectMeshData.CheckMeshFilters();
_collectMeshData.CheckSkinnedMeshRenderers();
_collectMeshData.CheckLODGroups();
_collectTextureData.CheckSelectedFolder();
_collectAudioClipData.CheckSelectedFolder();
_collectTextureData.CheckSpriteAnimations();
CheckScriptReferences();
_collectTextureData.CheckMaterials(); //Collect all materials before
_collectAudioClipData.CheckAudioSources();
CheckForMissingScriptsInAllGameObjects();
CalculateTotals();
ActiveMaterials.Sort(MaterialSorter);
CheckWarnings();
}
public void AddMissingSprite(SpriteRenderer tSpriteRenderer)
{
Missing tMissing = new Missing
{
Object = tSpriteRenderer.transform,
type = "sprite",
name = tSpriteRenderer.transform.name
};
MissingObjects.Add(tMissing);
thingsMissing = true;
}
private void CheckScriptReferences()
{
if (!IncludeScriptReferences) return;
MonoBehaviour[] scripts = FindObjects<MonoBehaviour>();
foreach (MonoBehaviour script in scripts)
{
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
FieldInfo[] fields = script.GetType().GetFields(flags);
foreach (FieldInfo field in fields)
{
_collectTextureData.CheckSpriteReferences(field, script);
_collectMeshData.CheckMeshReferences(field, script);
CheckMaterialReferences(field, script);
_collectAudioClipData.CheckAudioClipReferences(field, script);
_collectLightData.CheckLightReferences(field, script);
_сollectParticleSystemData.CheckParticleSystemReferences(field, script);
_collectPhysicsData.CheckRigidbodyReferences(field, script);
}
}
}
private void CheckMaterialReferences(FieldInfo field, MonoBehaviour script)
{
if (field.FieldType == typeof(Material))
{
Material tMaterial = field.GetValue(script) as Material;
if (tMaterial != null)
{
_collectMaterialsData.AddMaterialDetails(tMaterial);
_collectTextureData.CheckMaterialTextures(tMaterial);
_collectTextureData.CheckMaterialDependencies(tMaterial);
}
}
}
private void CheckForMissingScriptsInAllGameObjects()
{
GameObject[] allGameObjects = GetAllRootGameObjects();
foreach (GameObject go in allGameObjects)
{
CheckForMissingScripts(go);
}
}
void CheckForMissingScripts(GameObject go)
{
Component[] components = go.GetComponents<Component>();
foreach (Component component in components)
{
if (component == null)
{
Missing tMissing = new Missing();
tMissing.Object = go.transform;
tMissing.type = "missing script";
tMissing.name = go.name;
MissingObjects.Add(tMissing);
thingsMissing = true;
}
}
foreach (Transform child in go.transform)
{
CheckForMissingScripts(child.gameObject);
}
}
private void CalculateTotals()
{
TotalMeshVertices = 0;
foreach (MeshDetails tMeshDetails in ActiveMeshDetails) TotalMeshVertices += tMeshDetails.mesh.vertexCount;
ActiveTextures.Sort(delegate (TextureDetails details1, TextureDetails details2) { return (int)(details2.memSizeKB - details1.memSizeKB); });
ActiveTextures = ActiveTextures.Distinct().ToList();
TotalTextureMemory = 0;
foreach (TextureDetails tTextureDetails in ActiveTextures) TotalTextureMemory += tTextureDetails.memSizeKB;
ActiveMeshDetails.Sort(delegate (MeshDetails details1, MeshDetails details2) { return details2.mesh.vertexCount - details1.mesh.vertexCount; });
}
private void CheckWarnings()
{
Warnings.Clear();
if (thingsMissing)
{
Warnings.Add(new SceneWarningDetails("Some GameObjects are missing elements.", MessageType.Error));
}
float sceneFileSizeMB = _collectWarningsData.GetSceneFileSize();
Warnings.Add(new SceneWarningDetails($"Scene file size: {sceneFileSizeMB:F2} MB.", MessageType.Info));
int objectCount = _collectWarningsData.CountObjectsInScene();
Warnings.Add(new SceneWarningDetails($"There are {objectCount} objects in the scene.", MessageType.Info));
int canvasCount = _collectWarningsData.CountCanvasComponentsInScene();
if (canvasCount > 0)
{
Warnings.Add(new SceneWarningDetails($"There are {canvasCount} Canvas components in the scene.", MessageType.Info));
}
var platformsWithoutStaticBatching = _collectWarningsData.GetPlatformsWithoutStaticBatching();
if (platformsWithoutStaticBatching.Count > 0)
{
string message = "Static batching is not enabled: " + string.Join(", ", platformsWithoutStaticBatching);
Warnings.Add(new SceneWarningDetails(message, MessageType.Warning));
}
}
public GameObject[] GetAllRootGameObjects()
{
List<GameObject> allGo = new List<GameObject>();
for (int sceneIdx = 0; sceneIdx < UnityEngine.SceneManagement.SceneManager.sceneCount; ++sceneIdx)
{
Scene scene = UnityEngine.SceneManagement.SceneManager.GetSceneAt(sceneIdx);
if (scene.isLoaded)
{
allGo.AddRange(scene.GetRootGameObjects());
}
}
allGo.AddRange(GetDontDestroyOnLoadRoots());
return allGo.ToArray();
}
private static List<GameObject> GetDontDestroyOnLoadRoots()
{
List<GameObject> objs = new List<GameObject>();
if (Application.isPlaying)
{
GameObject temp = null;
try
{
temp = new GameObject();
DontDestroyOnLoad(temp);
UnityEngine.SceneManagement.Scene dontDestryScene = temp.scene;
DestroyImmediate(temp);
temp = null;
if(dontDestryScene.IsValid())
{
objs = dontDestryScene.GetRootGameObjects().ToList();
}
}
catch (System.Exception e)
{
Debug.LogException(e);
return null;
}
finally
{
if(temp != null)
DestroyImmediate(temp);
}
}
return objs;
}
public T[] FindObjects<T>() where T : Object
{
if (includeDisabledObjects) {
List<T> meshfilters = new List<T> ();
GameObject[] allGo = GetAllRootGameObjects();
foreach (GameObject go in allGo) {
Transform[] tgo = go.GetComponentsInChildren<Transform> (true).ToArray ();
foreach (Transform tr in tgo) {
if (tr.GetComponent<T> ())
meshfilters.Add (tr.GetComponent<T> ());
}
}
return (T[])meshfilters.ToArray ();
}
else
return (T[])FindObjectsOfType(typeof(T));
}
public List<GameObject> FindAllGameObjects()
{
List<GameObject> allObjects = new List<GameObject>();
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
if (scene.isLoaded)
{
allObjects.AddRange(scene.GetRootGameObjects());
}
}
List<GameObject> dontDestroyOnLoadObjects = GetDontDestroyOnLoadRoots();
allObjects.AddRange(dontDestroyOnLoadObjects);
if (includeDisabledObjects)
{
List<GameObject> allObjectsWithChildren = new List<GameObject>();
foreach (GameObject go in allObjects)
{
allObjectsWithChildren.AddRange(go.GetComponentsInChildren<Transform>(true)
.Select(t => t.gameObject));
}
return allObjectsWithChildren;
}
else
{
List<GameObject> allActiveObjectsWithChildren = new List<GameObject>();
foreach (GameObject go in allObjects)
{
if (go.activeInHierarchy)
{
allActiveObjectsWithChildren.AddRange(go.GetComponentsInChildren<Transform>(false)
.Where(t => t.gameObject.activeInHierarchy)
.Select(t => t.gameObject));
}
}
return allActiveObjectsWithChildren;
}
}
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e800d55bca04f8c49b06aa0167235ab3
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,208 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace SceneProfiler.Editor
{
public class TextureDetails : IEquatable<TextureDetails>
{
public bool isCubeMap;
public float memSizeKB;
public Texture texture;
public TextureFormat format;
public int mipMapCount;
public List<Object> FoundInMaterials = new List<Object>();
public List<Object> FoundInRenderers = new List<Object>();
public List<Object> FoundInAnimators = new List<Object>();
public List<Object> FoundInScripts = new List<Object>();
public List<Object> FoundInGraphics = new List<Object>();
public List<Object> FoundInButtons = new List<Object>();
public bool isSky;
public bool instance;
public bool isgui;
public TextureDetails() { }
public bool Equals(TextureDetails other)
{
if (other == null || texture == null || other.texture == null)
return false;
return texture.GetNativeTexturePtr() == other.texture.GetNativeTexturePtr();
}
public override int GetHashCode()
{
return (int)texture.GetNativeTexturePtr();
}
public override bool Equals(object obj)
{
return Equals(obj as TextureDetails);
}
}
public class MaterialDetails
{
public Material material;
public List<Renderer> FoundInRenderers = new List<Renderer>();
public List<Graphic> FoundInGraphics = new List<Graphic>();
public bool instance;
public bool isgui;
public bool isSky;
public MaterialDetails()
{
instance = false;
isgui = false;
isSky = false;
}
}
public class MeshDetails
{
public Mesh mesh;
public List<MeshFilter> FoundInMeshFilters = new List<MeshFilter>();
public List<SkinnedMeshRenderer> FoundInSkinnedMeshRenderer = new List<SkinnedMeshRenderer>();
public List<GameObject> StaticBatchingEnabled = new List<GameObject>();
public bool instance;
public MeshDetails()
{
instance = false;
}
}
public class AudioClipDetails
{
public AudioClip clip;
public List<AudioSource> FoundInAudioSources = new List<AudioSource>();
public AudioClipDetails() { }
}
public class Missing
{
public Transform Object;
public string type;
public string name;
}
public class LightDetails
{
public Light light;
public bool isEnabled;
public LightShadows shadowType;
public bool isActive;
}
public class ParticleSystemDetails
{
public ParticleSystem particleSystem;
public List<GameObject> FoundInGameObjects = new List<GameObject>();
public Material material;
public int maxParticles;
public int activeParticles;
}
public class PhysicsObjectDetails
{
public Rigidbody rigidbody;
public GameObject gameObject;
public bool isActive;
public bool isKinematic;
public float mass;
public float drag;
public float angularDrag;
public RigidbodyInterpolation interpolation;
public CollisionDetectionMode collisionDetectionMode;
public string colliderType;
public PhysicsObjectDetails(Rigidbody rb)
{
rigidbody = rb;
gameObject = rb.gameObject;
isActive = rb.gameObject.activeInHierarchy;
isKinematic = rb.isKinematic;
mass = rb.mass;
drag = rb.drag;
angularDrag = rb.angularDrag;
interpolation = rb.interpolation;
collisionDetectionMode = rb.collisionDetectionMode;
colliderType = GetColliderType(rb);
}
private string GetColliderType(Rigidbody rb)
{
Collider collider = rb.GetComponent<Collider>();
if (collider is BoxCollider) return "Box";
if (collider is SphereCollider) return "Sphere";
if (collider is CapsuleCollider) return "Capsule";
if (collider is MeshCollider) return "Mesh";
return "Other";
}
}
public class SceneWarningDetails
{
public string Message { get; private set; }
public MessageType Type { get; private set; }
public SceneWarningDetails(string message, MessageType type)
{
Message = message;
Type = type;
}
}
public class ExpensiveObjectDetails
{
public GameObject gameObject;
public Vector3 scale;
public string scaleType;
public int hierarchyDepth;
public int componentCount;
public ExpensiveObjectDetails(GameObject obj)
{
gameObject = obj;
scale = obj.transform.localScale;
scaleType = IsUniformScale(scale) ? "Uniform" : "NonUniform";
hierarchyDepth = GetHierarchyDepth(obj.transform);
componentCount = obj.GetComponents<Component>().Length;
}
private bool IsUniformScale(Vector3 scale)
{
return Mathf.Approximately(scale.x, scale.y) && Mathf.Approximately(scale.y, scale.z);
}
private int GetHierarchyDepth(Transform transform)
{
int depth = 0;
while (transform.parent != null)
{
depth++;
transform = transform.parent;
}
return depth;
}
public override bool Equals(object obj)
{
if (obj is ExpensiveObjectDetails other)
{
return gameObject == other.gameObject;
}
return false;
}
public override int GetHashCode()
{
return gameObject.GetHashCode();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c2a4c030d2b09dd44ad26d00ce9b3ee6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,18 @@
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License
Copyright (c) 2024 [Tony Green]
You are free to:
- Share — copy and redistribute the material in any medium or format
- Adapt — remix, transform, and build upon the material
Under the following terms:
- Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
- NonCommercial — You may not use the material for commercial purposes.
- ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
Notices:
- You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation.
- No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material.

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ac68082e1ee88424c97689cc054a0105
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,111 @@
# Scene Profiler Tool for Unity
![Scene Profiler Tool](https://github.com/TonyGreen9/Scene-Profiler/raw/main/SceneProfiler.png)
The Scene Profiler Tool is a powerful utility designed to help Unity developers optimize their scenes by providing comprehensive profiling of various scene elements.
Supports Unity 2022.2 or higher
## Table of Contents
- [Overview](#overview)
- [Installation](#installation)
- [Getting Started](#getting-started)
- [Features](#features)
- [Physics Profiler](#physics-profiler)
- [Audio Clips Profiler](#audio-clips-profiler)
- [Particle Systems Profiler](#particle-systems-profiler)
- [Lights Profiler](#lights-profiler)
- [Materials Profiler](#materials-profiler)
- [Meshes Profiler](#meshes-profiler)
- [Textures Profiler](#textures-profiler)
- [Warnings Data Collector](#warnings-data-collector)
- [Missing Assets Profiler](#missing-assets-profiler)
- [Expensive Objects Profiler](#expensive-objects-profiler)
- [Modularity](#modularity)
- [Sorting and Multi-Column Usage](#sorting-and-multi-column-usage)
- [Usage](#usage)
- [Support](#support)
- [License](#license)
## Overview
The Scene Profiler Tool provides detailed insights into the performance of various elements within a Unity scene. It helps developers identify and resolve performance bottlenecks, ensuring a smooth and optimized gaming experience.
## Installation
To install this package, follow the instructions in the [Package Manager documentation](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest/index.html).
## Getting Started
1. After importing the package, navigate to the Scene Profiler Tool window by selecting `Window > Analysis > Scene Profiler` from the Unity menu.
2. In the Scene Profiler Tool window, you can select different profiling options to gather data on various scene elements.
## Features
### Physics Profiler
Collects and displays data related to physics objects in the scene. It monitors performance metrics of physics interactions and helps optimize physical simulations.
### Audio Clips Profiler
Analyzes and profiles audio clips used in the scene. Provides detailed information on audio clip properties and usage statistics.
### Particle Systems Profiler
Gathers data on particle systems, offering insights into their performance and impact on the scene. Helps in optimizing particle effects for better performance.
### Lights Profiler
Collects and presents data on all light sources within the scene. Provides metrics to optimize lighting for improved performance and visual quality.
### Materials Profiler
Profiles materials used in the scene, displaying detailed information on material properties and usage. Aids in optimizing material configurations for better rendering performance.
### Meshes Profiler
Collects data on meshes within the scene. Offers insights into mesh properties and their impact on performance.
### Textures Profiler
Analyzes textures used in the scene, providing detailed information on texture properties and usage. Helps in optimizing texture usage for improved performance.
### Warnings Data Collector
Collects and displays warnings related to various aspects of the scene. Helps in identifying and addressing potential issues that may affect performance.
### Missing Assets Profiler
Identifies and reports missing assets within the scene. Ensures that all necessary assets are present and properly referenced.
### Expensive Objects Profiler
Profiles objects in the scene that are deemed "expensive" due to their scale, hierarchy depth, or component count. Helps in identifying objects that may be causing performance bottlenecks due to their complexity.
## Modularity
The Scene Profiler Tool is modular, allowing you to enable or disable specific profiling modules based on your needs. This flexibility ensures that you can focus on the aspects of your scene that are most critical for optimization. Each module can be toggled on or off from the tool's interface.
## Sorting and Multi-Column Usage
The Scene Profiler Tool supports sorting and multi-column usage to enhance the analysis of profiling data. You can sort data within each profiler module by various criteria, such as name, size, and performance metrics. Additionally, the tool uses multi-column layouts to display detailed information for each profiled object, making it easier to compare and analyze data.
## Usage
1. Open the Scene Profiler Tool window from the Unity menu: `Window > Analysis > Scene Profiler`.
2. Select the profiling category you want to analyze (e.g., Physics, Audio Clips, Particle Systems, etc.).
3. Click the `Collect Data` button to start collecting data.
4. Review the collected data in the tool's interface. Use the insights provided to optimize the respective elements of your scene.
5. To clear the collected data and refresh the interface, click the `Clear` button.
6. To access additional settings for the profiler, click the `Settings` button. Here, you can configure options such as including disabled objects, looking in sprite animations, and more.
7. Click the `Modules` button to toggle the display of different profiling modules.
## Support
If you encounter any issues or have any questions regarding the Scene Profiler Tool, please message me at [iamtonygreen@gmail.com](mailto:iamtonygreen@gmail.com).
## License
The Scene Profiler Tool is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License. For more information, see the LICENSE file included in the package.

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e09e13d4fc58ecb44b52ea48d2909019
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
{
"name": "com.tonygreen.sceneprofiler",
"version": "1.0.0",
"displayName": "Scene Profiler",
"description": "The Scene Profiler Tool operates by collecting data from various aspects of the scene, including physics, audio clips, particle systems, lights, materials, meshes, and textures. It then presents this data in a user-friendly GUI, allowing developers to easily identify performance bottlenecks and take appropriate actions to optimize their scenes.",
"unity": "2022.3"
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8e713626b9baaf04fb87ef0e8dad7d0c
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: