Migrating UnityScript code to C#, keeping serialised properties

Here’s an interesting one.

I am currently planning to convert all of my plugins to C#, and here’s the situation:

  • GameObject in scene with component MyClass from the script MyClass.js attached

  • Public variables are set to specific values in the inspector

  • Exit Unity, convert the MyClass.js script to C#, now named MyClass.cs

  • Reopen Unity and FAIL! The component MyClass is no longer attached to the GameObject

  • When reattaching the MyClass component, the inspector values are not restored

I tried serialising the scene file as text-only, mixed and binary to no avail.
As far as I can tell from doing a diff between a scene with MyClass.js and one with MyClass.cs is that the guid of m_Script changed. Would I need to replace the guid somehow?

Thanks in advance!

Actually, I figured out a script to change a reference from a .js script to a .cs one while preserving the properties through the SerialisedObject class. This requires that the .js and .cs are in the same folder, however, and it will cause issues with ambiguous references from other scripts using them. I’ll keep at it and update this script as I progress.

using UnityEngine;
using UnityEditor;
using System.Collections;

public class ScriptMigrator : MonoBehaviour {
   private static void Migrate ( GameObject go, string from, string to ) {
     foreach ( MonoBehaviour c in go.GetComponents(typeof(MonoBehaviour)) ) {
       SerializedObject so = new SerializedObject ( c );
       SerializedProperty prop = so.FindProperty("m_Script");
       object obj = prop.objectReferenceValue;
       MonoScript script = (MonoScript)obj;
       
       string thisAssetPath = AssetDatabase.GetAssetPath ( script );

       if ( thisAssetPath.Contains(from) ) {
         string newAssetPath = thisAssetPath.Replace(from,to);

         if ( System.IO.File.Exists ( newAssetPath ) ) {
           object newObject = AssetDatabase.LoadAssetAtPath(newAssetPath,typeof(object));
           MonoScript newMonoScript = (MonoScript)newObject;

           if ( newMonoScript ) {
             prop.objectReferenceValue = newMonoScript;
             so.ApplyModifiedProperties();
             return;
           }
         }
       }
     }
   }

   [MenuItem ("Debug/Script Migration/UnityScript to C#")]
   public static void MigrateUSToCS () {
     GameObject[] selection = Selection.gameObjects;

     foreach ( GameObject go in selection ) {
       Migrate ( go, ".js", ".cs" );
     }
   }
   
   [MenuItem ("Debug/Script Migration/C# to UnityScript")]
   public static void MigrateCStoUS () {
     GameObject[] selection = Selection.gameObjects;

     foreach ( GameObject go in selection ) {
       Migrate ( go, ".cs", ".js" );
     }
   }
}