When ever you change a C# filename in the Project view you also need to rename the class name inside the file. This has to be done every time a new C# file is created as well which all in all sums up.
I have made an editor script that does this automatically using Unity’s AssetPostprocessor - enjoy:
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text.RegularExpressions;
class AutoRenameClassName : AssetPostprocessor
{
const string cSharpIdentifier = ".cs";
const string preClassName = "public class ";
const string postClassName = " : ";
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
for (int i = 0; i < movedAssets.Length; i++)
{
string fromAsset = movedFromAssetPaths[i];
string toAsset = movedAssets[i];
if (toAsset.EndsWith(cSharpIdentifier) fromAsset.EndsWith(cSharpIdentifier))
{
string oldClassContext = preClassName + GetFileNameOfAsset(fromAsset) + postClassName;
string newClassContext = preClassName + GetFileNameOfAsset(toAsset) + postClassName;
string scriptFileContent = File.ReadAllText(toAsset);
scriptFileContent = Regex.Replace(scriptFileContent, oldClassContext, newClassContext, RegexOptions.IgnoreCase);
File.WriteAllText(toAsset, scriptFileContent);
}
}
AssetDatabase.RefreshDelayed();
}
static string GetFileNameOfAsset(string assetPath)
{
int posOfLastSlash = assetPath.LastIndexOf("/") + 1;
int posOfLastDot = assetPath.LastIndexOf(".");
return assetPath.Substring(posOfLastSlash, posOfLastDot - posOfLastSlash);
}
}
This would only replace the contents within that file itself, right? Any references to the old class name would be broken. It can also give false positives to similarly named classes or variables within that file.
//SomeThing.cs
public class SomeThing : MonoBehaviour {
public SomeThingHelper someThingHelper;
}
//SomeThingHelper.cs
public class SomeThingHelper : MonoBehaviour {
public SomeThing linkedThing;
}
So now I rename SomeThing.cs to OtherThing.cs, and no less than three obvious problems happen:
the reference to SomeThingHelper becomes OtherThingHelper, a class which doesn’t exist
the variable name someThingHelper also becomes OtherThingHelper, because your find/replace is case insensitive
the reference in SomeThingHelper.cs to SomeThing is broken
Worse, these problems are beyond what can be solved by naming the script file back to its old name (at least #2 - seriously, case sensitivity is a GOOD thing here), and if many scripts refer to SomeThing, you are going to have a hell of a time updating them all.
And no, this is not a contrived, extreme example - just a condensed one. I can name half a dozen classes in my current project that would break very, very badly being renamed this way.
OR
You can refactor code in MonoDevelop (and I believe in VS) and it will change all references to that class, and change the filename. Because MD actually understands the code, it won't rename any references that shouldn't be - even classes named the same but in different namespaces will be properly understood. All you have to do is right-click the class name and pick 'rename'.
The downside: Unity won't follow the name change, so you will have to re-assign the script to any prefabs that have that script attached. I would much prefer an editor extension that solves THAT problem than one that proactively and indiscriminately mucks with my script files....
(...which, if I'm not mistaken, is still a problem you'll have to deal with in your script, as well.)
One note: According to my coworker: If you refactor the class name in MD and untick the box to rename the file, then tab back and wait for Unity to compile the script, then rename the script file within Unity, it has a chance to update the metadata and will not break references. (I have not tested this myself.)
@StarManta , linked scripts in Unity is linked by the guid of the script file, not the class name. So as long as the name of the meta file is changed at the same time (ie. a new guid for the “new” renamed script isn’t created), there should be no problem. That’s what’s making your coworkers method work - renaming the script internally in Unity keeps the old guid, while renaming it externally will cause the old meta file to be destroyed, and a new one to be generated.
When I rename a class from inside VS, the script file gets auto-renamed too. This has never broken any script connections for me. I’m not sure why, but I suspect it’s due to VSTools being smart enough to know that if you rename a .cs file, the .cs.meta file should also be renamed. It might also be that Unity notices the file name change in some way, and updates the .meta accordingly. If this is all VSTools, this feature should probably be included in Unity’s MD port.