Skip to content

set_property fails with "SerializedProperty not found" for object-reference properties on built-in components (e.g. SpriteRenderer.sprite) #1413

Description

@Terabithian74111

Summary

manage_components (set_property action) fails to set object-reference properties on Unity's built-in components — e.g. SpriteRenderer.sprite — when the value is passed in the documented object form ({"guid": "..."}, {"path": "..."}, etc.), even though the property genuinely exists and is writable. It fails with:

SerializedProperty 'sprite' not found on component 'SpriteRenderer'.

This reproduced consistently across multiple separate calls in our project (setting a sprite on a newly-created SpriteRenderer), and I traced the root cause in the plugin source.

Root cause

In MCPForUnity/Editor/Helpers/ComponentOps.cs, SetProperty tries reflection first, then falls back to SetViaSerializedProperty. For object-reference values passed as a JSON object, the reflection path deliberately bails out early:

if (isJObjectValue && typeof(UnityEngine.Object).IsAssignableFrom(propInfo.PropertyType))
{
    // Let SerializedProperty path handle complex object references.
    return false;
}

...so it defers straight to SetViaSerializedProperty, which looks up the field like this:

SerializedProperty prop = so.FindProperty(propertyName)
                       ?? so.FindProperty(normalizedName);

propertyName/normalizedName here are derived from the public C# property name ("sprite"). That works fine for user-written MonoBehaviour fields, where the serialized field name typically matches the public field name. But Unity's built-in components very commonly back a public property with a differently-named native serialized field — SpriteRenderer.sprite is backed by m_Sprite, not sprite. There's no fallback that tries the m_ + PascalCase convention (or otherwise discovers the real backing field), so FindProperty returns null and the call fails even though the property is real and settable.

I confirmed this is still present on current main (checked ComponentOps.cs there directly) — not something already fixed in a newer version than what we had installed.

This is likely not sprite-specific — I'd expect the same failure for any built-in component's object-reference property passed in object form, wherever the public property name differs from Unity's native serialized field name (e.g. possibly Renderer.sharedMaterial → m_Materials, etc. — untested, but same code path).

Repro

  1. Create a GameObject with a SpriteRenderer via manage_components (add).
  2. Import a sprite asset.
  3. Call manage_components set_property on the SpriteRenderer, property: "sprite", value: {"path": "Assets/Sprites/WhiteSquare.png"} (or {"guid": "..."}).
  4. Observe: "SerializedProperty 'sprite' not found on component 'SpriteRenderer'."

Suggested fix

In SetViaSerializedProperty, before giving up, try Unity's conventional native serialized-field naming pattern as an additional fallback, e.g.:

SerializedProperty prop = so.FindProperty(propertyName)
                       ?? so.FindProperty(normalizedName)
                       ?? so.FindProperty("m_" + char.ToUpperInvariant(propertyName[0]) + propertyName.Substring(1));

(or more robustly, iterate the SerializedObject's top-level properties and match case-insensitively against the property name with/without the m_ prefix stripped — similar in spirit to the existing FindPropertyRelativeFuzzy used for nested properties).

Workaround

Setting the property via execute_code (direct C# assignment, e.g. sr.sprite = AssetDatabase.LoadAssetAtPath<Sprite>(path);) works fine, since it doesn't go through SerializedProperty lookup at all.

Environment

  • MCP for Unity: com.coplaydev.unity-mcp (git dependency, main branch)
  • Unity 6000.3.13f1

Related but distinct issues in the same general area: #765 (array property false-negative "not found", fixed) and #949 (Sprite sub-asset GUID/path resolving to the wrong asset type). Neither covers this specific public-name-vs-native-field-name mismatch.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions