Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Is there a better way to rename monobehaviours?

Discussion in 'Scripting' started by frosted, Aug 7, 2015.

  1. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    The process I use for renaming monobehaviours is so terrible that I end up frequently avoiding renaming poorly named behaviours. This kind of thing might sound minor, but good naming is an important tool to avoid code quality deterioration.

    The annoying part is that, most of the time when you want to rename a monobehaviour it's being driven from the code side. So the process is really:
    - In visual studio, decide that a file needs to be changed
    - tab into unity
    - search for the file name (may require upward of 4 clicks and/or typing)
    - rename the file
    - tab into visual studio
    - reload the project change
    - find the new file
    - resharper, rename class and references
    - recompile
    - tab into unity
    - refresh project

    It's also extremely dangerous if you use something like resharper in that a class+file rename from inside visual studio will break all the script references. So a careless change from the visual studio side be very time consuming to deal with.

    There has really gotta be a better way to deal with this, isn't there? Am I the only one that ends up just leaving poorly named monobehaviours around because it's such a pain?

    Is there something like [FormerlySerializedAs("CrappyName")] for classes that I missed?

    Edit: To help clarify
    The problem is not from the code side - automated refactoring and renaming will handle code that needs to be updated. The problem is that unity serializes inspector script references based on a matching filename + class name. Changing the class name from outside of unity will then break all of the script references set within unity's inspector (or file browser in the case of scriptable object).

    Unity does provide a tool for renaming fields, the [FormerlySerializedAs] attribute, but afaik, there is no good way to deal with file/class renames for monobehaviours.
     
    Last edited: Aug 8, 2015
    AlanMattano and vvnurmi like this.
  2. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,984
    Well, ideally, you name things properly from the start. The name should be clean an reflective of what it does. I often stub out most of the structure from the beginning, to try to avoid needing to rename. (though it still happens) ;)

    But, sometimes things do change. If I need to change a class name and it has scene/object references, I'll just duplicate it and rename the copy. Then in inspector, you can just swap the script, and if you haven't changed anything else, the values will persist. Then after I have dealt with scene refs, I'll just do a project wide find and replace as required.
     
    JG-Denver and Iraqi_Pharm like this.
  3. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    Ideally, we as programmers never make mistakes, never write bugs, and never have changing requirements. ;)

    I'm not sure I understand, can you clarify this?

    Let's say there's a monobehaviour being used across 10 different scenes, do you manually go through each scene, find each reference to the script and manually change it??

    If you care about efficiency, you should really use resharper, this process you describe above is ctr r + r, then type new name. Resharper renames the class, file, all references to the class and searches for all strings and variables that contain the class name or a variation and corrects this as well. But renaming references in code isn't the problem - the problem is unity script references don't get updated if you do this, so all your monobehaviour script references (in inspector) will break.

    The best way I have found to deal with this, is to change the file name from unity (this will update unity's internal script reference pointer, so every script reference will be updated to the new file name, unity will tell you the script is missing until you rename the class to match the updated file name) - you then go into the code and do the refactor -> rename. But that process is (as described above) is arduous at best.
     
  4. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,984
    Does VS also handle values and linkage in the inspector? (Serialized data an references)
     
  5. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,984
    Mistakes? Never, not once. Sure, often I have pre-optimized code, and un-documented test cases, but never mistakes or bugs. ;)

    Yea, that is what I mean. Not pretty, but it helps retain that stuff.

    I did once create an editor tool to help with swapping classes and maintaining links/values. Unfortunately, getting all the edge cases and conditions meant I spent more time building it than just doing it manually. I kinda gave up on after that. Mostly now I just try to keep inspector values to bare minimum, or in some cases have the settings as separate struct/class just for a bit more modularity. Not a perfect solution by any means, but generally works most of the time for me.
     
    Walter_Hulsebos and frosted like this.
  6. Kronnect

    Kronnect

    Joined:
    Nov 16, 2014
    Posts:
    2,876
    I'm on Mac and don't use VS but in MonoDevelop you just refactor (rename in this case) the class name and it will take care of the rest, even renaming the file name.

    I would never use replace in files except for very specific cases. It's too risky in complex projects.
     
    Last edited: Aug 8, 2015
    Rodolfo-Rubens likes this.
  7. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,984
    So, it doesn't? I have never used VS, so I have no clue how deep the integration with Unity is.
     
  8. aer0ace

    aer0ace

    Joined:
    May 11, 2012
    Posts:
    1,511
    Could've sworn Unity just picked up the rename change I made in VS2013 and automatically updated the references. I think I just did that a few min ago. Anyway, yeah, I make my change in VS2013 and have Unity pick up the change. I could be wrong, I'll check it later.
     
  9. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,332
    With MonoDevelop at least you must first rename the class file in the project, then open it in MonoDevelop and rename using F2, and it will work exactly as expected. If you don't do the first step then in my experience all script references will be lost and it will show as missing in the inspector.
     
    Walter_Hulsebos likes this.
  10. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,984
    I would, except I don't do windows. ;). I know it's fairly powerful, but not enough to justify taking a hit using a VM. ;)
     
    calmcarrots likes this.
  11. calmcarrots

    calmcarrots

    Joined:
    Mar 7, 2014
    Posts:
    654
    Ah I understand totally. Im going to switch as soon as I have the opportunity. Never going back to windows after my experience! Excited to switch!

    Also, I tested the issue and it works perfectly. It does retain the references in the inspector and everything else. No problems whatsoever.
     
    zombiegorilla likes this.
  12. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,984
    Ah cool, good to know.
     
  13. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    I use Visual Studio + Resharper + UnityVS.

    1) In Visual Studio I hit F2 to rename a class.
    2) Resharper automatically renames the file.
    3) UnityVS tracks .cs file rename and renames the corresponding .cs.meta file.
    4) Unity Editor automatically updates all the references to that .cs script using the info from its .cs.meta file.

    Everything happens automatically except #1.
     
    frosted and aer0ace like this.
  14. darkhog

    darkhog

    Joined:
    Dec 4, 2012
    Posts:
    2,218
    I think most people here miss one important thing: Unity's policy of "Monobehaviour must be named same as the file it's in herpaderp" is utterly stupid. This is not Java. This is C#. If I want to have file named droigohygodfitjohyidftoyijt.cs that contains class diurhgAUNHilrffgdouiOIUJfgojfjuigj (e.g. to confuse people trying to decompile my game), I better be able to.
     
  15. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    Oh wow, so the answer is unityvs!
     
  16. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,984
    Other than being impractical a several levels, it doesn't change anything, the point was about changing class names. It will still break references.
     
  17. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    What version of visual studio and resharper are you using?

    I'm using the ancient visual studio 2010 - even with unity vs installed this fails to update the corresponding meta file.

    I'm also using a fairly ancient version of resharper 6.1.

    Hrm...
     
  18. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    VS 2015, R# 9, UnityVS 2.0
     
  19. delinx32

    delinx32

    Joined:
    Apr 20, 2012
    Posts:
    417
    Right after you rename something in VS a smart tool tip will pop up (in 2013 it's a little rectangle near where you changed a name, in 2015, its a lightbulb in the left margin). If you click it, it will have an option "Rename classA to classB". It will handle all of the references in code, but you have any string literals that contain the name, it cannot handle it.
     
  20. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    This is why string literals are considered evil. Sure they have some uses, but mostly evil.
     
    zombiegorilla likes this.
  21. delinx32

    delinx32

    Joined:
    Apr 20, 2012
    Posts:
    417
    Which is exactly the thought (plus a few curse words) I had earlier tonight when I had to write a bunch of code that looked like this:

    TerrainSmoothIterations = serializedObject.FindProperty("TerrainSmoothIterations");

    instead of this

    TerrainSmoothIterations = serializedObject.FindProperty(x => _target.TerrainSmoothIterations);
     
    Kiwasi likes this.
  22. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    For the record, resharper deals really well with string literals. Not perfectly, but way better than anything else.

    It always struck me as crazy that some c# developers didn't use resharper. Unity even includes resharper attributes, so you can freely use the annotations and stuff.
     
  23. UCh

    UCh

    Joined:
    Nov 18, 2012
    Posts:
    29
    I'm using Consulo for a while now and recently the guy behind added this feature. Consulo (https://github.com/consulo/consulo/wiki/Downloads) is a fork of IntelliJ Community edition with support for C# and Unity 3D. Is really good TBH and the guy behind answer question, add feature and solve bug really fast.

    The feature that he added recently is basically changing the meta file when you use the refactor/rename feature, so no more missing script links, or moving from Unity editor to your IDE just to rename a class. I testes with references inside prefabs and scenes and works like a charm: http://klikr.org/687108c00786eb541ae79c235a1a.gif
     
    sfjohansson likes this.
  24. sfjohansson

    sfjohansson

    Joined:
    Mar 12, 2013
    Posts:
    368
    This works, pretty awesome!! =D I recently moved over to Consulo and already thought it was the best thing since sliced bread...but with this feature ...it's on par with fundamental things like the "wheel"!
     
  25. UCh

    UCh

    Joined:
    Nov 18, 2012
    Posts:
    29
    Here the awesome fact: Couple of days ago, testing the new Monodevelop bundled in Unity 5.3, I find a plugin called Monodevelop.Unity.Refactor that was claiming doing the same, but was not working properly (it fixed the unity side, but without renaming the class inside the file). I contacted with Vistall by mail (for first time) commenting this issue and suggesting that that will be a nice feature to add... next day I got an answer saying that the feature was implemented + the animated GIF. Boom! I really think that we should spread the word, make Consulo more popular, and put some pressure to Unity to support this guy.
     
  26. sfjohansson

    sfjohansson

    Joined:
    Mar 12, 2013
    Posts:
    368
    I totally agree.. he is an awesome guy and we have to spread the word!

    I asked about compatibility with unity 4.x and he did an update straight away and off I was in Consulo Happy Land..

    Having been using monodevelop since unity 3.X, I consider this a significant development and it would be a terrible shame if it doesn't become a permanent alternative for an IDE to use with UNITY.

    Googling around it seem like IntelliJ is considered as being a better IDE than VS by many and as such it should be prime candidate to be supported, especially as it is multiplatform.
     
  27. mbbmbbmm

    mbbmbbmm

    Joined:
    Dec 28, 2013
    Posts:
    59
  28. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,084
    VS2019 solution:

    1. Select class name
    2. Ctrl + R, Ctrl + R and rename (also select "Include strings" if u want to)
    3. Quick action (Ctrl + dot) "Rename file to ..."
     
  29. Lynxed

    Lynxed

    Joined:
    Dec 9, 2012
    Posts:
    121
    Does this break serialized data in 2019? Renaming ScriptableObjects or MonoBehaviours this way in VS 2017 will lead to serialized data loss.
     
  30. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,084
    Just tried one complex class with 20+ references that was also used in prefab and it worked fine.
    Also checked .meta file and VS2019 correctly renamed old one to new one (and guid stayed the same).

    One more nice thing about this method is that VS doesn't need solution reload.

    ^Unity 2019.1.14
     
  31. GameDeveloper1111

    GameDeveloper1111

    Joined:
    Jul 24, 2020
    Posts:
    100
    For a basic version of the task:

    Pure Unity solution (no VS):

    1. Rename class and file name.
    2. Rename meta file name.

    ---

    Problem statement: Renaming a MonoBehaviour without having to manually update the references to the MonoBehaviour in each GameObject Component in the Unity Inspector.

    Assumption: Only Unity Inspector GameObject Components need to be updated.

    Disclaimers:
    1. This worked for me, but I'm new to game development. I'm using Unity 2020.1.10f1 Personal.
    2. I didn't read this thread thoroughly.
     
    Last edited: Nov 18, 2020
    skullthug likes this.
  32. skullthug

    skullthug

    Joined:
    Oct 16, 2011
    Posts:
    202
    GameDeveloper1111's basic solution worked surprisingly great for me in a tricky spot.

    1. I renamed the class using VSCode's Rename Symbol, so it also changes all references to the class in other scripts as well
    2. Renamed the file to match the new class
    3. Rename the meta file to match the new file name

    I made sure to avoid switching to Unity and thus triggering the recompile during these steps, as I was worried it would have ended up discarding serialized data from being a bad transition state. IDK if it was necessary, but worth watching out for.
     
  33. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,797
    Here is a slight optimization on @GameDeveloper1111's process:

    1. In Unity, rename the C# file to the new class name (this will ALSO rename the .meta file, hidden or not)

    2. Doubleclick the renamed C# file to relaunch VS with updated filename in the CSProj files

    3. Use Visual Studio class rename (Refactor -> Rename) to globally rename the class.

    You are done.

    NOTE: you should NOT have any outstanding errors before trying this.

    NOTE: always use source control to revert any mistakes you make. git works great with Unity and best of all... it's FREE!
     
    shaunysaurus, spiritworld and Bunny83 like this.
  34. spiritworld

    spiritworld

    Joined:
    Nov 26, 2014
    Posts:
    29
    Yeah that step 1. is CRITICAL. I used to just "rename symbol" from VS Code first and lastly rename the file, also from VS Code. Big mistake since it will ef up your script references and you gonna have a bad time reassigning them into GameObjects.

    Today first time realized to change class name from Unity first and magic happened. Why did I made things so hard for myself all these years? :confused:

    EDIT: false start, script references were reassigned only in my active scene aaand all other scenes have now missing scripts all over.
     
    Last edited: Apr 17, 2021
  35. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,797
    This seems unlikely. The reason is that scenes and prefabs and any other places in Unity that connect to a scene all do it precisely the same way, via the internal guid contained in the script's .meta file. If it works in one place it would continue to work in any other place.
     
    Kiwasi likes this.
  36. R1PFake

    R1PFake

    Joined:
    Aug 7, 2015
    Posts:
    507
    Are there any plans to improve the process so that Unity finally detects cs file renames from Visual Studio (refactor command) to automatically rename the meta files too like they do if you rename the files directly in Unity?

    I wrote my own file change watcher which does it, it's only a few lines of code but it would be nice if Unity could add official support for this, because every extra step is annoying and this could easily be avoided, maybe make it optional if someone doesn't want to rename the meta file automatically for whatever reason.
     
  37. Serge_Billault

    Serge_Billault

    Joined:
    Aug 26, 2014
    Posts:
    190
    One of the reasons Unity is reluctent to automate files and class names changes is that it does not know if there are unsaved changes in your file on VS side, nor does it know if some others monobehaviours are temporarily there un-commented so as to get VS error checking, and therefore which one is to rename, and which ones are to obliterate, nor does it know if upon changing other scripts where the old class name is to replace if there are unsaved changes. Which can be a problem if the user is a big money maker studio. Let's add that even if Reflectivity allow to check if the new name is not already taken, some studios heavily use scripts generation automation and you could still end up with a name conflict.

    While on the other hand, by not automating it, If the file is only renamed, and hence other dependencies are left untouched (like 36 files referencing the old class name), you still got a chance to choose to not reload just this file in VS and not lose your unsaved changes. In which case Unity is free of the responsability, it's a user decision.


    mono_exemple.jpg
     
    Last edited: Dec 23, 2021
  38. R1PFake

    R1PFake

    Joined:
    Aug 7, 2015
    Posts:
    507
    My post was about automatically changing the meta file name to match the changed cs file name, not the cs file or class name. In this context there would be no issue with unsaved changes in VS, because the meta files are not edited by the user.

    Renaming a file directly inside Unity already changes the meta file name automatically, so what I request is not a new "feature", I only request that renaming a file inside the Unity editor and renaming a file inside VS behave the same way.

    It looks like they already tried implemented some automatic meta file rename detection, but it doesn't work properly, even when using the same rename command inside VS sometimes the meta files are automatically changed and sometimes they don't. I don't know why using the same rename command results in different behaviors, maybe it's just a bug in their implementation.
     
    Last edited: Dec 23, 2021
  39. Serge_Billault

    Serge_Billault

    Joined:
    Aug 26, 2014
    Posts:
    190
    Renaming the metafile? Good lord, no wonder why you have problems I never heard about.
     
  40. marcAKAmarc

    marcAKAmarc

    Joined:
    Dec 16, 2014
    Posts:
    7
    Just wanted to share - right clicking the monobehaviour file in VS and clicking rename, then just pressing enter worked for me. The meta files also were updated.
    I am using:
    -Unity 2021.3.10
    -VS Community 17.3.4
    -Unity Package: Visual Studio Editor 2.0.16 (Not sure if this contributes or not)