Quick answer: Unity tracks script references by class name + namespace + assembly. Renaming any of these breaks existing references. Use [MovedFrom(...)] from UnityEngine.Scripting.APIUpdating on the relocated class so Unity remaps prefab and scene references automatically.

Here is how to fix Unity prefabs and scenes that show Missing (Mono Script) after you reorganized code into a namespace. The class still exists; the file was not deleted; but every prefab instance now has a stale reference. The fix is the MovedFrom attribute, which lets Unity discover the new home automatically.

The Symptom

You moved PlayerController into namespace Game.Player. Open any prefab using PlayerController; the component shows Missing (Mono Script). The script is fine; new attachments work; only existing references are broken.

What Causes This

Reference key includes namespace. Serialized references use class identity = (assembly + namespace + class name). Changing any one part invalidates existing references.

Different .cs.meta GUID. If you also moved the .cs file, Unity may have generated a new meta GUID, breaking the link.

Editor not aware of move. Unity does not infer renames; it sees only old reference and new class with no link unless you add MovedFrom.

The Fix

Step 1: Annotate with MovedFrom.

using UnityEngine;
using UnityEngine.Scripting.APIUpdating;

namespace Game.Player
{
    [MovedFrom(true, sourceNamespace: "", sourceClassName: "PlayerController")]
    public class PlayerController : MonoBehaviour
    {
        // ...
    }
}

The first parameter is autoUpdateAPI; second is the old namespace (empty string if global); third is the old class name. Reimport prefabs after adding the attribute.

Step 2: Preserve the .cs meta file. Move the file with its .meta sibling. Git: git mv Old.cs Path/New.cs moves both. Avoid deleting and re-creating — that issues a new GUID.

Step 3: For renamed variables, use FormerlySerializedAs.

using UnityEngine.Serialization;

public class PlayerController : MonoBehaviour
{
    [FormerlySerializedAs("speed")]
    [SerializeField] private float moveSpeed = 5f;
}

Unity writes the new field with the old name’s data on next load.

Step 4: For broken existing references, force reimport. Right-click Assets in Project view, choose Reimport All. Unity walks every asset, applies MovedFrom remapping, and saves.

Step 5: Manual recovery (last resort). Open the .prefab in a text editor. Find the broken component:

m_Script: {fileID: 11500000, guid: abc123..., type: 3}
# Replace guid with the GUID from the new script's .cs.meta

Save. Reimport. The component reattaches.

Best Practices Going Forward

Plan namespace organization upfront. Once a class ships in prefabs, every move is a remap migration. Use MovedFrom liberally for any class that lives in serialized data. Keep MovedFrom attributes around for several releases so older saved data continues to load.

“Class identity = assembly + namespace + name. Change any part, MovedFrom records the past, Unity remaps the future.”

Related Issues

For prefab apply problems, see Prefab Apply All. For Prefab Mode save, see Prefab Stage Save.

MovedFrom on the new class. FormerlySerializedAs on renamed fields. References survive moves.