@aqian0/dsh-unity 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +53 -0
- package/LICENSE-UNITY-COMPANION.md +122 -0
- package/LICENSE.md +31 -0
- package/NOTICE.md +90 -0
- package/README.md +273 -2
- package/cordis.patch.yml +22 -0
- package/docs/design.md +297 -0
- package/icon.svg +16 -0
- package/lib/frontmatter.js +392 -0
- package/lib/gating.js +105 -0
- package/lib/harness.js +16 -0
- package/lib/index.js +171 -0
- package/lib/project.js +210 -0
- package/lib/registry.js +268 -0
- package/lib/requirements.js +214 -0
- package/lib/skills.js +191 -0
- package/lib/types/frontmatter.d.ts +84 -0
- package/lib/types/gating.d.ts +80 -0
- package/lib/types/harness.d.ts +152 -0
- package/lib/types/index.d.ts +75 -0
- package/lib/types/project.d.ts +93 -0
- package/lib/types/registry.d.ts +96 -0
- package/lib/types/requirements.d.ts +67 -0
- package/lib/types/skills.d.ts +54 -0
- package/lib/types/watch.d.ts +34 -0
- package/lib/watch.js +84 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +70 -4
- package/skills/2d-pixel-perfect/SKILL.md +208 -0
- package/skills/2d-pixel-perfect/references/api-reference.md +81 -0
- package/skills/2d-pixel-perfect/references/camera-setup-builtin.cs +40 -0
- package/skills/2d-pixel-perfect/references/camera-setup-urp.cs +49 -0
- package/skills/2d-pixel-perfect/references/pipeline-detection.cs +50 -0
- package/skills/2d-pixel-perfect/references/sprite-settings.cs +37 -0
- package/skills/asset-transformer-toolkit/SECURITY.md +15 -0
- package/skills/asset-transformer-toolkit/SKILL.md +39 -0
- package/skills/asset-transformer-toolkit/references/create-importer.md +121 -0
- package/skills/asset-transformer-toolkit/references/lods.md +61 -0
- package/skills/asset-transformer-toolkit/references/rule-api.md +154 -0
- package/skills/asset-transformer-toolkit/references/ruleblock-api.md +37 -0
- package/skills/asset-transformer-toolkit/references/ruleset-api.md +138 -0
- package/skills/asset-transformer-toolkit/references/rulesets-and-actions.md +227 -0
- package/skills/audio-setup-mixers/SECURITY.md +16 -0
- package/skills/audio-setup-mixers/SKILL.md +127 -0
- package/skills/audio-setup-mixers/references/api.md +162 -0
- package/skills/build-gtk/SECURITY.md +16 -0
- package/skills/build-gtk/SKILL.md +200 -0
- package/skills/build-gtk/references/api-reference.md +33 -0
- package/skills/build-gtk/references/graph-api-gaps.md +96 -0
- package/skills/build-gtk/references/runtime-and-visualization.md +191 -0
- package/skills/build-gtk/references/state-machine-api.md +270 -0
- package/skills/build-gtk/references/where-the-docs-stop.md +49 -0
- package/skills/build-live-game/SKILL.md +159 -0
- package/skills/build-live-game/references/achievements.md +757 -0
- package/skills/build-live-game/references/apis.md +271 -0
- package/skills/build-live-game/references/authentication.md +431 -0
- package/skills/build-live-game/references/battlepass.md +904 -0
- package/skills/build-live-game/references/blueprints-and-samples.md +75 -0
- package/skills/build-live-game/references/cloud-code-cloudbehaviours.md +1111 -0
- package/skills/build-live-game/references/cloud-code-modules.md +1276 -0
- package/skills/build-live-game/references/cloud-code.md +58 -0
- package/skills/build-live-game/references/cloud-save.md +464 -0
- package/skills/build-live-game/references/deployment.md +231 -0
- package/skills/build-live-game/references/orientation.md +30 -0
- package/skills/build-live-game/references/player-account.md +821 -0
- package/skills/build-live-game/references/remote-config.md +96 -0
- package/skills/build-live-game/references/services-overview.md +76 -0
- package/skills/build-live-game/references/tooling.md +375 -0
- package/skills/build-live-game/references/ugs-cli.md +86 -0
- package/skills/craft-game-floors/SECURITY.md +23 -0
- package/skills/craft-game-floors/SKILL.md +134 -0
- package/skills/craft-game-floors/references/art-direction.md +85 -0
- package/skills/craft-game-floors/references/camera-rigs.md +51 -0
- package/skills/craft-game-floors/references/character-motion.md +35 -0
- package/skills/craft-game-floors/references/game-audio.md +47 -0
- package/skills/craft-game-floors/references/game-feel.md +68 -0
- package/skills/craft-game-floors/references/game-shell.md +45 -0
- package/skills/craft-game-floors/references/live-floor.md +35 -0
- package/skills/craft-game-floors/references/placeholder-assets.md +35 -0
- package/skills/craft-game-floors/references/scene-lighting.md +52 -0
- package/skills/craft-game-floors/references/toon-shading.md +34 -0
- package/skills/craft-game-floors/references/vfx.md +40 -0
- package/skills/craft-game-floors/references/visual-scorecard.md +43 -0
- package/skills/create-2d-physics/SECURITY.md +16 -0
- package/skills/create-2d-physics/SKILL.md +128 -0
- package/skills/create-2d-physics/references/2d-physics-core.md +155 -0
- package/skills/create-2d-physics/references/legacy-2d-physics.md +45 -0
- package/skills/create-tile-palette-or-rule-tiles/SKILL.md +95 -0
- package/skills/create-tile-palette-or-rule-tiles/references/hexagonalruletile.md +71 -0
- package/skills/create-tile-palette-or-rule-tiles/references/palette-create.md +38 -0
- package/skills/create-tile-palette-or-rule-tiles/references/ruletile-createempty.md +37 -0
- package/skills/create-tile-palette-or-rule-tiles/references/ruletile-createfromsegment.md +219 -0
- package/skills/create-tile-palette-or-rule-tiles/references/ruletile.md +95 -0
- package/skills/create-tile-palette-or-rule-tiles/scripts/CreatePaletteTemplate.cs +148 -0
- package/skills/create-tile-palette-or-rule-tiles/scripts/ManualWorkflowExample.cs +63 -0
- package/skills/create-tile-palette-or-rule-tiles/scripts/RuleTileGenerator.cs +61 -0
- package/skills/create-tile-palette-or-rule-tiles/scripts/TilemapRuleTileCreateFromSegment.cs +225 -0
- package/skills/fix-3d-physics-collisions/SECURITY.md +17 -0
- package/skills/fix-3d-physics-collisions/SKILL.md +139 -0
- package/skills/fix-3d-physics-collisions/references/collision-checklist.md +80 -0
- package/skills/fix-3d-physics-collisions/references/collision-debugger.md +18 -0
- package/skills/fix-3d-physics-collisions/references/console-errors-table.md +9 -0
- package/skills/fix-3d-physics-collisions/references/kinematic-trigger-facts.md +18 -0
- package/skills/fix-3d-physics-collisions/references/other-symptoms.md +29 -0
- package/skills/fix-3d-physics-collisions/references/raycast-checklist.md +8 -0
- package/skills/fix-3d-physics-collisions/references/topic-map.md +42 -0
- package/skills/fix-3d-physics-collisions/references/trigger-checklist.md +9 -0
- package/skills/fix-3d-physics-collisions/scripts/CollisionDebugger.cs +561 -0
- package/skills/generate-editor-search-query/SECURITY.md +17 -0
- package/skills/generate-editor-search-query/SKILL.md +117 -0
- package/skills/generate-editor-search-query/references/open-search-window.md +70 -0
- package/skills/generate-editor-search-query/references/query-patterns.md +124 -0
- package/skills/implement-in-app-purchases/SKILL.md +82 -0
- package/skills/implement-in-app-purchases/references/api-details.md +41 -0
- package/skills/implement-in-app-purchases/references/api-notes.md +105 -0
- package/skills/implement-in-app-purchases/references/codeless-catalog.md +197 -0
- package/skills/implement-in-app-purchases/references/convert-adapty.md +270 -0
- package/skills/implement-in-app-purchases/references/convert-essentialkit.md +239 -0
- package/skills/implement-in-app-purchases/references/convert-revenuecat.md +277 -0
- package/skills/implement-in-app-purchases/references/convert-unipay.md +145 -0
- package/skills/implement-in-app-purchases/references/migration-v4-to-v5.md +46 -0
- package/skills/implement-in-app-purchases/references/path-add-iap-to-new-project.md +197 -0
- package/skills/implement-in-app-purchases/references/path-convert-native-google-billing.md +302 -0
- package/skills/implement-in-app-purchases/references/path-convert-native-storekit.md +357 -0
- package/skills/implement-in-app-purchases/references/path-implement-iap-d2c.md +253 -0
- package/skills/implement-in-app-purchases/references/platform-notes.md +55 -0
- package/skills/implement-in-app-purchases/references/pre-check.md +207 -0
- package/skills/implement-in-app-purchases/references/topic-map.md +46 -0
- package/skills/initialize-ai-navigation/SKILL.md +109 -0
- package/skills/initialize-ai-navigation/references/navigation-system.md +793 -0
- package/skills/initialize-ai-navigation/references/topic-map.md +66 -0
- package/skills/levelplay-unity-integration/SKILL.md +122 -0
- package/skills/levelplay-unity-integration/references/adding-more-ad-formats.md +15 -0
- package/skills/levelplay-unity-integration/references/banner-api.md +927 -0
- package/skills/levelplay-unity-integration/references/best-practices.md +604 -0
- package/skills/levelplay-unity-integration/references/dependency-resolution.md +94 -0
- package/skills/levelplay-unity-integration/references/examples.md +10 -0
- package/skills/levelplay-unity-integration/references/ilrd-api.md +337 -0
- package/skills/levelplay-unity-integration/references/initialization-api.md +851 -0
- package/skills/levelplay-unity-integration/references/interstitial-api.md +907 -0
- package/skills/levelplay-unity-integration/references/ios-setup.md +463 -0
- package/skills/levelplay-unity-integration/references/migration-sdk-9.md +666 -0
- package/skills/levelplay-unity-integration/references/privacy-settings.md +593 -0
- package/skills/levelplay-unity-integration/references/production-release-checklist.md +22 -0
- package/skills/levelplay-unity-integration/references/rewarded-api.md +918 -0
- package/skills/levelplay-unity-integration/references/step-0-new-or-migration.md +8 -0
- package/skills/levelplay-unity-integration/references/step-1-verify-environment.md +4 -0
- package/skills/levelplay-unity-integration/references/step-10-testing.md +15 -0
- package/skills/levelplay-unity-integration/references/step-2-business-goals.md +12 -0
- package/skills/levelplay-unity-integration/references/step-3-install-sdk.md +55 -0
- package/skills/levelplay-unity-integration/references/step-4-native-dependencies.md +22 -0
- package/skills/levelplay-unity-integration/references/step-5-app-key-and-ad-units.md +18 -0
- package/skills/levelplay-unity-integration/references/step-6-5-privacy-and-regulation.md +51 -0
- package/skills/levelplay-unity-integration/references/step-6-admob-keys.md +16 -0
- package/skills/levelplay-unity-integration/references/step-7-initialize.md +50 -0
- package/skills/levelplay-unity-integration/references/step-8-ad-unit-strategy.md +16 -0
- package/skills/levelplay-unity-integration/references/step-9-implement-ad-units.md +66 -0
- package/skills/levelplay-unity-integration/references/testing-and-validation.md +222 -0
- package/skills/levelplay-unity-integration/references/troubleshooting.md +99 -0
- package/skills/localize-unity-project/SKILL.md +159 -0
- package/skills/localize-unity-project/references/api-notes.md +15 -0
- package/skills/localize-unity-project/references/cjk-fonts.md +83 -0
- package/skills/localize-unity-project/references/docs-map.md +42 -0
- package/skills/localize-unity-project/references/documentation-lookup.md +33 -0
- package/skills/localize-unity-project/references/locale-switching.md +17 -0
- package/skills/localize-unity-project/references/table-completeness-check.md +47 -0
- package/skills/localize-unity-project/references/translating-existing-project.md +47 -0
- package/skills/localize-unity-project/references/translation-strategy.md +41 -0
- package/skills/localize-unity-project/references/troubleshooting.md +12 -0
- package/skills/localize-unity-project/scripts/L10nBatchProcessor.cs +191 -0
- package/skills/localize-unity-project/scripts/LocalizedFontAsset.cs +18 -0
- package/skills/manage-sprite-atlas/SKILL.md +202 -0
- package/skills/manage-sprite-atlas/references/addressables-delivery.md +58 -0
- package/skills/manage-sprite-atlas/references/advanced-manual-authoring.md +19 -0
- package/skills/manage-sprite-atlas/references/api.md +382 -0
- package/skills/manage-sprite-atlas/references/best-practices.md +183 -0
- package/skills/manage-sprite-atlas/references/common-errors.md +123 -0
- package/skills/manage-sprite-atlas/references/complete-workflow.md +61 -0
- package/skills/manage-sprite-atlas/references/custom-packing.md +147 -0
- package/skills/manage-sprite-atlas/references/delivery-mechanism.md +30 -0
- package/skills/manage-sprite-atlas/references/key-requirements.md +21 -0
- package/skills/manage-sprite-atlas/references/manual-authoring.md +39 -0
- package/skills/manage-sprite-atlas/references/namespaces.md +15 -0
- package/skills/manage-sprite-atlas/references/v2-architecture.md +21 -0
- package/skills/manage-sprite-atlas/resources/authoringvsruntime.cs +176 -0
- package/skills/manage-sprite-atlas/resources/buildaddressablespostprocess.cs +59 -0
- package/skills/manage-sprite-atlas/resources/cacheloadedatlases.cs +145 -0
- package/skills/manage-sprite-atlas/resources/cleanupbatchoperations.cs +119 -0
- package/skills/manage-sprite-atlas/resources/createandconfiguremasteratlas.cs +57 -0
- package/skills/manage-sprite-atlas/resources/custompackersetup.cs +88 -0
- package/skills/manage-sprite-atlas/resources/deprecatedmethods.cs +142 -0
- package/skills/manage-sprite-atlas/resources/dontmodifywithoutsaving.cs +120 -0
- package/skills/manage-sprite-atlas/resources/dontpackinruntimebuilds.cs +190 -0
- package/skills/manage-sprite-atlas/resources/dontscriptspriteatlasineditor.cs +114 -0
- package/skills/manage-sprite-atlas/resources/editorconfiguration.cs +95 -0
- package/skills/manage-sprite-atlas/resources/enablespritepacking.cs +172 -0
- package/skills/manage-sprite-atlas/resources/gridspritepacker.cs +50 -0
- package/skills/manage-sprite-atlas/resources/handlelatebinding.cs +147 -0
- package/skills/manage-sprite-atlas/resources/handlenullcases.cs +141 -0
- package/skills/manage-sprite-atlas/resources/migratev1tov2.cs +335 -0
- package/skills/manage-sprite-atlas/resources/multipagepacker.cs +80 -0
- package/skills/manage-sprite-atlas/resources/optimizetexturesettings.cs +191 -0
- package/skills/manage-sprite-atlas/resources/packerdebugging.cs +158 -0
- package/skills/manage-sprite-atlas/resources/packtransform.cs +51 -0
- package/skills/manage-sprite-atlas/resources/platformnames.cs +127 -0
- package/skills/manage-sprite-atlas/resources/queryspritesefficiently.cs +222 -0
- package/skills/manage-sprite-atlas/resources/registercallbacks.cs +152 -0
- package/skills/manage-sprite-atlas/resources/runtimeatlasloader.cs +15 -0
- package/skills/manage-sprite-atlas/resources/runtimespriteaccess.cs +19 -0
- package/skills/manage-sprite-atlas/resources/savespriteatlasasset.cs +107 -0
- package/skills/manage-sprite-atlas/resources/scriptablepacker.cs +81 -0
- package/skills/manage-sprite-atlas/resources/setincludeinbuild.cs +164 -0
- package/skills/manage-sprite-atlas/resources/sizeoptimizedpacker.cs +88 -0
- package/skills/manage-sprite-atlas/resources/spriteatlaslatebinding.cs +123 -0
- package/skills/manage-sprite-atlas/resources/spriteatlasprebuildgenerator.cs +219 -0
- package/skills/manage-sprite-atlas/resources/spritedata.cs +35 -0
- package/skills/manage-sprite-atlas/resources/spritepack.cs +39 -0
- package/skills/manage-sprite-atlas/resources/texturedata.cs +15 -0
- package/skills/manage-sprite-atlas/resources/updatebuildscripts.cs +357 -0
- package/skills/manage-sprite-atlas/resources/updatesettingsconfiguration.cs +135 -0
- package/skills/manage-sprite-atlas/resources/usevariantswisely.cs +179 -0
- package/skills/manage-sprite-atlas/resources/variantatlas.cs +39 -0
- package/skills/migrate-birp-to-urp/SECURITY.md +16 -0
- package/skills/migrate-birp-to-urp/SKILL.md +167 -0
- package/skills/migrate-birp-to-urp/references/capturing-the-editor.md +66 -0
- package/skills/migrate-birp-to-urp/references/complex-shader-situations.md +272 -0
- package/skills/migrate-birp-to-urp/references/conversion-and-rendering-triage.md +113 -0
- package/skills/migrate-birp-to-urp/references/custom-shader-triage.md +123 -0
- package/skills/migrate-birp-to-urp/references/implementation-patterns.md +529 -0
- package/skills/migrate-birp-to-urp/references/migration-workflow.md +265 -0
- package/skills/migrate-birp-to-urp/references/parity-validation-and-troubleshooting.md +114 -0
- package/skills/migrate-birp-to-urp/references/preflight-and-urp-setup.md +195 -0
- package/skills/migrate-birp-to-urp/references/quality-settings-map.md +69 -0
- package/skills/new-unity-project/SECURITY.md +26 -0
- package/skills/new-unity-project/SKILL.md +171 -0
- package/skills/new-unity-project/references/checklist.md +18 -0
- package/skills/new-unity-project/references/common-mistakes.md +15 -0
- package/skills/new-unity-project/references/skill-setup.md +66 -0
- package/skills/new-unity-project/references/step-1-concept.md +13 -0
- package/skills/new-unity-project/references/step-2-platforms-and-create.md +31 -0
- package/skills/new-unity-project/references/step-3-join-and-reconcile.md +16 -0
- package/skills/new-unity-project/references/step-4-source-control.md +9 -0
- package/skills/new-unity-project/references/step-5-packages.md +18 -0
- package/skills/new-unity-project/references/step-6-identity-and-floors.md +20 -0
- package/skills/new-unity-project/references/step-7-visual-baseline.md +75 -0
- package/skills/new-unity-project/references/step-8-first-commit.md +21 -0
- package/skills/new-unity-project/references/step-9-handoff.md +23 -0
- package/skills/optimize-audio/SECURITY.md +16 -0
- package/skills/optimize-audio/SKILL.md +120 -0
- package/skills/optimize-audio/references/diagnostics.md +42 -0
- package/skills/optimize-audio/references/troubleshooting.md +41 -0
- package/skills/optimize-audio/resources/audio-import-api.md +149 -0
- package/skills/optimize-audio/resources/platform-settings.md +48 -0
- package/skills/optimize-text-mesh-pro/SKILL.md +181 -0
- package/skills/optimize-text-mesh-pro/references/dynamic-atlas-and-profiling.md +28 -0
- package/skills/optimize-text-mesh-pro/references/topic-map.md +36 -0
- package/skills/optimize-web/SECURITY.md +16 -0
- package/skills/optimize-web/SKILL.md +157 -0
- package/skills/optimize-web/references/editor-csharp.md +120 -0
- package/skills/optimize-web/references/topic-map.md +49 -0
- package/skills/optimize-web/references/troubleshooting.md +45 -0
- package/skills/optimize-web/references/understand-request.md +19 -0
- package/skills/optimize-web/references/web-assets-quality.md +59 -0
- package/skills/optimize-web/references/web-player-settings.md +39 -0
- package/skills/optimize-web/references/web-profiling-memory.md +71 -0
- package/skills/optimize-web/scripts/WebOptimizer.cs +46 -0
- package/skills/optimize-web/scripts/toktx-examples.sh +11 -0
- package/skills/setup-multiplayer-services/SKILL.md +36 -0
- package/skills/setup-multiplayer-services/references/dgs-entrypoint.md +79 -0
- package/skills/setup-multiplayer-services/references/entrypoints.md +213 -0
- package/skills/setup-multiplayer-services/references/examples.md +33 -0
- package/skills/setup-multiplayer-services/references/implementation-fit.md +30 -0
- package/skills/setup-multiplayer-services/references/underlying-services.md +11 -0
- package/skills/setup-multiplayer-services/references/workflows-prerequisites.md +17 -0
- package/skills/setup-vivox-voice-chat/SECURITY.md +16 -0
- package/skills/setup-vivox-voice-chat/SKILL.md +166 -0
- package/skills/setup-vivox-voice-chat/references/api-reference-lookup.md +28 -0
- package/skills/setup-vivox-voice-chat/references/docs-topic-map.md +13 -0
- package/skills/setup-vivox-voice-chat/references/events-and-participants.md +79 -0
- package/skills/setup-vivox-voice-chat/references/init-and-login.md +92 -0
- package/skills/setup-vivox-voice-chat/references/text-chat.md +93 -0
- package/skills/setup-vivox-voice-chat/references/troubleshooting.md +47 -0
- package/skills/setup-vivox-voice-chat/references/voice-channels.md +92 -0
- package/skills/shader-graph-create-custom-node/SKILL.md +25 -0
- package/skills/shader-graph-create-custom-node/resources/all_hints.hlsl +182 -0
- package/skills/sprite-editor/SECURITY.md +16 -0
- package/skills/sprite-editor/SKILL.md +66 -0
- package/skills/sprite-editor/references/api_reference.md +151 -0
- package/skills/sprite-editor/references/background.md +112 -0
- package/skills/sprite-editor/references/templates.md +72 -0
- package/skills/sprite-editor/scripts/AutomaticSliceTexture.cs +40 -0
- package/skills/sprite-editor/scripts/GenerateNewSpriteRects.cs +200 -0
- package/skills/sprite-editor/scripts/GetTextureSourceImageSize.cs +32 -0
- package/skills/sprite-editor/scripts/GetTextureToSlice.cs +55 -0
- package/skills/sprite-editor/scripts/GridSliceTexture.cs +40 -0
- package/skills/sprite-editor/scripts/IsometricSliceTexture.cs +141 -0
- package/skills/sprite-editor/scripts/README.md +134 -0
- package/skills/sprite-editor/scripts/SetPivotExample.cs +58 -0
- package/skills/sprite-editor/scripts/SpriteToPng.cs +88 -0
- package/skills/sprite-segment-3x3grid/SKILL.md +177 -0
- package/skills/sprite-segment-3x3grid/references/topic-map.md +37 -0
- package/skills/sprite-segment-3x3grid/scripts/SpriteGridAnalysis.cs +119 -0
- package/skills/ui/SKILL.md +142 -0
- package/skills/ui-imgui/SKILL.md +180 -0
- package/skills/ui-imgui/references/gui-elements.md +156 -0
- package/skills/ui-imgui/references/templates.md +141 -0
- package/skills/ui-ugui/SKILL.md +217 -0
- package/skills/ui-ugui/references/layout-and-anchors.md +61 -0
- package/skills/ui-ugui/references/scrollview-setup.md +29 -0
- package/skills/ui-uitk/SKILL.md +229 -0
- package/skills/ui-uitk/references/common-issues.md +74 -0
- package/skills/ui-uitk/references/custom-elements.md +241 -0
- package/skills/ui-uitk/references/painter2d.md +282 -0
- package/skills/ui-uitk/references/pointermanipulator-guide.md +94 -0
- package/skills/ui-uitk/references/svg-icons.md +136 -0
- package/skills/ui-uitk/references/ui-runtime-binding.md +234 -0
- package/skills/ui-uitk/references/uss-guide.md +138 -0
- package/skills/unity-cli/CHANGELOG.md +524 -0
- package/skills/unity-cli/SECURITY.md +68 -0
- package/skills/unity-cli/SKILL.md +160 -0
- package/skills/unity-cli/references/auth-license-cloud.md +318 -0
- package/skills/unity-cli/references/bootstrap-project.md +177 -0
- package/skills/unity-cli/references/build-run-test.md +555 -0
- package/skills/unity-cli/references/catalog-plugins.md +86 -0
- package/skills/unity-cli/references/ci-recipes.md +76 -0
- package/skills/unity-cli/references/cloud-automation.md +819 -0
- package/skills/unity-cli/references/cloud-workflows.md +19 -0
- package/skills/unity-cli/references/collaboration.md +533 -0
- package/skills/unity-cli/references/config-hub.md +239 -0
- package/skills/unity-cli/references/diagnostics-maintenance.md +718 -0
- package/skills/unity-cli/references/docs-workflow.md +179 -0
- package/skills/unity-cli/references/editor-targeting.md +29 -0
- package/skills/unity-cli/references/editors-install.md +490 -0
- package/skills/unity-cli/references/environment-variables.md +42 -0
- package/skills/unity-cli/references/exit-codes.md +47 -0
- package/skills/unity-cli/references/global-flags.md +32 -0
- package/skills/unity-cli/references/integration-advanced.md +1130 -0
- package/skills/unity-cli/references/notes.md +20 -0
- package/skills/unity-cli/references/notifications.md +39 -0
- package/skills/unity-cli/references/playmode-verification-loop.md +279 -0
- package/skills/unity-cli/references/projects-templates.md +997 -0
- package/skills/unity-cli/references/scene-editing-preflight.md +25 -0
- package/skills/unity-cli/references/setup-and-help.md +54 -0
- package/skills/unity-cli/references/version-control.md +612 -0
- package/skills/unity-package-management/SKILL.md +169 -0
- package/skills/unity-package-management/references/discovering-packages.md +66 -0
- package/skills/unity-package-management/references/headless-run.md +31 -0
- package/skills/unity-package-management/references/installer-script.md +92 -0
- package/skills/unity-package-management/references/select-packages.md +126 -0
- package/skills/unity-pipeline/SECURITY.md +17 -0
- package/skills/unity-pipeline/SKILL.md +205 -0
- package/skills/unity-pipeline/references/csharp-eval.md +23 -0
- package/skills/unity-pipeline/references/multiplayer-play-mode.md +103 -0
- package/skills/urp-postprocessing/SECURITY.md +16 -0
- package/skills/urp-postprocessing/SKILL.md +188 -0
- package/skills/urp-postprocessing/references/code-templates.md +150 -0
- package/skills/urp-postprocessing/references/effect-reference.md +86 -0
- package/skills/validate-urp-render-graph-renderer-feature/SKILL.md +92 -0
- package/skills/validate-urp-render-graph-renderer-feature/references/validation-checklist.md +179 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
// Editor-only contact recorder for the fix-3d-physics-collisions skill.
|
|
2
|
+
//
|
|
3
|
+
// It adds no components and saves nothing to the scene. In Play mode it sets Collider.providesContacts on the
|
|
4
|
+
// tracked colliders, which Unity reverts when Play mode ends, reads Physics.ContactEvent, flattens and filters
|
|
5
|
+
// the contact buffer in a job, and logs the result to the Console with the [CollisionDebugger] prefix.
|
|
6
|
+
//
|
|
7
|
+
// 1. Copy this file to Assets/Editor/CollisionDebugger.cs and wait for the Editor to compile it.
|
|
8
|
+
// 2. In Edit mode, call CollisionDebugger.Track("Bullet", "Wall") with the GameObject names to watch.
|
|
9
|
+
// 3. Enter Play mode and reproduce the problem. Contact enter and exit events are logged as they happen.
|
|
10
|
+
// 4. Exit Play mode. A summary of every tracked pair is logged, and the debugger switches itself off.
|
|
11
|
+
// 5. Delete this file and its .meta file.
|
|
12
|
+
using System;
|
|
13
|
+
using System.Collections.Generic;
|
|
14
|
+
using System.Text;
|
|
15
|
+
using Unity.Collections;
|
|
16
|
+
using Unity.Jobs;
|
|
17
|
+
using UnityEditor;
|
|
18
|
+
using UnityEngine;
|
|
19
|
+
using UnityEngine.SceneManagement;
|
|
20
|
+
using Object = UnityEngine.Object;
|
|
21
|
+
|
|
22
|
+
[InitializeOnLoad]
|
|
23
|
+
public static class CollisionDebugger
|
|
24
|
+
{
|
|
25
|
+
const string k_Prefix = "[CollisionDebugger]";
|
|
26
|
+
const string k_ActiveKey = "CollisionDebugger.Active";
|
|
27
|
+
const string k_TrackedKey = "CollisionDebugger.Tracked";
|
|
28
|
+
const int k_MaxEventLogs = 200;
|
|
29
|
+
|
|
30
|
+
enum Phase : byte { Stay, Enter, Exit }
|
|
31
|
+
|
|
32
|
+
struct PairRecord
|
|
33
|
+
{
|
|
34
|
+
public EntityId collider;
|
|
35
|
+
public EntityId otherCollider;
|
|
36
|
+
public EntityId body;
|
|
37
|
+
public EntityId otherBody;
|
|
38
|
+
public Phase phase;
|
|
39
|
+
public int contactCount;
|
|
40
|
+
public float impulse;
|
|
41
|
+
public bool tracked;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
struct PairStats
|
|
45
|
+
{
|
|
46
|
+
public int enter;
|
|
47
|
+
public int stay;
|
|
48
|
+
public int exit;
|
|
49
|
+
public int maxContacts;
|
|
50
|
+
public float maxImpulse;
|
|
51
|
+
public EntityId body;
|
|
52
|
+
public EntityId otherBody;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Flattens every ContactPair in the buffer into one record, and marks the records that involve a tracked
|
|
56
|
+
// collider or body. The buffer is read-only and only valid until the next simulation step.
|
|
57
|
+
struct FlattenContactsJob : IJobParallelFor
|
|
58
|
+
{
|
|
59
|
+
[ReadOnly] public NativeArray<ContactPairHeader>.ReadOnly headers;
|
|
60
|
+
[ReadOnly] public NativeArray<int> offsets;
|
|
61
|
+
[ReadOnly] public NativeArray<EntityId> trackedIds;
|
|
62
|
+
[NativeDisableParallelForRestriction] public NativeArray<PairRecord> records;
|
|
63
|
+
|
|
64
|
+
public void Execute(int index)
|
|
65
|
+
{
|
|
66
|
+
var header = headers[index];
|
|
67
|
+
var body = header.bodyEntityId;
|
|
68
|
+
var otherBody = header.otherBodyEntityId;
|
|
69
|
+
var pairCount = header.pairCount;
|
|
70
|
+
|
|
71
|
+
for (int i = 0; i < pairCount; i++)
|
|
72
|
+
{
|
|
73
|
+
ref readonly var pair = ref header.GetContactPair(i);
|
|
74
|
+
var record = new PairRecord
|
|
75
|
+
{
|
|
76
|
+
collider = pair.colliderEntityId,
|
|
77
|
+
otherCollider = pair.otherColliderEntityId,
|
|
78
|
+
body = body,
|
|
79
|
+
otherBody = otherBody,
|
|
80
|
+
phase = pair.isCollisionEnter ? Phase.Enter : pair.isCollisionExit ? Phase.Exit : Phase.Stay,
|
|
81
|
+
contactCount = pair.contactCount,
|
|
82
|
+
impulse = pair.impulseSum.magnitude,
|
|
83
|
+
};
|
|
84
|
+
record.tracked = Contains(record.collider) || Contains(record.otherCollider)
|
|
85
|
+
|| Contains(body) || Contains(otherBody);
|
|
86
|
+
records[offsets[index] + i] = record;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
bool Contains(EntityId id)
|
|
91
|
+
{
|
|
92
|
+
for (int i = 0; i < trackedIds.Length; i++)
|
|
93
|
+
if (trackedIds[i] == id)
|
|
94
|
+
return true;
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Object.GetEntityId is public from Unity 6000.5, which removes GetInstanceID. In 6000.3 and 6000.4 the
|
|
100
|
+
// instance ID converts to the same EntityId that contact events report.
|
|
101
|
+
static EntityId IdOf(Object obj)
|
|
102
|
+
{
|
|
103
|
+
#if UNITY_6000_5_OR_NEWER
|
|
104
|
+
return obj.GetEntityId();
|
|
105
|
+
#else
|
|
106
|
+
return obj.GetInstanceID();
|
|
107
|
+
#endif
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static bool s_Attached;
|
|
111
|
+
static int s_EventLogs;
|
|
112
|
+
static NativeArray<EntityId> s_TrackedIds;
|
|
113
|
+
static readonly List<Collider> s_TrackedColliders = new List<Collider>();
|
|
114
|
+
static readonly Dictionary<EntityId, string> s_Names = new Dictionary<EntityId, string>();
|
|
115
|
+
static readonly Dictionary<(EntityId, EntityId), PairStats> s_Stats = new Dictionary<(EntityId, EntityId), PairStats>();
|
|
116
|
+
static readonly HashSet<EntityId> s_Touched = new HashSet<EntityId>();
|
|
117
|
+
static readonly HashSet<(Collider, Collider)> s_Overlaps = new HashSet<(Collider, Collider)>();
|
|
118
|
+
static readonly HashSet<Collider> s_EverOverlapped = new HashSet<Collider>();
|
|
119
|
+
static readonly List<(Collider, Collider)> s_OverlapScratch = new List<(Collider, Collider)>();
|
|
120
|
+
static Collider[] s_OverlapHits = new Collider[64];
|
|
121
|
+
|
|
122
|
+
static CollisionDebugger()
|
|
123
|
+
{
|
|
124
|
+
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
|
125
|
+
AssemblyReloadEvents.beforeAssemblyReload += Detach;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/// Records contacts for the named GameObjects, and their child colliders, in the next Play mode session.
|
|
129
|
+
/// At least one name is required, because only tracked colliders are set to provide contacts.
|
|
130
|
+
/// Call this in Edit mode.
|
|
131
|
+
public static void Track(string gameObjectName, params string[] moreGameObjectNames)
|
|
132
|
+
{
|
|
133
|
+
var names = new List<string> { gameObjectName };
|
|
134
|
+
if (moreGameObjectNames != null)
|
|
135
|
+
names.AddRange(moreGameObjectNames);
|
|
136
|
+
names.RemoveAll(string.IsNullOrWhiteSpace);
|
|
137
|
+
if (names.Count == 0)
|
|
138
|
+
{
|
|
139
|
+
Debug.LogError($"{k_Prefix} Pass the name of at least one GameObject to track.");
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
SessionState.SetString(k_TrackedKey, string.Join("\n", names));
|
|
144
|
+
SessionState.SetBool(k_ActiveKey, true);
|
|
145
|
+
var what = string.Join(", ", names);
|
|
146
|
+
if (EditorApplication.isPlaying)
|
|
147
|
+
Debug.LogWarning($"{k_Prefix} Tracking {what} from the next Play mode session. Exit and re-enter Play mode, because the debugger finds the tracked GameObjects when Play mode starts.");
|
|
148
|
+
else
|
|
149
|
+
Debug.Log($"{k_Prefix} Tracking {what}. Enter Play mode to record.");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/// Switches the debugger off without waiting for Play mode to end.
|
|
153
|
+
public static void Stop()
|
|
154
|
+
{
|
|
155
|
+
if (s_Attached)
|
|
156
|
+
LogSummary();
|
|
157
|
+
Detach();
|
|
158
|
+
SessionState.EraseBool(k_ActiveKey);
|
|
159
|
+
SessionState.EraseString(k_TrackedKey);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
static void OnPlayModeStateChanged(PlayModeStateChange change)
|
|
163
|
+
{
|
|
164
|
+
if (!SessionState.GetBool(k_ActiveKey, false))
|
|
165
|
+
return;
|
|
166
|
+
|
|
167
|
+
switch (change)
|
|
168
|
+
{
|
|
169
|
+
case PlayModeStateChange.EnteredPlayMode:
|
|
170
|
+
Attach();
|
|
171
|
+
break;
|
|
172
|
+
case PlayModeStateChange.ExitingPlayMode:
|
|
173
|
+
if (s_Attached)
|
|
174
|
+
LogSummary();
|
|
175
|
+
Detach();
|
|
176
|
+
SessionState.EraseBool(k_ActiveKey);
|
|
177
|
+
SessionState.EraseString(k_TrackedKey);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
static void Attach()
|
|
183
|
+
{
|
|
184
|
+
if (s_Attached)
|
|
185
|
+
return;
|
|
186
|
+
|
|
187
|
+
s_Names.Clear();
|
|
188
|
+
s_Stats.Clear();
|
|
189
|
+
s_Touched.Clear();
|
|
190
|
+
s_Overlaps.Clear();
|
|
191
|
+
s_EverOverlapped.Clear();
|
|
192
|
+
s_TrackedColliders.Clear();
|
|
193
|
+
s_EventLogs = 0;
|
|
194
|
+
|
|
195
|
+
var names = SessionState.GetString(k_TrackedKey, string.Empty)
|
|
196
|
+
.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
|
197
|
+
var ids = new List<EntityId>();
|
|
198
|
+
var report = new StringBuilder($"{k_Prefix} Setup\n");
|
|
199
|
+
LogGlobalSettings(report);
|
|
200
|
+
|
|
201
|
+
var tracked = new List<GameObject>();
|
|
202
|
+
foreach (var name in names)
|
|
203
|
+
{
|
|
204
|
+
var matches = FindInLoadedScenes(name);
|
|
205
|
+
if (matches.Count == 0)
|
|
206
|
+
report.AppendLine($"- '{name}': no GameObject with this name in the loaded scenes, including inactive ones.");
|
|
207
|
+
tracked.AddRange(matches);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
foreach (var go in tracked)
|
|
211
|
+
{
|
|
212
|
+
LogGameObject(go, report);
|
|
213
|
+
foreach (var col in go.GetComponentsInChildren<Collider>(true))
|
|
214
|
+
{
|
|
215
|
+
// Physics.ContactEvent only reports colliders that provide contacts. This change is made in
|
|
216
|
+
// Play mode only, so Unity discards it when Play mode ends.
|
|
217
|
+
col.providesContacts = true;
|
|
218
|
+
s_TrackedColliders.Add(col);
|
|
219
|
+
ids.Add(IdOf(col));
|
|
220
|
+
s_Names[IdOf(col)] = PathOf(col);
|
|
221
|
+
if (col.attachedRigidbody != null)
|
|
222
|
+
{
|
|
223
|
+
ids.Add(IdOf(col.attachedRigidbody));
|
|
224
|
+
s_Names[IdOf(col.attachedRigidbody)] = PathOf(col.attachedRigidbody);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
LogPairFilters(tracked, report);
|
|
230
|
+
Debug.Log(report.ToString());
|
|
231
|
+
|
|
232
|
+
if (ids.Count == 0)
|
|
233
|
+
Debug.LogWarning($"{k_Prefix} None of the tracked GameObjects has a 3D Collider, so there is nothing to record.");
|
|
234
|
+
|
|
235
|
+
s_TrackedIds = new NativeArray<EntityId>(ids.ToArray(), Allocator.Persistent);
|
|
236
|
+
Physics.ContactEvent += OnContactEvent;
|
|
237
|
+
EditorApplication.update += CheckTriggerOverlaps;
|
|
238
|
+
s_Attached = true;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
static void Detach()
|
|
242
|
+
{
|
|
243
|
+
if (!s_Attached)
|
|
244
|
+
return;
|
|
245
|
+
Physics.ContactEvent -= OnContactEvent;
|
|
246
|
+
EditorApplication.update -= CheckTriggerOverlaps;
|
|
247
|
+
if (s_TrackedIds.IsCreated)
|
|
248
|
+
s_TrackedIds.Dispose();
|
|
249
|
+
s_Attached = false;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
static void OnContactEvent(PhysicsScene scene, NativeArray<ContactPairHeader>.ReadOnly headers)
|
|
253
|
+
{
|
|
254
|
+
var headerCount = headers.Length;
|
|
255
|
+
if (headerCount == 0)
|
|
256
|
+
return;
|
|
257
|
+
|
|
258
|
+
var offsets = new NativeArray<int>(headerCount, Allocator.TempJob);
|
|
259
|
+
var total = 0;
|
|
260
|
+
for (int i = 0; i < headerCount; i++)
|
|
261
|
+
{
|
|
262
|
+
offsets[i] = total;
|
|
263
|
+
total += headers[i].pairCount;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
var records = new NativeArray<PairRecord>(total, Allocator.TempJob);
|
|
267
|
+
var job = new FlattenContactsJob
|
|
268
|
+
{
|
|
269
|
+
headers = headers,
|
|
270
|
+
offsets = offsets,
|
|
271
|
+
trackedIds = s_TrackedIds,
|
|
272
|
+
records = records,
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
// The contact buffer is only valid until the next simulation step, so complete the job before returning.
|
|
276
|
+
job.Schedule(headerCount, 16).Complete();
|
|
277
|
+
|
|
278
|
+
for (int i = 0; i < total; i++)
|
|
279
|
+
{
|
|
280
|
+
var r = records[i];
|
|
281
|
+
if (r.tracked)
|
|
282
|
+
Record(r);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
records.Dispose();
|
|
286
|
+
offsets.Dispose();
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
static void Record(in PairRecord r)
|
|
290
|
+
{
|
|
291
|
+
s_Touched.Add(r.collider);
|
|
292
|
+
s_Touched.Add(r.otherCollider);
|
|
293
|
+
s_Touched.Add(r.body);
|
|
294
|
+
s_Touched.Add(r.otherBody);
|
|
295
|
+
|
|
296
|
+
var key = r.collider.CompareTo(r.otherCollider) <= 0 ? (r.collider, r.otherCollider) : (r.otherCollider, r.collider);
|
|
297
|
+
s_Stats.TryGetValue(key, out var stats);
|
|
298
|
+
stats.body = r.body;
|
|
299
|
+
stats.otherBody = r.otherBody;
|
|
300
|
+
stats.maxContacts = Math.Max(stats.maxContacts, r.contactCount);
|
|
301
|
+
stats.maxImpulse = Math.Max(stats.maxImpulse, r.impulse);
|
|
302
|
+
switch (r.phase)
|
|
303
|
+
{
|
|
304
|
+
case Phase.Enter: stats.enter++; break;
|
|
305
|
+
case Phase.Exit: stats.exit++; break;
|
|
306
|
+
default: stats.stay++; break;
|
|
307
|
+
}
|
|
308
|
+
s_Stats[key] = stats;
|
|
309
|
+
|
|
310
|
+
if (r.phase == Phase.Stay || s_EventLogs > k_MaxEventLogs)
|
|
311
|
+
return;
|
|
312
|
+
if (++s_EventLogs > k_MaxEventLogs)
|
|
313
|
+
{
|
|
314
|
+
Debug.Log($"{k_Prefix} More than {k_MaxEventLogs} contact events. Further events are only counted in the summary.");
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
Debug.Log($"{k_Prefix} [Contact {r.phase}] frame {Time.frameCount}: {NameOf(r.collider)} <-> {NameOf(r.otherCollider)} " +
|
|
318
|
+
$"| bodies: {NameOf(r.body)} / {NameOf(r.otherBody)} | contacts: {r.contactCount} | impulse: {r.impulse:F3}");
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Physics.ContactEvent never reports triggers, so compare the geometry of tracked colliders instead.
|
|
322
|
+
// An overlap here means the shapes intersect. Whether Unity sends OnTrigger messages for it also depends on
|
|
323
|
+
// the layers, the body types, and Contact Pairs Mode, which the Setup report lists.
|
|
324
|
+
static void CheckTriggerOverlaps()
|
|
325
|
+
{
|
|
326
|
+
if (!EditorApplication.isPlaying || EditorApplication.isPaused || s_TrackedColliders.Count == 0)
|
|
327
|
+
return;
|
|
328
|
+
|
|
329
|
+
s_OverlapScratch.Clear();
|
|
330
|
+
foreach (var col in s_TrackedColliders)
|
|
331
|
+
{
|
|
332
|
+
if (col == null || !col.enabled || !col.gameObject.activeInHierarchy)
|
|
333
|
+
continue;
|
|
334
|
+
var hitCount = OverlapBounds(col);
|
|
335
|
+
for (int i = 0; i < hitCount; i++)
|
|
336
|
+
{
|
|
337
|
+
var other = s_OverlapHits[i];
|
|
338
|
+
if (other == col || (!col.isTrigger && !other.isTrigger))
|
|
339
|
+
continue;
|
|
340
|
+
var ct = col.transform;
|
|
341
|
+
var ot = other.transform;
|
|
342
|
+
if (!Physics.ComputePenetration(col, ct.position, ct.rotation, other, ot.position, ot.rotation, out _, out _))
|
|
343
|
+
continue;
|
|
344
|
+
// Store the trigger first. When both are triggers, order them so the pair is logged once.
|
|
345
|
+
var pair = col.isTrigger && (!other.isTrigger || IdOf(col).CompareTo(IdOf(other)) < 0) ? (col, other) : (other, col);
|
|
346
|
+
if (!s_OverlapScratch.Contains(pair))
|
|
347
|
+
s_OverlapScratch.Add(pair);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
foreach (var pair in s_OverlapScratch)
|
|
352
|
+
{
|
|
353
|
+
if (!s_Overlaps.Add(pair))
|
|
354
|
+
continue;
|
|
355
|
+
s_EverOverlapped.Add(pair.Item1);
|
|
356
|
+
s_EverOverlapped.Add(pair.Item2);
|
|
357
|
+
Debug.Log($"{k_Prefix} [Trigger overlap start] frame {Time.frameCount}: trigger {PathOf(pair.Item1)} overlaps {PathOf(pair.Item2)} " +
|
|
358
|
+
$"| bodies: {BodyType(pair.Item1)} / {BodyType(pair.Item2)}");
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
s_Overlaps.RemoveWhere(pair =>
|
|
362
|
+
{
|
|
363
|
+
if (s_OverlapScratch.Contains(pair))
|
|
364
|
+
return false;
|
|
365
|
+
Debug.Log($"{k_Prefix} [Trigger overlap end] frame {Time.frameCount}: {(pair.Item1 ? PathOf(pair.Item1) : "(destroyed)")} / {(pair.Item2 ? PathOf(pair.Item2) : "(destroyed)")}");
|
|
366
|
+
return true;
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Collects every collider that overlaps the bounds of col into s_OverlapHits, and returns the count. It queries
|
|
371
|
+
// the collider's own physics scene, because a scene loaded with LocalPhysicsMode.Physics3D has its own world.
|
|
372
|
+
// A full buffer can mean results were dropped, so grow it and query again until the result is complete.
|
|
373
|
+
static int OverlapBounds(Collider col)
|
|
374
|
+
{
|
|
375
|
+
var bounds = col.bounds;
|
|
376
|
+
var physicsScene = col.gameObject.scene.GetPhysicsScene();
|
|
377
|
+
while (true)
|
|
378
|
+
{
|
|
379
|
+
var hitCount = physicsScene.OverlapBox(bounds.center, bounds.extents, s_OverlapHits, Quaternion.identity,
|
|
380
|
+
Physics.AllLayers, QueryTriggerInteraction.Collide);
|
|
381
|
+
if (hitCount < s_OverlapHits.Length)
|
|
382
|
+
return hitCount;
|
|
383
|
+
s_OverlapHits = new Collider[s_OverlapHits.Length * 2];
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
static void LogSummary()
|
|
388
|
+
{
|
|
389
|
+
var sb = new StringBuilder($"{k_Prefix} Summary for frames up to {Time.frameCount}\n");
|
|
390
|
+
if (s_Stats.Count == 0)
|
|
391
|
+
sb.AppendLine("- No contacts were recorded for the tracked colliders.");
|
|
392
|
+
foreach (var entry in s_Stats)
|
|
393
|
+
{
|
|
394
|
+
var s = entry.Value;
|
|
395
|
+
sb.AppendLine($"- {NameOf(entry.Key.Item1)} <-> {NameOf(entry.Key.Item2)} | bodies: {NameOf(s.body)} / {NameOf(s.otherBody)} " +
|
|
396
|
+
$"| enter: {s.enter}, stay: {s.stay}, exit: {s.exit} | max contacts: {s.maxContacts} | max impulse: {s.maxImpulse:F3}");
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
foreach (var col in s_TrackedColliders)
|
|
400
|
+
{
|
|
401
|
+
if (col == null || s_Touched.Contains(IdOf(col)))
|
|
402
|
+
continue;
|
|
403
|
+
if (!col.isTrigger)
|
|
404
|
+
sb.AppendLine($"- {PathOf(col)} had no contacts. Check its layers, the Layer Collision Matrix, its Rigidbody, and Contact Pairs Mode in the Setup report.");
|
|
405
|
+
else if (!s_EverOverlapped.Contains(col))
|
|
406
|
+
sb.AppendLine($"- Trigger {PathOf(col)} never overlapped another collider. Check its position, size, and layers in the Setup report.");
|
|
407
|
+
}
|
|
408
|
+
Debug.Log(sb.ToString());
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// The Physics settings, read from the project's DynamicsManager.asset because some of them, such as
|
|
412
|
+
// Contact Pairs Mode, have no scripting API. Where a script changed a setting at runtime, both values are listed.
|
|
413
|
+
static void LogGlobalSettings(StringBuilder sb)
|
|
414
|
+
{
|
|
415
|
+
sb.AppendLine($"- Unity {Application.unityVersion} | Time.timeScale: {Time.timeScale}");
|
|
416
|
+
var assets = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/DynamicsManager.asset");
|
|
417
|
+
if (assets.Length == 0)
|
|
418
|
+
{
|
|
419
|
+
sb.AppendLine("- Couldn't load ProjectSettings/DynamicsManager.asset to read the Physics settings.");
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
var settings = new SerializedObject(assets[0]);
|
|
424
|
+
var line = new StringBuilder("- Physics settings");
|
|
425
|
+
AppendSetting(settings, line, "m_ContactPairsMode", "Contact Pairs Mode", null, k_ContactPairsModes);
|
|
426
|
+
AppendSetting(settings, line, "m_SimulationMode", "Simulation Mode", ((int)Physics.simulationMode).ToString());
|
|
427
|
+
AppendSetting(settings, line, "m_InvokeCollisionCallbacks", "Invoke Collision Callbacks", Physics.invokeCollisionCallbacks.ToString());
|
|
428
|
+
AppendSetting(settings, line, "m_GenerateOnTriggerStayEvents", "Generate OnTriggerStay Events", null);
|
|
429
|
+
AppendSetting(settings, line, "m_QueriesHitTriggers", "Queries Hit Triggers", Physics.queriesHitTriggers.ToString());
|
|
430
|
+
AppendSetting(settings, line, "m_QueriesHitBackfaces", "Queries Hit Backfaces", Physics.queriesHitBackfaces.ToString());
|
|
431
|
+
AppendSetting(settings, line, "m_DefaultContactOffset", "Default Contact Offset", Physics.defaultContactOffset.ToString());
|
|
432
|
+
AppendSetting(settings, line, "m_SleepThreshold", "Sleep Threshold", Physics.sleepThreshold.ToString());
|
|
433
|
+
sb.AppendLine(line.ToString());
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
static readonly string[] k_ContactPairsModes =
|
|
437
|
+
{ "Default Contact Pairs", "Enable Kinematic Kinematic Pairs", "Enable Kinematic Static Pairs", "Enable All Contact Pairs" };
|
|
438
|
+
|
|
439
|
+
static void AppendSetting(SerializedObject settings, StringBuilder line, string propertyName, string label, string runtimeValue, string[] names = null)
|
|
440
|
+
{
|
|
441
|
+
var p = settings.FindProperty(propertyName);
|
|
442
|
+
if (p == null)
|
|
443
|
+
{
|
|
444
|
+
line.Append($" | {label}: not found");
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
string raw;
|
|
449
|
+
switch (p.propertyType)
|
|
450
|
+
{
|
|
451
|
+
case SerializedPropertyType.Boolean: raw = p.boolValue.ToString(); break;
|
|
452
|
+
case SerializedPropertyType.Float: raw = p.floatValue.ToString(); break;
|
|
453
|
+
case SerializedPropertyType.Integer:
|
|
454
|
+
case SerializedPropertyType.Enum: raw = p.intValue.ToString(); break;
|
|
455
|
+
default: raw = p.propertyType.ToString(); break;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
var display = raw;
|
|
459
|
+
if (names != null && p.intValue >= 0 && p.intValue < names.Length)
|
|
460
|
+
display = $"{raw} ({names[p.intValue]})";
|
|
461
|
+
else if (p.propertyType == SerializedPropertyType.Enum && p.enumValueIndex >= 0 && p.enumValueIndex < p.enumDisplayNames.Length)
|
|
462
|
+
display = $"{raw} ({p.enumDisplayNames[p.enumValueIndex]})";
|
|
463
|
+
|
|
464
|
+
line.Append($" | {label}: {display}");
|
|
465
|
+
if (runtimeValue != null && runtimeValue != raw)
|
|
466
|
+
line.Append($" (changed by a script to {runtimeValue})");
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
static void LogGameObject(GameObject go, StringBuilder sb)
|
|
470
|
+
{
|
|
471
|
+
sb.AppendLine($"- {PathOf(go)} | activeInHierarchy: {go.activeInHierarchy} | layer: {go.layer} ({LayerMask.LayerToName(go.layer)}) " +
|
|
472
|
+
$"| lossyScale: {go.transform.lossyScale}");
|
|
473
|
+
if (go.GetComponent<CharacterController>() != null)
|
|
474
|
+
sb.AppendLine(" - Has a CharacterController: it reports hits through OnControllerColliderHit, not OnCollisionEnter.");
|
|
475
|
+
if (go.GetComponentInChildren<Collider2D>(true) != null || go.GetComponentInParent<Rigidbody2D>() != null)
|
|
476
|
+
sb.AppendLine(" - Has 2D physics components, which never interact with 3D colliders.");
|
|
477
|
+
|
|
478
|
+
foreach (var col in go.GetComponentsInChildren<Collider>(true))
|
|
479
|
+
{
|
|
480
|
+
var mesh = col as MeshCollider;
|
|
481
|
+
var parentBody = col.GetComponentInParent<Rigidbody>(true);
|
|
482
|
+
if (mesh != null && !mesh.convex && !mesh.isTrigger && col.attachedRigidbody == null && parentBody != null && !parentBody.isKinematic)
|
|
483
|
+
sb.AppendLine($" - Non-convex MeshCollider under the dynamic Rigidbody {PathOf(parentBody)}: Unity logs an error and doesn't attach the collider to the body.");
|
|
484
|
+
var meshInfo = mesh == null ? string.Empty
|
|
485
|
+
: $" | convex: {mesh.convex} | mesh: {(mesh.sharedMesh ? mesh.sharedMesh.name : "none")} | isReadable: {(mesh.sharedMesh ? mesh.sharedMesh.isReadable.ToString() : "n/a")}";
|
|
486
|
+
sb.AppendLine($" - {col.GetType().Name} on {PathOf(col)} | enabled: {col.enabled} | isTrigger: {col.isTrigger} " +
|
|
487
|
+
$"| includeLayers: {col.includeLayers.value} | excludeLayers: {col.excludeLayers.value} | contactOffset: {col.contactOffset}{meshInfo} " +
|
|
488
|
+
$"| body: {BodyType(col)}");
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
foreach (var rb in go.GetComponentsInChildren<Rigidbody>(true))
|
|
492
|
+
sb.AppendLine($" - Rigidbody on {PathOf(rb)} | isKinematic: {rb.isKinematic} | collisionDetectionMode: {rb.collisionDetectionMode} " +
|
|
493
|
+
$"| detectCollisions: {rb.detectCollisions} | includeLayers: {rb.includeLayers.value} | excludeLayers: {rb.excludeLayers.value}");
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
static void LogPairFilters(List<GameObject> tracked, StringBuilder sb)
|
|
497
|
+
{
|
|
498
|
+
for (int a = 0; a < tracked.Count; a++)
|
|
499
|
+
{
|
|
500
|
+
for (int b = a + 1; b < tracked.Count; b++)
|
|
501
|
+
{
|
|
502
|
+
var ga = tracked[a];
|
|
503
|
+
var gb = tracked[b];
|
|
504
|
+
sb.AppendLine($"- {ga.name} / {gb.name} | layers ignored by the Layer Collision Matrix: {Physics.GetIgnoreLayerCollision(ga.layer, gb.layer)}");
|
|
505
|
+
foreach (var ca in ga.GetComponentsInChildren<Collider>(true))
|
|
506
|
+
foreach (var cb in gb.GetComponentsInChildren<Collider>(true))
|
|
507
|
+
if (Physics.GetIgnoreCollision(ca, cb))
|
|
508
|
+
sb.AppendLine($" - Physics.IgnoreCollision is set for {PathOf(ca)} / {PathOf(cb)}");
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
static List<GameObject> FindInLoadedScenes(string name)
|
|
515
|
+
{
|
|
516
|
+
var result = new List<GameObject>();
|
|
517
|
+
for (int i = 0; i < SceneManager.sceneCount; i++)
|
|
518
|
+
{
|
|
519
|
+
var scene = SceneManager.GetSceneAt(i);
|
|
520
|
+
if (!scene.isLoaded)
|
|
521
|
+
continue;
|
|
522
|
+
foreach (var root in scene.GetRootGameObjects())
|
|
523
|
+
foreach (var t in root.GetComponentsInChildren<Transform>(true))
|
|
524
|
+
if (t.name == name)
|
|
525
|
+
result.Add(t.gameObject);
|
|
526
|
+
}
|
|
527
|
+
return result;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
static string BodyType(Collider col)
|
|
531
|
+
{
|
|
532
|
+
var rb = col.attachedRigidbody;
|
|
533
|
+
if (rb != null)
|
|
534
|
+
return rb.isKinematic ? $"Kinematic ({rb.name})" : $"Dynamic ({rb.name})";
|
|
535
|
+
var ab = col.attachedArticulationBody;
|
|
536
|
+
return ab != null ? $"ArticulationBody ({ab.name})" : "Static";
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
static string NameOf(EntityId id)
|
|
540
|
+
{
|
|
541
|
+
if (id == default)
|
|
542
|
+
return "(none)";
|
|
543
|
+
if (s_Names.TryGetValue(id, out var name))
|
|
544
|
+
return name;
|
|
545
|
+
var obj = Resources.EntityIdToObject(id);
|
|
546
|
+
name = obj != null ? PathOf(obj) : $"(destroyed {id})";
|
|
547
|
+
s_Names[id] = name;
|
|
548
|
+
return name;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
static string PathOf(Object obj)
|
|
552
|
+
{
|
|
553
|
+
var t = obj is Component c ? c.transform : obj is GameObject g ? g.transform : null;
|
|
554
|
+
if (t == null)
|
|
555
|
+
return obj.name;
|
|
556
|
+
var path = t.name;
|
|
557
|
+
for (var p = t.parent; p != null; p = p.parent)
|
|
558
|
+
path = p.name + "/" + path;
|
|
559
|
+
return obj is Component ? $"{path} ({obj.GetType().Name})" : path;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Security notes: generate-editor-search-query
|
|
2
|
+
|
|
3
|
+
This skill has the agent run C# inside the user's open Unity Editor through `unity command script eval`. Automated skill scanners flag that as a powerful capability. It is intentional, and it is limited by the safeguards below.
|
|
4
|
+
|
|
5
|
+
## Accepted risks
|
|
6
|
+
|
|
7
|
+
| Risk | Capability | Why it is accepted |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `SEC_POWER_CAP` | Runs C# in the user's open Editor through `unity command script eval` | It only reaches the Editor the user already has open, on their own machine, as that user, so it grants nothing they couldn't do themselves. `script eval` sits behind the Pipeline capability gate. No code fetched from a remote source is run. The skill only opens the Search window with a query; it does not act on results. |
|
|
10
|
+
|
|
11
|
+
## Mitigations
|
|
12
|
+
|
|
13
|
+
- **Only the user's own Editor.** `unity command script eval` talks to the Editor open on this machine. It can't reach another machine or another user's Editor.
|
|
14
|
+
- **Capability gate.** `script eval` is only available when the project's Pipeline package provides it.
|
|
15
|
+
- **No remote code.** The agent runs C# it writes from this skill's own recipes. Nothing downloaded from outside is executed.
|
|
16
|
+
- **Query passed base64-encoded, not interpolated as text.** The generated Unity Search query is base64-encoded before it is embedded in the C# snippet, and decoded back to a string inside the snippet. A query containing `"` can't break out of the C# string, and a query containing `'` can't break the shell's single-quoting around `--code` — base64's alphabet (`A-Z a-z 0-9 + / =`) contains neither character, so the query text can never change the code that runs.
|
|
17
|
+
- **Read-only.** The snippet only opens the Search window; it does not select, rename, delete, move, import, edit, or save anything.
|