How to switch script in editor via code?

You can switch the Unity inspector to debug mode and then drag new scripts into the ‘Script’ slot on any of your components. Your component will then use this new script and also retain all the Serialized values that were on it before.

I want to do this same thing, except via code. I want to switch all the components on a prefab to using a different script, but have those components retained their serialized data.

I was trying to dig through the API with reflection. Unfortunately this m_Script field is not in the MonoBehaviour. Looking through unity decompiled it looks like it is stored in a SelectableEditor class?

This is starting to look like a struggle so I was curious has anyone dug into trying to do this before? Would you mind sharing any insights?

The actual class of a MonoBehaviour is just stored in the serialized data (basically on the native C++ side of Unity). The only way to change it is through the serialization system. That means through SerializedObject and SerializedProperty.

    MonoBehaviour yourScriptInstance;
    MonoScript yourReplacementScript;

    SerializedObject so = new SerializedObject(yourScriptInstance);
    SerializedProperty scriptProperty = so.FindProperty("m_Script");
    so.Update();
    scriptProperty.objectReferenceValue = yourReplacementScript;
    so.ApplyModifiedProperties();

To get the replacement MonoScript reference you can use an editor script and an ObjectField where you could assign the script you want to replace. Alternatively you can use MonoScript.FromMonoBehaviour();. Unfortunately you need an instance of that script in order to use that method. There is no version that directly takes a type reference. So you could do:

    var tmpGO = new GameObject("tempOBJ");
    var inst = tmpGO.AddComponent<YourReplacementScript>();
    MonoScript yourReplacementScript = MonoScript.FromMonoBehaviour(inst);
    DestroyImmediate(tmpGO);

ps: you may need to mark the object as dirty in order to actually apply the change. Editing objects outside of the context of the inspector sometimes behaves a bit strange.

adding scripts is easy as:
gameObject.AddComponent(“name of script”);
it doesnt even need to be in a scene as long as it’s in your asset folder.
to remove one you would say:
Destroy(this);

if you really wanted to move a script to another object without changing current variables I would personally attach it to a child object and have the script address the parent. then all you would do is switch the parenting. I cant think of a practicle reason why you would want to do that though.