feat: add component reference wiring — get_referenceable, set_reference, batch_wire#1043
feat: add component reference wiring — get_referenceable, set_reference, batch_wire#1043zaferdace wants to merge 3 commits intoCoplayDev:betafrom
Conversation
Reviewer's GuideExtends the existing manage_components tool with three new actions (get_referenceable, set_reference, batch_wire) to support type-safe Unity object reference discovery and assignment from both Python and the Unity editor, including batch atomic wiring, Undo/prefab override correctness, and flexible reference selectors (scene path, asset path, instance ID). Sequence diagram for set_reference action in manage_componentssequenceDiagram
actor PythonClient
participant PythonTool as manage_components_py
participant UnityBridge as send_with_unity_instance
participant UnityEditor as ManageComponents_HandleCommand
participant RefHelper as SetReference
participant Validator as ValidateReferenceAssignment
PythonClient->>PythonTool: manage_components(action=set_reference, target, component_type, property, reference_path/reference_asset_path/reference_instance_id/clear)
PythonTool->>PythonTool: Build params dict
PythonTool->>UnityBridge: send_with_unity_instance("manage_components", params)
UnityBridge->>UnityEditor: HandleCommand(params)
UnityEditor->>UnityEditor: Parse action and target
UnityEditor->>RefHelper: SetReference(params, targetToken, searchMethod)
RefHelper->>RefHelper: TryGetComponentAndObjectReferenceProperty
RefHelper-->>UnityEditor: ErrorResponse? (if failure)
RefHelper->>Validator: ValidateReferenceAssignment(component, propertyName, expectedType, params)
Validator->>Validator: HasReferenceSelector / ResolveReference
Validator->>Validator: ConvertResolvedObject
Validator-->>RefHelper: ReferenceAssignmentValidation
alt validation fails
RefHelper-->>UnityEditor: ErrorResponse(validation.Error)
UnityEditor-->>UnityBridge: error payload
UnityBridge-->>PythonTool: error dict
PythonTool-->>PythonClient: error result
else validation succeeds
RefHelper->>UnityEditor: Undo.RecordObject(component)
RefHelper->>RefHelper: property.objectReferenceValue = ResolvedObject
RefHelper->>RefHelper: serializedObject.ApplyModifiedProperties
RefHelper->>UnityEditor: EditorUtility.SetDirty(component)
RefHelper->>UnityEditor: MarkOwningSceneDirty(targetGo)
RefHelper-->>UnityEditor: success payload with previous_value and new_value
UnityEditor-->>UnityBridge: success payload
UnityBridge-->>PythonTool: success dict
PythonTool-->>PythonClient: success result
end
Updated class diagram for ManageComponents reference wiringclassDiagram
class ManageComponents {
+HandleCommand(@params : JObject) object
-GetReferenceable(@params : JObject, targetToken : JToken, searchMethod : string) object
-SetReference(@params : JObject, targetToken : JToken, searchMethod : string) object
-BatchWire(@params : JObject, targetToken : JToken, searchMethod : string) object
-TryGetComponentAndObjectReferenceProperty(@params : JObject, targetToken : JToken, searchMethod : string, actionName : string, targetGo : GameObject, component : Component, serializedObject : SerializedObject, property : SerializedProperty, expectedType : Type, error : ErrorResponse) bool
-GetFieldType(component : Component, propertyName : string) Type
-ResolveReference(refParams : JObject) UnityEngine.Object
-FindReferenceableSceneObjects(expectedType : Type, limit : int) IEnumerable~object~
-FindReferenceableAssets(expectedType : Type, limit : int) IEnumerable~object~
-BuildAssetSearchFilter(expectedType : Type) string
-LoadReferenceableAssetsAtPath(assetPath : string, expectedType : Type) IEnumerable~UnityEngine.Object~
-ValidateReferenceAssignment(component : Component, propertyName : string, expectedType : Type, refParams : JObject) ReferenceAssignmentValidation
-HasReferenceSelector(refParams : JObject) bool
-ConvertResolvedObject(resolved : UnityEngine.Object, expectedType : Type) UnityEngine.Object
-DescribeObjectReference(obj : UnityEngine.Object) object
}
class ReferenceAssignmentValidation {
-PropertyName : string
-Success : bool
-Error : string
-ResolvedObject : UnityEngine.Object
+Ok(propertyName : string, resolvedObject : UnityEngine.Object) ReferenceAssignmentValidation
+Fail(propertyName : string, error : string) ReferenceAssignmentValidation
}
class BatchWireResult {
+Property : string
+Success : bool
+Error : string
+NewValue : object
+ToResponse() object
}
class GameObjectLookup {
+ResolveInstanceID(instanceId : int) UnityEngine.Object
+FindByTarget(target : JToken, searchMethod : string, includeInactive : bool) GameObject
+GetAllSceneObjects(includeInactive : bool) IEnumerable~GameObject~
+GetGameObjectPath(gameObject : GameObject) string
}
class UnityTypeResolver {
+ResolveComponent(componentType : string) Type
}
class ErrorResponse {
+ErrorResponse(message : string)
+message : string
}
class SerializedObject
class SerializedProperty {
+propertyType : SerializedPropertyType
+propertyPath : string
+objectReferenceValue : UnityEngine.Object
}
class UnityEngine.Object {
+GetInstanceID() int
+name : string
+GetType() Type
}
class Component {
+gameObject : GameObject
+GetComponent(type : Type) Component
}
class GameObject {
+name : string
+GetComponent(type : Type) Component
}
class Undo {
+RecordObject(target : UnityEngine.Object, name : string) void
+GetCurrentGroup() int
+SetCurrentGroupName(name : string) void
+CollapseUndoOperations(group : int) void
}
class AssetDatabase {
+FindAssets(filter : string) string[]
+GUIDToAssetPath(guid : string) string
+LoadAssetAtPath~T~(assetPath : string) T
+LoadAllAssetsAtPath(assetPath : string) UnityEngine.Object[]
+GetAssetPath(obj : UnityEngine.Object) string
}
class EditorUtility {
+SetDirty(obj : UnityEngine.Object) void
}
class SerializedPropertyType {
}
ManageComponents --> ReferenceAssignmentValidation : uses
ManageComponents --> BatchWireResult : uses
ManageComponents --> GameObjectLookup : uses
ManageComponents --> UnityTypeResolver : uses
ManageComponents --> ErrorResponse : returns
ManageComponents --> SerializedObject : uses
ManageComponents --> SerializedProperty : uses
ManageComponents --> Undo : uses
ManageComponents --> AssetDatabase : uses
ManageComponents --> EditorUtility : uses
ManageComponents --> Component : manipulates
ManageComponents --> GameObject : manipulates
ReferenceAssignmentValidation --> UnityEngine.Object : holds
BatchWireResult --> UnityEngine.Object : via NewValue description
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 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. Comment |
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- In
BatchWire, you recreate a newSerializedObjectfor the same component on everyvalidationduring apply; consider constructing it once and reusing it (or using the one fromTryGetComponentAndObjectReferenceProperty-like helper) to avoid unnecessary allocations and simplify the write path. GetFieldTypecurrently only resolves backing fields and will return null for array/list element paths or more complexSerializedPropertypaths; if you intend to support wiring into collection elements, you may want to extend this logic to derive the element type from the property path rather than simple field reflection.- There is some duplication between
SetReferenceand the apply loop inBatchWire(Undo recording,SerializedObject/SerializedPropertyhandling, marking dirty); extracting a shared helper for "apply validated reference to property" would reduce repetition and make future changes to the write semantics less error-prone.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `BatchWire`, you recreate a new `SerializedObject` for the same component on every `validation` during apply; consider constructing it once and reusing it (or using the one from `TryGetComponentAndObjectReferenceProperty`-like helper) to avoid unnecessary allocations and simplify the write path.
- `GetFieldType` currently only resolves backing fields and will return null for array/list element paths or more complex `SerializedProperty` paths; if you intend to support wiring into collection elements, you may want to extend this logic to derive the element type from the property path rather than simple field reflection.
- There is some duplication between `SetReference` and the apply loop in `BatchWire` (Undo recording, `SerializedObject`/`SerializedProperty` handling, marking dirty); extracting a shared helper for "apply validated reference to property" would reduce repetition and make future changes to the write semantics less error-prone.
## Individual Comments
### Comment 1
<location path="MCPForUnity/Editor/Tools/ManageComponents.cs" line_range="719" />
<code_context>
+
+ private static UnityEngine.Object ResolveReference(JObject refParams)
+ {
+ var instanceId = refParams["reference_instance_id"]?.Value<int>();
+ if (instanceId.HasValue)
+ return GameObjectLookup.ResolveInstanceID(instanceId.Value);
</code_context>
<issue_to_address>
**issue (bug_risk):** Use safer coercion for `reference_instance_id` to avoid exceptions on malformed input.
`JToken.Value<int>()` will throw if `reference_instance_id` is present but not a valid int (e.g., string, float, null), and this input comes from an external tool. That means a malformed payload can cause an exception before you can surface a structured validation error. Prefer using `ParamCoercion.CoerceInt(refParams[
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
Hi, can you fix the conflict, and add Python tests and CLI usages? Also this is targeted at the main branch, you should retarget to beta for any PR. Thanks! |
…ce, batch_wire Extends manage_components with 3 new actions for object reference fields: - get_referenceable: list assignable scene objects and project assets for a component's reference field, with type filtering - set_reference: assign an object reference via path, asset path, or instance ID, with SerializedProperty + Undo support - batch_wire: wire multiple references atomically in one call, with validation-first approach and grouped Undo C# uses SerializedObject/SerializedProperty for correct prefab override tracking, dirty state, and Undo. Reference resolution supports scene objects, project assets, and component auto-resolution from GameObjects.
- Extract ApplyReferenceToProperty shared helper to deduplicate SetReference and BatchWire write logic - BatchWire now reuses single SerializedObject instead of recreating per validation entry - ResolveReference uses ParamCoercion.CoerceInt instead of unsafe JToken.Value<int>() to prevent exceptions on malformed input - GetFieldType now handles array/list element paths (e.g., "targets.Array.data[0]") by extracting element type
- Add 4 pytest cases (Server/tests/integration/test_manage_components.py) covering get_referenceable, set_reference (asset_path + clear), and batch_wire. Mocks async_send_command_with_retry; verifies the action and parameter shape sent to Unity. - Document the three new actions in docs/guides/CLI_USAGE.md under Component Operations. - Extend manage_components docstring with examples for the new actions. Note: Undo and prefab-override correctness require a real Unity Editor and are not asserted in Python unit tests.
b110b72 to
ea2ec85
Compare
|
Hi @Scriptwonder — addressed all four points:
Also folded a small docstring polish into the same commit so the in-tool examples cover the new actions too. A note on test scope: Undo correctness and prefab override tracking require a real Unity Editor and are intentionally not asserted in the Python unit tests — they're covered by the SerializedProperty + Undo.RecordObject path on the C# side. Happy to add Editor-side tests under Branch was force-pushed once for the rebase ( |
|
I am working on PR#1097 at the moment, and notice you are using some APIs that are changing and going to be removed in the future. FindObjectsOfType is one of these that is going to be removed in CoreCLR. Try to use UnityFindObjectsCompat in the Codebase to fit the versions, also double check if you are using other deprecated APIs. |
Summary
Extends
manage_componentswith 3 new actions for automating object reference field assignment — the programmatic equivalent of drag-and-drop in the Inspector.New Actions
get_referenceableset_referencebatch_wireExample Usage
Implementation Details
Python (
Server/src/services/tools/manage_components.py):reference_path,reference_asset_path,reference_instance_id,references,clear,atomic,include_scene,include_assets,limitsend_with_unity_instancesame as existing actionsC# (
MCPForUnity/Editor/Tools/ManageComponents.cs):get_referenceable: resolves field type via reflection, searches scene (FindObjectsOfType) and assets (AssetDatabase.FindAssets) for matching typesset_reference: usesSerializedObject+SerializedProperty.objectReferenceValuefor correct prefab override tracking and Undo supportbatch_wire: atomic mode (default) validates all entries first, then applies all writes in a single Undo groupTryGetComponentAndObjectReferenceProperty,ResolveReference,ValidateReferenceAssignmentDesign Decisions
manage_*multi-action patternUndo.RecordObject+ grouped operations for batchGetComponentReference Selectors
reference_pathreference_asset_pathreference_instance_idclear=trueTest plan
get_referenceablereturns correct types for Transform, AudioClip, Material fieldsset_referencewith scene object pathset_referencewith project asset pathset_referencewith instance IDset_referencewithclear=trueset_referencetype mismatch returns errorbatch_wireatomic success (all valid)batch_wireatomic failure (one invalid, none applied)batch_wirenon-atomic partial successSummary by Sourcery
Extend the manage_components tool to support querying and assigning Unity object reference fields, including batch wiring of multiple references.
New Features:
Enhancements: