Skip to content

Pr 1051 unity65 compat#1058

Merged
Scriptwonder merged 8 commits intoCoplayDev:betafrom
Scriptwonder:pr-1051-unity65-compat
Apr 12, 2026
Merged

Pr 1051 unity65 compat#1058
Scriptwonder merged 8 commits intoCoplayDev:betafrom
Scriptwonder:pr-1051-unity65-compat

Conversation

@Scriptwonder
Copy link
Copy Markdown
Collaborator

@Scriptwonder Scriptwonder commented Apr 12, 2026

Pickup on #1051 for cleanup

Summary by Sourcery

Add Unity 6.5+ compatible object identification and find-object helpers while preserving backward-compatible instanceID-based serialization.

Enhancements:

  • Introduce compatibility wrappers for Unity object ID access and object-finding APIs, replacing direct GetInstanceID and FindObjectsOfType/FindObjectsByType calls across editor and runtime tools.
  • Extend UnityEngine.Object JSON serialization to emit and consume stable entityID values on Unity 6.5+ while maintaining instanceID fields for older consumers.
  • Standardize use of the new helpers in camera, physics, graphics, prefab, ProBuilder, asset, and selection tooling to smooth upgrades across Unity versions.

Summary by CodeRabbit

  • Refactor
    • Enhanced compatibility across Unity versions by introducing standardized object identification helpers that abstract version-specific APIs, eliminating conditional compilation branches throughout the codebase.
    • Improved serialization to support newer Unity's entity system while maintaining backward compatibility with older versions.

tomicz and others added 8 commits April 9, 2026 11:35
Use a version-gated helper that calls GetEntityId on UNITY_6000_5_OR_NEWER while preserving GetInstanceID for older Unity versions.
Suppress the transitional CS0619 cast warning when serializing GetEntityId so projects with warnings-as-errors can compile while keeping backward-compatible instanceID payloads.
Replace direct GetInstanceID calls with a compatibility helper and update serialization to handle EntityId-era identifiers, so the package compiles on Unity 6.5 while preserving behavior on older versions.
Place the compatibility extension in MCPForUnity.Runtime so Runtime/Serialization can resolve GetInstanceIDCompat, fixing Unity 2022 compile errors from assembly visibility.
Keep instanceID in outgoing payloads for wire compatibility, add entityID on newer Unity, continue fallback resolution when entityID lookup fails, and make reflective entity resolution exception-safe.
Addresses review feedback on the Unity 6.5 GetInstanceID migration:

- UnityObjectIdCompatExtensions: drop the reflective method lookup in
  favor of a simple #if UNITY_6000_5_OR_NEWER / #else split calling
  GetEntityId() or GetInstanceID() directly. Also wrap the class in
  the MCPForUnity.Runtime.Helpers namespace.
- UnityTypeConverters: remove the reflective EntityIdToObject probe and
  call EditorUtility.EntityIdToObject(EntityId) directly under the same
  version gate. Serialize entityID as EntityId.ToULong() rather than
  ToString(), since Unity's docs explicitly warn that the textual form
  is not a stable serialization contract.
- Drop #pragma warning disable 0619 from 22 files that no longer make
  any direct calls to obsolete APIs. The remaining 7 files still need
  it (FindObjectsOfType, InstanceIDToObject fallback) and are left as-is
  — those deprecations are out of scope for this PR.
- Add the MCPForUnity.Runtime.Helpers using to every file that calls
  GetInstanceIDCompat() now that the extension method lives in a
  namespace.
Copilot AI review requested due to automatic review settings April 12, 2026 20:43
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai bot commented Apr 12, 2026

Reviewer's Guide

Adds Unity 6.5-compatible object ID and object-finding helpers, switches existing systems to use them, and extends Unity object JSON serialization/deserialization to support the new EntityId API while preserving backward compatibility with instanceID-based workflows.

Sequence diagram for UnityEngine.Object JSON serialization/deserialization with entityID support

sequenceDiagram
    participant Caller
    participant Converter as UnityEngineObjectConverter
    participant Obj as UnityEngine.Object
    participant IdExt as UnityObjectIdCompatExtensions
    participant EntityId
    participant EditorUtil as UnityEditor.EditorUtility

    Caller->>Converter: WriteJson(writer, Obj, serializer)
    activate Converter
    Converter->>Obj: name
    Converter->>IdExt: GetInstanceIDCompat(Obj)
    IdExt-->>Converter: instanceID:int
    Converter->>Obj: GetEntityId()
    Obj-->>Converter: EntityId
    Converter->>EntityId: ToULong(EntityId)
    EntityId-->>Converter: entityIdUlong:ulong
    Converter-->>Caller: JSON with name, instanceID, entityID
    deactivate Converter

    Caller->>Converter: ReadJson(reader, objectType, existingValue, serializer)
    activate Converter
    Converter->>Converter: parse JObject jo
    Converter->>jo: try get entityID
    alt entityID present and valid
        Converter->>EntityId: FromULong(parsedEntityId)
        EntityId-->>Converter: eid
        Converter->>EditorUtil: EntityIdToObject(eid)
        EditorUtil-->>Converter: entityObj
        alt entityObj matches objectType
            Converter-->>Caller: entityObj
        else objectType is Transform and entityObj is GameObject
            Converter-->>Caller: entityObj.transform
        else objectType is Component
            Converter->>entityObj: GetComponent(objectType)
            entityObj-->>Converter: component
            Converter-->>Caller: component or null
        end
    else no valid entityID
        Converter->>jo: try get instanceID
        note over Converter,Caller: If entityID resolution fails or is missing Converter falls back to legacy instanceID guid or path logic.
    end
    deactivate Converter
Loading

Class diagram for Unity 6.5-compatible object ID helpers and converters

classDiagram
    class UnityEngineObjectConverter {
        +WriteJson(writer, value, serializer)
        +ReadJson(reader, objectType, existingValue, serializer) UnityEngine.Object
        -WriteSerializedObjectId(writer, value)
    }

    class UnityFindObjectsCompat {
        +FindAll~T~() T[]
        +FindAll(type) Object[]
        +FindAll(type, includeInactive) Object[]
        +FindAny(type) Object
    }

    class UnityObjectIdCompatExtensions {
        +GetInstanceIDCompat(obj) int
    }

    class UnityEngineObject {
        <<UnityEngine>>
        +name string
        +GetEntityId() EntityId
    }

    class EntityId {
        <<UnityEngine>>
        +FromULong(value) EntityId
        +ToULong(id) ulong
    }

    class UnityEditorEditorUtility {
        <<UnityEditor>>
        +EntityIdToObject(id) UnityEngineObject
    }

    UnityEngineObjectConverter ..> UnityFindObjectsCompat : uses
    UnityEngineObjectConverter ..> UnityObjectIdCompatExtensions : uses
    UnityEngineObjectConverter ..> UnityEditorEditorUtility : resolves_entityID
    UnityObjectIdCompatExtensions ..> UnityEngineObject : extends
    UnityFindObjectsCompat ..> UnityEngineObject : finds
    UnityEditorEditorUtility ..> EntityId : converts
    UnityEngineObjectConverter ..> EntityId : serialize_entityID
    UnityEngineObject <|-- EntityId
Loading

Flow diagram for UnityEngine.Object deserialization resolution order

flowchart TD
    A["Start ReadJson for UnityEngine.Object"] --> B{"JSON has entityID field?"}
    B -- "Yes" --> C["Parse entityID string to ulong"]
    C --> D{"Parse succeeded?"}
    D -- "Yes" --> E["Create EntityId from ulong"]
    E --> F["EditorUtility.EntityIdToObject(eid)"]
    F --> G{"entityObj not null?"}
    G -- "Yes" --> H{"objectType assignable from entityObj type?"}
    H -- "Yes" --> R1["Return entityObj"]
    H -- "No" --> I{"objectType is Transform and entityObj is GameObject?"}
    I -- "Yes" --> R2["Return entityObj.transform"]
    I -- "No" --> J{"objectType is Component and entityObj is GameObject?"}
    J -- "Yes" --> K["GetComponent(objectType) on GameObject"]
    K --> L{"component not null?"}
    L -- "Yes" --> R3["Return component"]
    L -- "No" --> Bfallback["Log warning: entityID could not be resolved"]
    G -- "No" --> Bfallback
    D -- "No" --> Bfallback
    Bfallback --> M["Fall back to instanceID/guid/path resolution"]

    B -- "No" --> N{"JSON has instanceID field?"}
    N -- "Yes" --> O["Resolve by instanceID"]
    O --> P{"Resolved object not null?"}
    P -- "Yes" --> R4["Return resolved object"]
    P -- "No" --> Q{"JSON has guid or path field?"}
    N -- "No" --> Q
    Q -- "Yes" --> R["Resolve by guid/path (asset lookup)"]
    R --> S{"Resolved object not null?"}
    S -- "Yes" --> R5["Return resolved object"]
    S -- "No" --> T["Log warning: could not resolve object"]
    Q -- "No" --> T
    T --> U["Return null"]
Loading

File-Level Changes

Change Details Files
Introduce compatibility helpers for Unity 6.5 object IDs and object-finding APIs and wire them into existing code paths.
  • Add UnityObjectIdCompatExtensions with GetInstanceIDCompat wrapper that maps EntityId to an int on Unity 6.5+ and delegates to GetInstanceID on older versions.
  • Add UnityFindObjectsCompat utility providing version-gated wrappers for FindObjectsOfType/FindObjectsByType and related APIs, including overloads for generic and runtime types and inactive inclusion.
  • Replace direct calls to GetInstanceID() across editor tools, serializers, physics, graphics, prefab, ProBuilder, and other utilities with GetInstanceIDCompat to keep a stable int-shaped ID across Unity versions.
  • Replace scattered preprocessor-guarded FindObjectsOfType/FindObjectsByType usages with UnityFindObjectsCompat.FindAll/FindAny to centralize API differences across Unity versions.
MCPForUnity/Runtime/Helpers/UnityObjectIdCompatExtensions.cs
MCPForUnity/Runtime/Helpers/UnityObjectIdCompatExtensions.cs.meta
MCPForUnity/Runtime/Helpers/UnityFindObjectsCompat.cs
MCPForUnity/Runtime/Helpers/UnityFindObjectsCompat.cs.meta
MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs
MCPForUnity/Editor/Tools/ManageScene.cs
MCPForUnity/Editor/Tools/Cameras/CameraControl.cs
MCPForUnity/Editor/Helpers/GameObjectSerializer.cs
MCPForUnity/Editor/Tools/Cameras/CameraConfigure.cs
MCPForUnity/Editor/Tools/Physics/PhysicsQueryOps.cs
MCPForUnity/Editor/Tools/Physics/PhysicsSimulationOps.cs
MCPForUnity/Editor/Helpers/GameObjectLookup.cs
MCPForUnity/Editor/Tools/GameObjects/ManageGameObjectCommon.cs
MCPForUnity/Editor/Tools/Cameras/CameraHelpers.cs
MCPForUnity/Editor/Tools/Graphics/VolumeOps.cs
MCPForUnity/Editor/Tools/ManageComponents.cs
MCPForUnity/Editor/Resources/Scene/GameObjectResource.cs
MCPForUnity/Editor/Tools/Cameras/CameraCreate.cs
MCPForUnity/Editor/Tools/Graphics/LightBakingOps.cs
MCPForUnity/Editor/Tools/Physics/JointOps.cs
MCPForUnity/Editor/Resources/Editor/Selection.cs
MCPForUnity/Editor/Tools/Graphics/GraphicsHelpers.cs
MCPForUnity/Editor/Tools/ManageAsset.cs
MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs
MCPForUnity/Runtime/Helpers/ScreenshotUtility.cs
MCPForUnity/Editor/Tools/Graphics/SkyboxOps.cs
MCPForUnity/Editor/Tools/Physics/PhysicsRigidbodyOps.cs
MCPForUnity/Editor/Tools/Prefabs/ManagePrefabs.cs
MCPForUnity/Editor/Helpers/ComponentOps.cs
MCPForUnity/Editor/Resources/Editor/Windows.cs
MCPForUnity/Editor/Tools/GameObjects/GameObjectDelete.cs
MCPForUnity/Editor/Tools/GameObjects/GameObjectDuplicate.cs
MCPForUnity/Editor/Tools/GameObjects/GameObjectLookAt.cs
MCPForUnity/Editor/Tools/Graphics/RendererFeatureOps.cs
MCPForUnity/Editor/Tools/ManageMaterial.cs
MCPForUnity/Editor/Tools/Vfx/ParticleControl.cs
MCPForUnity/Editor/Tools/ManageUI.cs
Extend UnityEngine.Object JSON serialization/deserialization to support EntityId-based resolution on Unity 6.5+ while maintaining backward compatibility with older JSON consumers.
  • Refactor UnityEngineObjectConverter to centralize ID writing into WriteSerializedObjectId, which always emits instanceID and additionally emits entityID (as a ulong string) on Unity 6.5+.
  • Add deserialization logic under UNITY_6000_5_OR_NEWER to resolve Unity objects by entityID via EditorUtility.EntityIdToObject, with fallbacks to type checks, Transform/component resolution, and existing instanceID/guid/path paths.
  • Update warning messages to mention entityID in the list of required fields when JSON cannot be resolved to a Unity object.
  • Ensure non-editor serialization path also uses WriteSerializedObjectId so runtime warnings still include compatible IDs.
MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 12, 2026

📝 Walkthrough

Walkthrough

This pull request introduces compatibility helpers for handling Unity version differences—specifically supporting Unity 6.0.5+ which changed instance ID retrieval—and systematically updates ~30 files across editor tools, serialization, and runtime helpers to use these new abstractions instead of version-specific APIs.

Changes

Cohort / File(s) Summary
Compatibility Helpers
MCPForUnity/Runtime/Helpers/UnityObjectIdCompatExtensions.cs, MCPForUnity/Runtime/Helpers/UnityFindObjectsCompat.cs, MCPForUnity/Runtime/Helpers/UnityObjectIdCompatExtensions.cs.meta, MCPForUnity/Runtime/Helpers/UnityFindObjectsCompat.cs.meta
Added new GetInstanceIDCompat() extension (returns EntityId-derived int for Unity 6.0.5+, falls back to GetInstanceID) and UnityFindObjectsCompat helper (wraps version-conditional FindObjectsByType/FindObjectsOfType APIs). Both handle compile-time version branching internally.
Editor Helpers – Instance ID Updates
MCPForUnity/Editor/Helpers/ComponentOps.cs, MCPForUnity/Editor/Helpers/GameObjectLookup.cs, MCPForUnity/Editor/Helpers/GameObjectSerializer.cs, MCPForUnity/Editor/Resources/Editor/Selection.cs, MCPForUnity/Editor/Resources/Editor/Windows.cs
Replaced GetInstanceID() with GetInstanceIDCompat() throughout instance ID serialization in GameObject lookup, component operations, and editor selection/window payloads.
Scene & Resource Management
MCPForUnity/Editor/Resources/Scene/GameObjectResource.cs, MCPForUnity/Editor/Tools/ManageScene.cs, MCPForUnity/Editor/Tools/Prefabs/ManagePrefabs.cs
Updated GameObject instance ID serialization to use GetInstanceIDCompat() and replaced version-conditional camera/renderer object discovery with UnityFindObjectsCompat.FindAll().
Camera Tools
MCPForUnity/Editor/Tools/Cameras/CameraConfigure.cs, MCPForUnity/Editor/Tools/Cameras/CameraControl.cs, MCPForUnity/Editor/Tools/Cameras/CameraCreate.cs, MCPForUnity/Editor/Tools/Cameras/CameraHelpers.cs
Replaced GetInstanceID() with GetInstanceIDCompat() in camera response payloads and updated object discovery (FindBrain/FindMainCamera) to use UnityFindObjectsCompat instead of version-conditional FindObjectsByType/FindObjectsOfType branches.
Physics Tools
MCPForUnity/Editor/Tools/Physics/JointOps.cs, MCPForUnity/Editor/Tools/Physics/PhysicsQueryOps.cs, MCPForUnity/Editor/Tools/Physics/PhysicsRigidbodyOps.cs, MCPForUnity/Editor/Tools/Physics/PhysicsSimulationOps.cs
Updated all rigidbody and physics query response payloads to report instanceID via GetInstanceIDCompat(); replaced version-conditional rigidbody discovery with UnityFindObjectsCompat.FindAll().
Graphics Tools
MCPForUnity/Editor/Tools/Graphics/GraphicsHelpers.cs, MCPForUnity/Editor/Tools/Graphics/LightBakingOps.cs, MCPForUnity/Editor/Tools/Graphics/RendererFeatureOps.cs, MCPForUnity/Editor/Tools/Graphics/SkyboxOps.cs, MCPForUnity/Editor/Tools/Graphics/VolumeOps.cs
Updated probe/volume/light response payloads to use GetInstanceIDCompat() for instanceID; replaced version-conditional volume/object discovery with UnityFindObjectsCompat calls.
GameObject & Asset Tools
MCPForUnity/Editor/Tools/GameObjects/GameObjectDelete.cs, MCPForUnity/Editor/Tools/GameObjects/GameObjectDuplicate.cs, MCPForUnity/Editor/Tools/GameObjects/GameObjectLookAt.cs, MCPForUnity/Editor/Tools/ManageAsset.cs, MCPForUnity/Editor/Tools/ManageComponents.cs, MCPForUnity/Editor/Tools/ManageMaterial.cs, MCPForUnity/Editor/Tools/ManageGameObjectCommon.cs
Replaced GetInstanceID() with GetInstanceIDCompat() in asset/component response payloads and unique material path generation; removed version-conditional component discovery in ManageGameObjectCommon, replacing it with UnityFindObjectsCompat.FindAll().
ProBuilder & VFX Tools
MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs, MCPForUnity/Editor/Tools/Vfx/ParticleControl.cs
Updated shape/mesh creation response payloads to use GetInstanceIDCompat() for instanceId/targetId fields.
UI & Serialization
MCPForUnity/Editor/Tools/ManageUI.cs, MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs, MCPForUnity/Runtime/Helpers/ScreenshotUtility.cs
Changed PanelSettings cache keying to use GetInstanceIDCompat(); refactored UnityEngineObjectConverter to centralize instanceID serialization via GetInstanceIDCompat() helper and added dual entityID serialization/deserialization for Unity 6.0.5+; updated ScreenshotUtility camera discovery to use UnityFindObjectsCompat.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 Across Unity's many lands,
Where instance IDs shift like desert sands,
A helper brave declares with glee,
"One compat call works for version three!"
From six-point-oh to yesterday's way,
Find and ID objects the unified way! 🎯

🚥 Pre-merge checks | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description partially addresses the changeset but is incomplete: it lacks the Type of Change field, Testing/Screenshots section, and Documentation Updates checklist required by the template. Complete the description by adding all required template sections: explicitly select a Type of Change (Refactoring), add Testing information, and fill out the Documentation Updates checklist.
Docstring Coverage ⚠️ Warning Docstring coverage is 32.63% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Pr 1051 unity65 compat' is vague and does not clearly describe the main changes, using generic phrasing without meaningful detail about the changeset. Revise the title to be more descriptive, such as 'Add Unity 6.5+ compatibility helpers for object identification and find-object APIs' to clearly communicate the primary change.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In UnityTypeConverters.ReadJson the new entityID resolution block is only wrapped in UNITY_6000_5_OR_NEWER, but it still calls UnityEditor.EditorUtility; this code should also be gated by UNITY_EDITOR (or moved to an Editor-only path) to avoid UnityEditor references in runtime/player builds.
  • The new GetInstanceIDCompat implementation truncates a ulong EntityId to int on Unity 6.5+, which can introduce collisions for large id ranges; if these IDs are used as keys or for lookup, consider either documenting this limitation clearly at call sites or preferring the new entityID field in those flows instead of relying on the compat int.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In UnityTypeConverters.ReadJson the new entityID resolution block is only wrapped in UNITY_6000_5_OR_NEWER, but it still calls UnityEditor.EditorUtility; this code should also be gated by UNITY_EDITOR (or moved to an Editor-only path) to avoid UnityEditor references in runtime/player builds.
- The new GetInstanceIDCompat implementation truncates a ulong EntityId to int on Unity 6.5+, which can introduce collisions for large id ranges; if these IDs are used as keys or for lookup, consider either documenting this limitation clearly at call sites or preferring the new entityID field in those flows instead of relying on the compat int.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates MCP for Unity to compile and run cleanly on Unity 6.5 by replacing deprecated Object.GetInstanceID() call sites with compatibility helpers and extending object serialization to support Unity 6.5’s entity-style identifiers.

Changes:

  • Introduces GetInstanceIDCompat() and replaces GetInstanceID() usages across editor/runtime tooling.
  • Adds UnityFindObjectsCompat wrappers and updates callers to use version-compatible object-finding APIs.
  • Extends UnityEngine.Object JSON serialization/deserialization to emit/consume entityID (Unity 6.5+) while keeping instanceID for backward compatibility.

Reviewed changes

Copilot reviewed 37 out of 37 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs Emits instanceID via compat helper and optionally emits/reads entityID for Unity 6.5+ object reference round-trips.
MCPForUnity/Runtime/Helpers/UnityObjectIdCompatExtensions.cs Adds GetInstanceIDCompat() to avoid Unity 6.5 GetInstanceID() compile breaks.
MCPForUnity/Runtime/Helpers/UnityObjectIdCompatExtensions.cs.meta Adds Unity meta for new script.
MCPForUnity/Runtime/Helpers/UnityFindObjectsCompat.cs Adds version-gated wrappers around Unity’s object-finding APIs.
MCPForUnity/Runtime/Helpers/UnityFindObjectsCompat.cs.meta Adds Unity meta for new script.
MCPForUnity/Runtime/Helpers/ScreenshotUtility.cs Uses UnityFindObjectsCompat to locate cameras across Unity versions.
MCPForUnity/Editor/Tools/Vfx/ParticleControl.cs Uses GetInstanceIDCompat() in tool responses.
MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs Uses GetInstanceIDCompat() for returned instance IDs.
MCPForUnity/Editor/Tools/Prefabs/ManagePrefabs.cs Uses GetInstanceIDCompat() for prefab and hierarchy IDs.
MCPForUnity/Editor/Tools/Physics/PhysicsSimulationOps.cs Uses GetInstanceIDCompat() and UnityFindObjectsCompat for rigidbody enumeration.
MCPForUnity/Editor/Tools/Physics/PhysicsRigidbodyOps.cs Uses GetInstanceIDCompat() in rigidbody info responses.
MCPForUnity/Editor/Tools/Physics/PhysicsQueryOps.cs Uses GetInstanceIDCompat() for collider/gameobject IDs in query results.
MCPForUnity/Editor/Tools/Physics/JointOps.cs Uses GetInstanceIDCompat() for joint/gameobject IDs.
MCPForUnity/Editor/Tools/ManageUI.cs Uses GetInstanceIDCompat() for PanelSettings identification.
MCPForUnity/Editor/Tools/ManageScene.cs Uses UnityFindObjectsCompat for camera/renderer enumeration and GetInstanceIDCompat() in summaries.
MCPForUnity/Editor/Tools/ManageMaterial.cs Uses GetInstanceIDCompat() for unique material asset naming.
MCPForUnity/Editor/Tools/ManageComponents.cs Uses GetInstanceIDCompat() for component and gameobject IDs in responses.
MCPForUnity/Editor/Tools/ManageAsset.cs Uses GetInstanceIDCompat() in asset/component payloads and minor cleanup.
MCPForUnity/Editor/Tools/Graphics/VolumeOps.cs Uses GetInstanceIDCompat() and UnityFindObjectsCompat for volume operations.
MCPForUnity/Editor/Tools/Graphics/SkyboxOps.cs Uses GetInstanceIDCompat() for sun/gameobject IDs.
MCPForUnity/Editor/Tools/Graphics/RendererFeatureOps.cs Uses GetInstanceIDCompat() for renderer feature IDs.
MCPForUnity/Editor/Tools/Graphics/LightBakingOps.cs Uses GetInstanceIDCompat() for created/baked object IDs.
MCPForUnity/Editor/Tools/Graphics/GraphicsHelpers.cs Uses UnityFindObjectsCompat for volume lookup.
MCPForUnity/Editor/Tools/GameObjects/ManageGameObjectCommon.cs Uses GetInstanceIDCompat() in instance-id based searches and UnityFindObjectsCompat for type searches.
MCPForUnity/Editor/Tools/GameObjects/GameObjectLookAt.cs Uses GetInstanceIDCompat() in response payloads.
MCPForUnity/Editor/Tools/GameObjects/GameObjectDuplicate.cs Uses GetInstanceIDCompat() for original object ID reporting.
MCPForUnity/Editor/Tools/GameObjects/GameObjectDelete.cs Uses GetInstanceIDCompat() when reporting deleted object IDs.
MCPForUnity/Editor/Tools/Cameras/CameraHelpers.cs Uses UnityFindObjectsCompat for camera/brain discovery.
MCPForUnity/Editor/Tools/Cameras/CameraCreate.cs Uses GetInstanceIDCompat() in create/ensure responses.
MCPForUnity/Editor/Tools/Cameras/CameraControl.cs Uses UnityFindObjectsCompat enumeration and GetInstanceIDCompat() in payloads.
MCPForUnity/Editor/Tools/Cameras/CameraConfigure.cs Uses GetInstanceIDCompat() in configuration responses.
MCPForUnity/Editor/Resources/Scene/GameObjectResource.cs Uses GetInstanceIDCompat() for scene serialization IDs.
MCPForUnity/Editor/Resources/Editor/Windows.cs Uses GetInstanceIDCompat() for editor window IDs.
MCPForUnity/Editor/Resources/Editor/Selection.cs Uses GetInstanceIDCompat() for selection IDs.
MCPForUnity/Editor/Helpers/GameObjectSerializer.cs Uses GetInstanceIDCompat() throughout serialized object/component payloads.
MCPForUnity/Editor/Helpers/GameObjectLookup.cs Uses GetInstanceIDCompat() for search result IDs.
MCPForUnity/Editor/Helpers/ComponentOps.cs Uses GetInstanceIDCompat() in logging for sprite file-id lookup failures.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +20 to +27
#if UNITY_6000_5_OR_NEWER
// GetInstanceID() is obsolete-as-error on Unity 6.5+. Truncate the EntityId's
// underlying ulong to int; this is lossy but stable within a session and
// preserves the int-shaped wire format that older consumers expect.
return (int)EntityId.ToULong(obj.GetEntityId());
#else
return obj.GetInstanceID();
#endif
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetInstanceIDCompat() derives the legacy int ID by casting the 64-bit EntityId to int. This is inherently lossy (upper 32 bits discarded), so different objects can collide to the same instanceID on Unity 6.5+, which can break lookups/commands that rely on instanceID uniqueness. Consider maintaining a session-scoped bijective mapping from EntityId (ulong) to a generated int handle (or otherwise ensure uniqueness), and/or make the cast explicitly unchecked to avoid overflow exceptions in checked builds.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +2
fileFormatVersion: 2
guid: 5ea8b580f3e80459cab9019f71d0ccb6 No newline at end of file
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new .meta file only contains fileFormatVersion and guid. Unity typically writes a full MonoImporter block for C# scripts; committing a minimal meta often results in Unity regenerating it on import and causing noisy diffs/merge conflicts. Please include the standard MonoImporter section (matching other script metas in the repo).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment on lines +1 to +2
fileFormatVersion: 2
guid: 7c3a9f12e4b60438d9a1c52ef8d07b3e No newline at end of file
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new .meta file only contains fileFormatVersion and guid. Unity typically writes a full MonoImporter block for C# scripts; committing a minimal meta often results in Unity regenerating it on import and causing noisy diffs/merge conflicts. Please include the standard MonoImporter section (matching other script metas in the repo).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
MCPForUnity/Runtime/Helpers/UnityFindObjectsCompat.cs (1)

28-31: Add explicit null checks for type parameters.

These public methods currently pass null through to Unity APIs, which can surface less actionable exceptions. Guarding early improves diagnostics.

♻️ Suggested guard clauses
 public static UObject[] FindAll(Type type)
 {
+    if (type == null) throw new ArgumentNullException(nameof(type));
 `#if` UNITY_6000_5_OR_NEWER
     return UObject.FindObjectsByType(type, UnityEngine.FindObjectsInactive.Exclude);
 `#elif` UNITY_2022_2_OR_NEWER
     return UObject.FindObjectsByType(type, UnityEngine.FindObjectsSortMode.None);
 `#else`
@@
 public static UObject[] FindAll(Type type, bool includeInactive)
 {
+    if (type == null) throw new ArgumentNullException(nameof(type));
 `#if` UNITY_6000_5_OR_NEWER
     return UObject.FindObjectsByType(type,
         includeInactive ? UnityEngine.FindObjectsInactive.Include : UnityEngine.FindObjectsInactive.Exclude);
@@
 public static UObject FindAny(Type type)
 {
+    if (type == null) throw new ArgumentNullException(nameof(type));
 `#if` UNITY_2022_2_OR_NEWER
     return UObject.FindAnyObjectByType(type);
 `#else`

Also applies to: 40-44, 55-58

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Runtime/Helpers/UnityFindObjectsCompat.cs` around lines 28 - 31,
Add an explicit null guard at the start of each public method that accepts a
Type (e.g., FindAll(Type) and the other FindAll overloads referenced) so you
don't pass null into Unity APIs; check if (type == null) and throw new
ArgumentNullException(nameof(type)) before calling UObject.FindObjectsByType or
UObject.FindObjectsOfTypeAll to provide a clear, actionable exception and
prevent downstream Unity errors.
MCPForUnity/Editor/Tools/ManageScene.cs (1)

817-818: Optional cleanup: remove redundant active-state checks after FindAll<Renderer>().

If UnityFindObjectsCompat.FindAll<Renderer>() already excludes inactive objects, these activeInHierarchy checks are unnecessary branches.

♻️ Proposed cleanup
- if (r == null || !r.gameObject.activeInHierarchy) continue;
+ if (r == null) continue;

Also applies to: 958-959, 1257-1258

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Editor/Tools/ManageScene.cs` around lines 817 - 818, The code
redundantly checks renderer active state after calling
UnityFindObjectsCompat.FindAll<Renderer>() — remove the unnecessary
'!r.gameObject.activeInHierarchy' checks (and the associated short-circuiting
branches) where you already filter by the compat finder; keep the null check for
safety. Update the occurrences around the blocks that iterate renderers in
ManageScene.cs (the if handling 'r == null || !r.gameObject.activeInHierarchy'
near the current lines and the similar checks around lines referenced 958-959
and 1257-1258), leaving the null guard and any logic that depends on
activeInHierarchy only if truly required elsewhere.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@MCPForUnity/Editor/Tools/ManageMaterial.cs`:
- Line 421: The material path uses GetInstanceIDCompat() (matPath, safeName, go)
which truncates the object ID and can collide; change the filename generation to
use the full non-lossy identifier for the GameObject (e.g., replace
GetInstanceIDCompat() with your project's non-lossy ID getter such as the
EntityId/GUID provider or a GetInstanceIDNonLossy() equivalent) so matPath uses
that full identifier to produce stable, non-colliding material filenames.

In `@MCPForUnity/Editor/Tools/ManageUI.cs`:
- Line 1036: The code uses GetInstanceIDCompat() for psId which can be lossy on
newer Unity versions and cause collisions; replace that key with a non-lossy
identifier (e.g., use panelSettings.GetInstanceID() or another unique stable id
derived from the object) and propagate that change to all places that rely on
psId (s_panelRTs dictionary keys and any RT asset naming that currently uses
psId in ManageUI.cs, e.g., where s_panelRTs is accessed and RT names are
constructed). Ensure the chosen id is used consistently for lookup, creation,
and naming so unrelated panels cannot collide.

In `@MCPForUnity/Runtime/Helpers/UnityObjectIdCompatExtensions.cs`:
- Line 24: The cast from ulong to int in UnityObjectIdCompatExtensions (return
(int)EntityId.ToULong(obj.GetEntityId());) should be made explicit about lossy
behavior by wrapping it in unchecked(); update the return expression to use
unchecked((int)EntityId.ToULong(obj.GetEntityId())) so the intent is clear and
future overflow-checking settings won't change behavior.

In `@MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs`:
- Around line 379-383: In UnityTypeConverters.cs update the entityID token type
check so numeric tokens are accepted: in the block that checks
jo.TryGetValue("entityID", out JToken entityIdToken) and currently requires
entityIdToken.Type == JTokenType.String, change it to allow JTokenType.Integer
as well (e.g. entityIdToken.Type == JTokenType.String || entityIdToken.Type ==
JTokenType.Integer), then continue using entityIdToken.ToString() and
ulong.TryParse into rawEntityId as before to resolve the entity instead of
falling back to instanceID; also add unit tests covering both payload shapes
("entityID":"123" and "entityID":123) to ensure both code paths use the
entity-resolution logic (look for variables/methods named entityIdToken,
serializedEntityId, rawEntityId, and the instanceID fallback to validate
behavior).

---

Nitpick comments:
In `@MCPForUnity/Editor/Tools/ManageScene.cs`:
- Around line 817-818: The code redundantly checks renderer active state after
calling UnityFindObjectsCompat.FindAll<Renderer>() — remove the unnecessary
'!r.gameObject.activeInHierarchy' checks (and the associated short-circuiting
branches) where you already filter by the compat finder; keep the null check for
safety. Update the occurrences around the blocks that iterate renderers in
ManageScene.cs (the if handling 'r == null || !r.gameObject.activeInHierarchy'
near the current lines and the similar checks around lines referenced 958-959
and 1257-1258), leaving the null guard and any logic that depends on
activeInHierarchy only if truly required elsewhere.

In `@MCPForUnity/Runtime/Helpers/UnityFindObjectsCompat.cs`:
- Around line 28-31: Add an explicit null guard at the start of each public
method that accepts a Type (e.g., FindAll(Type) and the other FindAll overloads
referenced) so you don't pass null into Unity APIs; check if (type == null) and
throw new ArgumentNullException(nameof(type)) before calling
UObject.FindObjectsByType or UObject.FindObjectsOfTypeAll to provide a clear,
actionable exception and prevent downstream Unity errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ed363935-6a11-4a84-8482-df661c8587d5

📥 Commits

Reviewing files that changed from the base of the PR and between 6948193 and f69acf0.

📒 Files selected for processing (37)
  • MCPForUnity/Editor/Helpers/ComponentOps.cs
  • MCPForUnity/Editor/Helpers/GameObjectLookup.cs
  • MCPForUnity/Editor/Helpers/GameObjectSerializer.cs
  • MCPForUnity/Editor/Resources/Editor/Selection.cs
  • MCPForUnity/Editor/Resources/Editor/Windows.cs
  • MCPForUnity/Editor/Resources/Scene/GameObjectResource.cs
  • MCPForUnity/Editor/Tools/Cameras/CameraConfigure.cs
  • MCPForUnity/Editor/Tools/Cameras/CameraControl.cs
  • MCPForUnity/Editor/Tools/Cameras/CameraCreate.cs
  • MCPForUnity/Editor/Tools/Cameras/CameraHelpers.cs
  • MCPForUnity/Editor/Tools/GameObjects/GameObjectDelete.cs
  • MCPForUnity/Editor/Tools/GameObjects/GameObjectDuplicate.cs
  • MCPForUnity/Editor/Tools/GameObjects/GameObjectLookAt.cs
  • MCPForUnity/Editor/Tools/GameObjects/ManageGameObjectCommon.cs
  • MCPForUnity/Editor/Tools/Graphics/GraphicsHelpers.cs
  • MCPForUnity/Editor/Tools/Graphics/LightBakingOps.cs
  • MCPForUnity/Editor/Tools/Graphics/RendererFeatureOps.cs
  • MCPForUnity/Editor/Tools/Graphics/SkyboxOps.cs
  • MCPForUnity/Editor/Tools/Graphics/VolumeOps.cs
  • MCPForUnity/Editor/Tools/ManageAsset.cs
  • MCPForUnity/Editor/Tools/ManageComponents.cs
  • MCPForUnity/Editor/Tools/ManageMaterial.cs
  • MCPForUnity/Editor/Tools/ManageScene.cs
  • MCPForUnity/Editor/Tools/ManageUI.cs
  • MCPForUnity/Editor/Tools/Physics/JointOps.cs
  • MCPForUnity/Editor/Tools/Physics/PhysicsQueryOps.cs
  • MCPForUnity/Editor/Tools/Physics/PhysicsRigidbodyOps.cs
  • MCPForUnity/Editor/Tools/Physics/PhysicsSimulationOps.cs
  • MCPForUnity/Editor/Tools/Prefabs/ManagePrefabs.cs
  • MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs
  • MCPForUnity/Editor/Tools/Vfx/ParticleControl.cs
  • MCPForUnity/Runtime/Helpers/ScreenshotUtility.cs
  • MCPForUnity/Runtime/Helpers/UnityFindObjectsCompat.cs
  • MCPForUnity/Runtime/Helpers/UnityFindObjectsCompat.cs.meta
  • MCPForUnity/Runtime/Helpers/UnityObjectIdCompatExtensions.cs
  • MCPForUnity/Runtime/Helpers/UnityObjectIdCompatExtensions.cs.meta
  • MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs

}

string matPath = $"{materialFolder}/{safeName}_{go.GetInstanceID()}_mat.mat";
string matPath = $"{materialFolder}/{safeName}_{go.GetInstanceIDCompat()}_mat.mat";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "GetInstanceIDCompat\\(|CreateUniqueAndAssign\\(|_mat\\.mat|EntityId\\.ToULong" \
  MCPForUnity/Editor/Tools/ManageMaterial.cs \
  MCPForUnity/Runtime/Helpers/UnityObjectIdCompatExtensions.cs

Repository: CoplayDev/unity-mcp

Length of output: 733


🏁 Script executed:

# First, let's see the complete CreateUniqueAndAssign method and how matPath is used
sed -n '407,450p' MCPForUnity/Editor/Tools/ManageMaterial.cs

Repository: CoplayDev/unity-mcp

Length of output: 2142


🏁 Script executed:

# Also check if there's any deduplication or collision handling logic
rg -A 10 -B 5 "CreateUniqueAndAssign" MCPForUnity/Editor/Tools/ManageMaterial.cs | head -80

Repository: CoplayDev/unity-mcp

Length of output: 1324


🏁 Script executed:

# Check the complete create_unique mode logic
rg -A 5 -B 5 "create_unique" MCPForUnity/Editor/Tools/ManageMaterial.cs

Repository: CoplayDev/unity-mcp

Length of output: 582


🏁 Script executed:

# Find all uses of GetInstanceIDCompat in the codebase
rg "GetInstanceIDCompat" --type cs

Repository: CoplayDev/unity-mcp

Length of output: 14215


🏁 Script executed:

# Also check if GetStableObjectKey or similar non-lossy ID getter already exists
rg "ToULong|GetEntityId" MCPForUnity --type cs | head -30

Repository: CoplayDev/unity-mcp

Length of output: 478


Use non-lossy object ID for stable material file naming.

Line 421 uses GetInstanceIDCompat() for persistent asset file naming. This truncates EntityId to int on Unity 6.5+, creating collision risk: different GameObjects with IDs differing only in high bits will map to the same material path, causing unintended overwrites or reuse.

For persistent asset paths, use the full non-lossy identifier:

🔧 Proposed fix
+        private static string GetStableObjectKey(UnityEngine.Object obj)
+        {
+#if UNITY_6000_5_OR_NEWER
+            return EntityId.ToULong(obj.GetEntityId()).ToString();
+#else
+            return obj.GetInstanceID().ToString();
+#endif
+        }
...
-            string matPath = $"{materialFolder}/{safeName}_{go.GetInstanceIDCompat()}_mat.mat";
+            string matPath = $"{materialFolder}/{safeName}_{GetStableObjectKey(go)}_mat.mat";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
string matPath = $"{materialFolder}/{safeName}_{go.GetInstanceIDCompat()}_mat.mat";
private static string GetStableObjectKey(UnityEngine.Object obj)
{
`#if` UNITY_6000_5_OR_NEWER
return EntityId.ToULong(obj.GetEntityId()).ToString();
`#else`
return obj.GetInstanceID().ToString();
`#endif`
}
string matPath = $"{materialFolder}/{safeName}_{GetStableObjectKey(go)}_mat.mat";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Editor/Tools/ManageMaterial.cs` at line 421, The material path
uses GetInstanceIDCompat() (matPath, safeName, go) which truncates the object ID
and can collide; change the filename generation to use the full non-lossy
identifier for the GameObject (e.g., replace GetInstanceIDCompat() with your
project's non-lossy ID getter such as the EntityId/GUID provider or a
GetInstanceIDNonLossy() equivalent) so matPath uses that full identifier to
produce stable, non-colliding material filenames.


var panelSettings = uiDoc.panelSettings;
int psId = panelSettings.GetInstanceID();
int psId = panelSettings.GetInstanceIDCompat();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "GetInstanceIDCompat\\(|EntityId\\.ToULong|s_panelRTs|RT_MCP_UI_Render_" \
  MCPForUnity/Editor/Tools/ManageUI.cs \
  MCPForUnity/Runtime/Helpers/UnityObjectIdCompatExtensions.cs

Repository: CoplayDev/unity-mcp

Length of output: 1398


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Get context around the psId usage in ManageUI.cs
echo "=== Full context of psId usage (lines 1030-1100) ==="
sed -n '1030,1100p' MCPForUnity/Editor/Tools/ManageUI.cs | cat -n

# Check all references to s_panelRTs
echo -e "\n=== All s_panelRTs usages ==="
rg -n "s_panelRTs" MCPForUnity/Editor/Tools/ManageUI.cs | cat -n

Repository: CoplayDev/unity-mcp

Length of output: 4788


Avoid lossy compat ID as internal cache key.

Line 1036 uses GetInstanceIDCompat() for psId, but on Unity 6.5+ that value is a truncated ulong and can collide. Here it drives s_panelRTs identity (lines 1047, 1074, 1093) and RT asset naming (lines 1053, 1059), so collisions can mix unrelated panels' render textures and asset paths.

🔧 Proposed fix (use non-lossy key for internal identity)
-        private static readonly Dictionary<int, RenderTexture> s_panelRTs = new();
+        private static readonly Dictionary<string, RenderTexture> s_panelRTs = new();
+
+        private static string GetPanelSettingsCacheKey(PanelSettings panelSettings)
+        {
+#if UNITY_6000_5_OR_NEWER
+            return EntityId.ToULong(panelSettings.GetEntityId()).ToString();
+#else
+            return panelSettings.GetInstanceID().ToString();
+#endif
+        }
...
-                int psId = panelSettings.GetInstanceIDCompat();
+                string psId = GetPanelSettingsCacheKey(panelSettings);
...
                    rt.name = $"MCP_UI_Render_{psId}";
...
                    string rtAssetPath = $"{rtFolder}/RT_MCP_UI_Render_{psId}.renderTexture";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
int psId = panelSettings.GetInstanceIDCompat();
private static readonly Dictionary<string, RenderTexture> s_panelRTs = new();
private static string GetPanelSettingsCacheKey(PanelSettings panelSettings)
{
`#if` UNITY_6000_5_OR_NEWER
return EntityId.ToULong(panelSettings.GetEntityId()).ToString();
`#else`
return panelSettings.GetInstanceID().ToString();
`#endif`
}
// ... other code ...
string psId = GetPanelSettingsCacheKey(panelSettings);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Editor/Tools/ManageUI.cs` at line 1036, The code uses
GetInstanceIDCompat() for psId which can be lossy on newer Unity versions and
cause collisions; replace that key with a non-lossy identifier (e.g., use
panelSettings.GetInstanceID() or another unique stable id derived from the
object) and propagate that change to all places that rely on psId (s_panelRTs
dictionary keys and any RT asset naming that currently uses psId in ManageUI.cs,
e.g., where s_panelRTs is accessed and RT names are constructed). Ensure the
chosen id is used consistently for lookup, creation, and naming so unrelated
panels cannot collide.

// GetInstanceID() is obsolete-as-error on Unity 6.5+. Truncate the EntityId's
// underlying ulong to int; this is lossy but stable within a session and
// preserves the int-shaped wire format that older consumers expect.
return (int)EntityId.ToULong(obj.GetEntityId());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Look for checked overflow contexts or compiler flags that may affect explicit casts.
rg -n --iglob '*.cs' '\bchecked\s*\('
rg -n --iglob '*.rsp' --iglob '*.csproj' --iglob '*.sln' --iglob '*.json' 'checked\+|/checked|CheckForOverflowUnderflow|checkForOverflowUnderflow'

Repository: CoplayDev/unity-mcp

Length of output: 45


Consider wrapping the lossy cast in unchecked() for explicit intent.

The cast from ulong to int at line 24 truncates silently. While no checked-overflow contexts were found in the repository, wrapping the cast explicitly with unchecked() documents the intended lossy behavior and protects against future changes to overflow-checking settings.

💡 Suggested improvement
-            return (int)EntityId.ToULong(obj.GetEntityId());
+            return unchecked((int)EntityId.ToULong(obj.GetEntityId()));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Runtime/Helpers/UnityObjectIdCompatExtensions.cs` at line 24, The
cast from ulong to int in UnityObjectIdCompatExtensions (return
(int)EntityId.ToULong(obj.GetEntityId());) should be made explicit about lossy
behavior by wrapping it in unchecked(); update the return expression to use
unchecked((int)EntityId.ToULong(obj.GetEntityId())) so the intent is clear and
future overflow-checking settings won't change behavior.

Comment on lines +379 to +383
if (jo.TryGetValue("entityID", out JToken entityIdToken) && entityIdToken.Type == JTokenType.String)
{
string serializedEntityId = entityIdToken.ToString();
if (ulong.TryParse(serializedEntityId, out ulong rawEntityId))
{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "UnityTypeConverters.cs" | head -5

Repository: CoplayDev/unity-mcp

Length of output: 121


🏁 Script executed:

cat -n ./MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs | sed -n '375,390p'

Repository: CoplayDev/unity-mcp

Length of output: 1054


🏁 Script executed:

cat -n ./MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs | sed -n '405,415p'

Repository: CoplayDev/unity-mcp

Length of output: 619


🏁 Script executed:

# Let me check the context around the fallback behavior and see what happens after the entityID block
cat -n ./MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs | sed -n '410,430p'

Repository: CoplayDev/unity-mcp

Length of output: 1083


🏁 Script executed:

# Check if there are any tests for this serialization
find . -type f -name "*.cs" | xargs rg -l "UnityEngineObjectConverter|entityID" | grep -i test

Repository: CoplayDev/unity-mcp

Length of output: 9448


🏁 Script executed:

# Let me search for test files more carefully
find . -type f -name "*Test*.cs" -o -name "*test*.cs" | head -20

Repository: CoplayDev/unity-mcp

Length of output: 2074


🏁 Script executed:

# Search for serialization tests
find . -type f -name "*.cs" | xargs rg -l "Serialization|UnityEngineObjectConverter" | grep -i test

Repository: CoplayDev/unity-mcp

Length of output: 13467


🏁 Script executed:

cat -n ./TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/UIDocumentSerializationTests.cs | head -100

Repository: CoplayDev/unity-mcp

Length of output: 4554


🏁 Script executed:

# Search for tests related to UnityEngineObjectConverter
rg "UnityEngineObjectConverter|entityID" --type cs ./TestProjects/UnityMCPTests/

Repository: CoplayDev/unity-mcp

Length of output: 45


🏁 Script executed:

# Let me check the broader context of the UnityEngineObjectConverter class
cat -n ./MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs | sed -n '350,420p'

Repository: CoplayDev/unity-mcp

Length of output: 4276


🏁 Script executed:

rg "entityID" --type cs -B 2 -A 2 | head -80

Repository: CoplayDev/unity-mcp

Length of output: 3363


🏁 Script executed:

cat -n ./MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs | sed -n '430,440p'

Repository: CoplayDev/unity-mcp

Length of output: 800


🏁 Script executed:

cat -n ./MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs | sed -n '260,290p'

Repository: CoplayDev/unity-mcp

Length of output: 1568


🏁 Script executed:

cat -n ./MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs | sed -n '275,330p'

Repository: CoplayDev/unity-mcp

Length of output: 2753


🏁 Script executed:

cat -n ./MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs | sed -n '450,480p'

Repository: CoplayDev/unity-mcp

Length of output: 2176


🏁 Script executed:

cat -n ./MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs | sed -n '490,520p'

Repository: CoplayDev/unity-mcp

Length of output: 1496


Accept numeric entityID tokens in addition to strings.

Current deserialization only enters the entity-resolution path when entityID is a JSON string. Numeric emitters will bypass this and fall back to the lossy instanceID path. Update the type check at line 379 to accept both JTokenType.String and JTokenType.Integer, since JToken.ToString() handles both. Add test cases for both payload shapes: "entityID":"123" and "entityID":123.

🛠️ Suggested fix
- if (jo.TryGetValue("entityID", out JToken entityIdToken) && entityIdToken.Type == JTokenType.String)
+ if (jo.TryGetValue("entityID", out JToken entityIdToken) &&
+     (entityIdToken.Type == JTokenType.String || entityIdToken.Type == JTokenType.Integer))
{
    string serializedEntityId = entityIdToken.ToString();
    if (ulong.TryParse(serializedEntityId, out ulong rawEntityId))
    {
        EntityId eid = EntityId.FromULong(rawEntityId);
        UnityEngine.Object entityObj = UnityEditor.EditorUtility.EntityIdToObject(eid);
        ...
    }
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Runtime/Serialization/UnityTypeConverters.cs` around lines 379 -
383, In UnityTypeConverters.cs update the entityID token type check so numeric
tokens are accepted: in the block that checks jo.TryGetValue("entityID", out
JToken entityIdToken) and currently requires entityIdToken.Type ==
JTokenType.String, change it to allow JTokenType.Integer as well (e.g.
entityIdToken.Type == JTokenType.String || entityIdToken.Type ==
JTokenType.Integer), then continue using entityIdToken.ToString() and
ulong.TryParse into rawEntityId as before to resolve the entity instead of
falling back to instanceID; also add unit tests covering both payload shapes
("entityID":"123" and "entityID":123) to ensure both code paths use the
entity-resolution logic (look for variables/methods named entityIdToken,
serializedEntityId, rawEntityId, and the instanceID fallback to validate
behavior).

@Scriptwonder Scriptwonder merged commit 294c325 into CoplayDev:beta Apr 12, 2026
6 checks passed
@Scriptwonder Scriptwonder deleted the pr-1051-unity65-compat branch April 12, 2026 21:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants