Skip to content

feat: add scene content stats to the Current Scene debug widget#9457

Draft
dalkia wants to merge 2 commits into
devfrom
feat/current-scene-content-stats-debug
Draft

feat: add scene content stats to the Current Scene debug widget#9457
dalkia wants to merge 2 commits into
devfrom
feat/current-scene-content-stats-debug

Conversation

@dalkia

@dalkia dalkia commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Pull Request Description

What does this PR change?

Adds per-scene content statistics to the "Current scene" debug widget so creators and devs can see, at a glance, how close the scene they are standing in is to its limits. Nine new rows appear at the top of the widget, each formatted current / maxcap (pct%) and colored green (< 80%), yellow (80–99%) or red (≥ 100%):

  • Entities — live CRDT entities (EntitiesMap.Count)
  • Triangles — summed from primitive mesh renderers + GLTF container renderers
  • Meshes (bodies) — renderer count (primitive + GLTF)
  • Geometries — unique Mesh instances
  • Materials / Textures — unique instances, deduped across SDK materials and GLTF-embedded materials (textures probed from common shader properties)
  • Colliders — primitive colliders + GLTF invisible/decoded-visible colliders
  • Content size — runtime memory of the scene's unique meshes + textures (Profiler.GetRuntimeMemorySizeLong); there is no per-scene downloaded-bytes accumulator, so deployed size is not knowable at runtime
  • External content — media streams not served from the content server + NFT shapes

Caps are hardcoded from the documented Decentraland scene limitations, scaled by parcel count n: triangles n×10000, entities n×200, bodies n×300, materials log2(n+1)×20, textures log2(n+1)×10, geometries log2(n+1)×200, content size 15MB×n. Colliders (n×300) and external content (10) have no documented limit, so they use project-chosen constants. All caps live in one constants block in DebugViewCurrentSceneSystem.Formatting.cs.

Architecture: a new scene-world system (SceneContentStatsSystem, SyncedPresentationSystemGroup) counts every 30 frames and writes into a new SceneContentStats payload on SceneRuntimeMetrics (now exposed to scene-world systems via ECSWorldInstanceSharedDependencies). The global DebugViewCurrentSceneSystem sets a CollectionRequested demand flag only while the widget is expanded on the current scene — with the debug panel closed or disabled, the scene system does a single bool check per frame and nothing else. Counting is allocation-free (reused HashSets / scratch list, non-alloc GetSharedMaterials).

Test Instructions

Steps (standard run):

metaforge explorer run 9457

Expected result:
The "Current scene" debug widget shows the nine new stat rows with colored current / max (pct%) values for the scene you are standing in.

Steps (fresh account):

metaforge account create --clear
metaforge explorer run 9457

Expected result:
Same as above after finishing onboarding.

Automation (if applicable):
N/A

Prerequisites

  • Run with the debug panel available (editor play mode or a build with --debug)

Test Steps

  1. Enter any world/scene and open the debug panel
  2. Expand the "Current scene" widget
  3. Rows show "—" for up to ~1 second, then populate with current / max (pct%) values colored green/yellow/red
  4. Walk into a neighboring scene — values reset and repopulate for the new scene, and caps change with the scene's parcel count
  5. Collapse the widget or close the panel — values freeze (collection stops); reopen and they refresh within a second
  6. Visit a heavy scene (e.g. Genesis Plaza) and verify triangle/material counts move into yellow/red

Additional Testing Notes

  • "Content size" measures runtime memory of unique meshes + textures, not the deployed bundle size — the 15MB/parcel cap is indicative
  • GLTF stats only count containers in Finished state, so values grow while a scene streams in
  • Empty/loading scenes show "—" until the first collection pass
  • No SDK behavior changes — this is debug-panel-only

Quality Checklist

  • Changes have been tested locally
  • Documentation has been updated (if required)
  • Performance impact has been considered
  • For SDK features: Test scene is included

Code Review Reference

Please review our Branch & PR Standards before submitting. It explains the automated review flow, QA/DEV approval requirements, and what each label does — especially useful for first-time contributors.

🤖 Generated with Claude Code

Adds per-scene content statistics (entities, triangles, meshes/bodies,
geometries, materials, textures, colliders, runtime content size and
external content) to the "Current scene" debug widget, shown as
current / maxcap (pct%) colored green/yellow/red against hardcoded
caps derived from the scene's parcel count.

Counting runs in a new scene-world system (SceneContentStatsSystem)
gated by a demand flag the widget sets only while expanded, so it
costs a single bool check per frame when the debug panel is closed
or disabled.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

badge

Build failed! Check the logs to see what went wrong.
If the error repeats please consider the clean-build tag.

@dalkia dalkia self-assigned this Jul 21, 2026
@dalkia dalkia added the force-build Used to trigger a build on draft PR label Jul 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Warnings count reduced: 14593 => 14591

Warnings/errors in files changed by this PR (68)
Assets/DCL/Infrastructure/Global/StaticContainer.cs:89  CSharpWarnings::CS8618  Non-nullable field 'assetsProvisioner' is uninitialized. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/Infrastructure/SceneRunner/SceneInstanceDeps.cs:85  CSharpWarnings::CS8618  Non-nullable field 'permissionsProvider' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:136  CSharpWarnings::CS8618  Non-nullable property 'AssetPreLoadCache' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:119  CSharpWarnings::CS8618  Non-nullable property 'CacheCleaner' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:95  CSharpWarnings::CS8618  Non-nullable property 'CharacterContainer' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:137  CSharpWarnings::CS8618  Non-nullable property 'CharacterDataPropagationUtility' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:128  CSharpWarnings::CS8618  Non-nullable property 'DebugContainerBuilder' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:102  CSharpWarnings::CS8618  Non-nullable property 'ECSWorldPlugins' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:103  CSharpWarnings::CS8618  Non-nullable property 'EmoteStorage' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:97  CSharpWarnings::CS8618  Non-nullable property 'EmotesContainer' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:115  CSharpWarnings::CS8618  Non-nullable property 'EntityCollidersGlobalCache' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:120  CSharpWarnings::CS8618  Non-nullable property 'EthereumApi' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:100  CSharpWarnings::CS8618  Non-nullable property 'ExposedGlobalDataContainer' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:124  CSharpWarnings::CS8618  Non-nullable property 'FeatureFlagsProvider' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:130  CSharpWarnings::CS8618  Non-nullable property 'GPUInstancingService' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:135  CSharpWarnings::CS8618  Non-nullable property 'GltfContainerAssetsCache' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:138  CSharpWarnings::CS8618  Non-nullable property 'ISSDescriptorDiskCache' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:127  CSharpWarnings::CS8618  Non-nullable property 'ImageControllerProvider' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:121  CSharpWarnings::CS8618  Non-nullable property 'InputBlock' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:132  CSharpWarnings::CS8618  Non-nullable property 'LaunchMode' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:131  CSharpWarnings::CS8618  Non-nullable property 'LoadingStatus' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:96  CSharpWarnings::CS8618  Non-nullable property 'MediaContainer' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:105  CSharpWarnings::CS8618  Non-nullable property 'MemoryCap' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:125  CSharpWarnings::CS8618  Non-nullable property 'PortableExperiencesController' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:114  CSharpWarnings::CS8618  Non-nullable property 'Profiler' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:98  CSharpWarnings::CS8618  Non-nullable property 'ProfilesContainer' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:92  CSharpWarnings::CS8618  Non-nullable property 'PublishIpfsEntityCommand' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:99  CSharpWarnings::CS8618  Non-nullable property 'QualityContainer' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:91  CSharpWarnings::CS8618  Non-nullable property 'RealmData' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:107  CSharpWarnings::CS8618  Non-nullable property 'SceneLoadingLimit' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:123  CSharpWarnings::CS8618  Non-nullable property 'SceneReadinessReportQueue' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:129  CSharpWarnings::CS8618  Non-nullable property 'SceneRestrictionBusController' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:122  CSharpWarnings::CS8618  Non-nullable property 'ScenesCache' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:112  CSharpWarnings::CS8618  Non-nullable property 'SharedPlugins' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:126  CSharpWarnings::CS8618  Non-nullable property 'SmartWearableCache' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:118  CSharpWarnings::CS8618  Non-nullable property 'StaticSettings' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:101  CSharpWarnings::CS8618  Non-nullable property 'WebRequestsContainer' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:133  CSharpWarnings::CS8618  Non-nullable property 'WorldManifestProvider' is uninitialized. Consider adding the 'required' modifier or declaring the property as nullable.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:276  ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract  Expression is always true according to nullable reference types' annotations
Assets/DCL/Infrastructure/SceneRunner/SceneInstanceDeps.cs:194  InconsistentNaming  Name 'CommunicationsControllerAPI' does not match rule 'members_should_be_pascal_case'. Suggested name is 'CommunicationsControllerApi'.
Assets/DCL/Infrastructure/SceneRunner/SceneInstanceDeps.cs:199  InconsistentNaming  Name 'EngineAPI' does not match rule 'members_should_be_pascal_case'. Suggested name is 'EngineApi'.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:130  InconsistentNaming  Name 'GPUInstancingService' does not match rule 'members_should_be_pascal_case'. Suggested name is 'GpuInstancingService'.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:138  InconsistentNaming  Name 'ISSDescriptorDiskCache' does not match rule 'members_should_be_pascal_case'. Suggested name is 'IssDescriptorDiskCache'.
Assets/DCL/Infrastructure/SceneRunner/SceneInstanceDeps.cs:190  InconsistentNaming  Name 'RestrictedActionsAPI' does not match rule 'members_should_be_pascal_case'. Suggested name is 'RestrictedActionsApi'.
Assets/DCL/Infrastructure/SceneRunner/SceneInstanceDeps.cs:268  InconsistentNaming  Name 'WithRuntimeAndJsAPI' does not match rule 'members_should_be_pascal_case'. Suggested name is 'WithRuntimeAndJsApi'.
Assets/DCL/Infrastructure/SceneRunner/SceneInstanceDeps.cs:188  InconsistentNaming  Name 'WithRuntimeAndJsAPIBase' does not match rule 'members_should_be_pascal_case'. Suggested name is 'WithRuntimeAndJsApiBase'.
Assets/DCL/Infrastructure/SceneRunner/SceneInstanceDeps.cs:296  InconsistentNaming  Name 'WithRuntimeJsAndSDKObservablesEngineAPI' does not match rule 'members_should_be_pascal_case'. Suggested name is 'WithRuntimeJsAndSdkObservablesEngineApi'.
Assets/DCL/Infrastructure/SceneRunner/SceneInstanceDeps.cs:211  InconsistentNaming  Name 'communicationsControllerAPI' does not match rule 'parameters_should_be_camel_case'. Suggested name is 'communicationsControllerApi'.
Assets/DCL/Infrastructure/Global/StaticContainer.cs:176  InconsistentNaming  Name 'enableGPUInstancing' does not match rule 'parameters_should_be_camel_case'. Suggested name is 'enableGpuInstancing'.
Assets/DCL/Infrastructure/SceneRunner/SceneInstanceDeps.cs:205  InconsistentNaming  Name 'engineAPI' does not match rule 'parameters_should_be_camel_case'. Suggested name is 'engineApi'.

…and 18 more (see the csharp-lint-reports artifact).

@github-actions

Copy link
Copy Markdown
Contributor

Tests: 23922 passed, 0 failed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

force-build Used to trigger a build on draft PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant