Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
8
Question by mactyr · Feb 28, 2014 at 05:00 PM · inspectorfieldrename

Rename a field without losing inspector values

Is there any way to rename a field on a component without losing all the values I've set for that field (in the inspector) in all of my scenes?

And/or, is it possible to automate copying of inspector values from one field to another, either in a single scene or across all scenes? This is basically what I've been doing manually (create new field; copy values from old field to new by hand; delete old field). It's quite tedious but wouldn't be so bad if I could automate that middle step!

UPDATE: Nowadays the best way to do this is probably with the FormerlySerializedAs attribute, as noted in Martin Sharkbomb's answer below.

Comment
Add comment · Show 3
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Powdered_sugar · Feb 28, 2014 at 05:21 PM 0
Share

What do you mean by rena$$anonymous$$g a field? Do you mean just changing the variable name in the script? If that's all you're doing then it should keep its value when you change it.

avatar image PAEvenson · Feb 28, 2014 at 05:23 PM 1
Share

Use prefabs. You can easily change the values across all instances of the prefab by changing just the prefab values. As long as they remain synced.

avatar image mactyr · Feb 28, 2014 at 07:48 PM 2
Share

Thanks for the thoughts.

@Powdered_sugar: I can rename a variable and keep a value that's set in the script, but I'm talking about keeping values that were set in the inspector. Those disappear when I change the name of the field in the script. (For understandable serialization reasons, as @chris_taylor points out in his answer.)

@PAEvenson: I don't think prefabs will help here. I'm not trying to change the value across a number of instances of the component, I'm trying to change the name of the field and retain the custom inspector values that were already set.

3 Replies

· Add your reply
  • Sort: 
avatar image
-1
Best Answer

Answer by robertbu · Feb 28, 2014 at 07:47 PM

I don't do much editor scripting, but it sounds like your problem can be solved by an editor script. The process would as follows:

  1. Add the new variable to a script

  2. Modify the editor script to copy that data

  3. Run the editor script on every scene that used that script to copy data from the old variable to the new one.

  4. Disable or modify the editor script (since the variable it references is about to go away)

  5. Delete the old variable.

For example, say a script like this where there was data initialized in the Inspector for the name 'strings' and I wanted to move it to new strings:

 #pragma strict
 
 public var strings : String[]; 
 public var newStrings : String[];

I could use the editor script like the following to move the data (the script must be in the Editor folder and the name must match the class):

 using UnityEditor;
 using UnityEngine;
 
 public class MoveVariableData : EditorWindow {
     [MenuItem("Window/MoveVariableData")]
     public static void ShowWindow() {
         EditorWindow.GetWindow(typeof(MoveVariableData));
     }
     
     void OnGUI() {
         if(GUILayout.Button("MoveData")) {
             DataTest[] dts = Resources.FindObjectsOfTypeAll<DataTest>();
             foreach (DataTest dt in dts) {
                 dt.newStrings = dt.strings;
             }
         }
     }
 }

You could then select 'MoveVariableData' from the Windows menu and click on the button to copy it over. For each script you change, you would need to edit the data type passed to FindObjectOfTypeAll(), and then change what info you copied.

Note I've done very little Editor extension work, so there may be easier or better ways to do what I've outlined.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image mactyr · Mar 02, 2014 at 06:13 AM 0
Share

Ah ha! This is exactly the awesome sauce I was imagining; works great. Thanks so much!

For the record, it works fine in my Scripts folder, there doesn't seem to be any need to put it in an Editor folder.

avatar image mactyr · Mar 02, 2014 at 09:46 AM 0
Share

This needed a bit of tweaking but I think I've got it pretty solid now. The most important adjustment was that a PrefabUtility.RecordPrefabInstanceProperty$$anonymous$$odifications(component) is necessary to make sure changes to instances of prefabs stick. I've also set up a one-click way to apply the copy to all scenes in the Assets/Scenes folder, or you can flip through the scenes and change one at a time.

 using UnityEditor;
 using UnityEngine;
 using System.IO;
 
 public class CopyFieldData : EditorWindow {
     int sceneIndex; // scene to advance to next
 
     [$$anonymous$$enuItem("Window/Copy Field Data")]
     public static void ShowWindow() {
         EditorWindow.GetWindow(typeof(CopyFieldData));
     }
     
     void OnGUI () {
         // If you only want to change scenes that are in your build, you can do this:
         //string[] paths = EditorBuildSettings.scenes.Select(scene => scene.path).ToArray();
         // In my case I have debugging scenes that are not in my build, so I do this ins$$anonymous$$d:
         string[] paths = Directory.GetFiles("Assets/Scenes", "*.unity");
 
         GUIStyle buttonStyle = new GUIStyle(GUI.skin.button);
         buttonStyle.margin = new RectOffset(10, 10, 10, 10);
 
         GUIStyle labelStyle = new GUIStyle(GUI.skin.label);
         labelStyle.wordWrap = true;
 
         GUILayout.Label("Look at CopyFieldData.CopyDataInScene() to see/set what field is being copied on which component.", labelStyle);
 
         if (GUILayout.Button("Save and open " + paths[sceneIndex], buttonStyle)) {
             EditorApplication.SaveScene();
             EditorApplication.OpenScene(paths[sceneIndex]);
             sceneIndex++;
             if (sceneIndex >= paths.Length) {
                 sceneIndex = 0;
             }
         }
 
         if (GUILayout.Button("Copy data in this scene", buttonStyle)) {
             CopyDataInScene();
         }
 
         if (GUILayout.Button("Copy data in ALL scenes", buttonStyle)) {
             if (EditorApplication.SaveCurrentSceneIfUserWantsTo()) {
                 string originalScene = EditorApplication.currentScene;
 
                 foreach (string scene in paths) {
                     EditorApplication.OpenScene(scene);
                     EditorUtility.FocusProjectWindow();
                     CopyDataInScene();
                     EditorApplication.SaveScene();
                 }
 
                 EditorApplication.OpenScene(originalScene);
             }
         }
 
         GUILayout.Label("Scenes Found:\n" + string.Join("\n", paths), labelStyle);
     }
 
     void CopyDataInScene () {
         Debug.Log("Copying data in " + EditorApplication.currentScene);
 
         // Find and replace "Bus" to change the component being worked on
         Bus[] components = Resources.FindObjectsOfTypeAll<Bus>();
         foreach (Bus component in components) {
             // Edit this line to change which field is copied into which
             component.newField = component.oldField;
 
             // The following line is necessary to get changes to instances of
             // prefabs to stick. If it gives you "unsupported type" errors, see:
             // http://answers.unity3d.com/questions/533541/unsupported-type-error-in-custom-editor-script.html
             PrefabUtility.RecordPrefabInstanceProperty$$anonymous$$odifications(component);
         }
     }
 }

   
avatar image Jamora · Mar 02, 2014 at 10:38 AM 1
Share

@mactyr You should place Editor scripts in Editor folders. If you don't, you will not be able to build your game. This is because the UnityEditor namespace is not included in the build, and when attempting to build the game, it'll complain about missing namespaces (UnityEditor).

avatar image mactyr · Mar 02, 2014 at 04:58 PM 0
Share

Oh, I see. Thanks for the clarification!

avatar image adeward · Mar 23, 2018 at 01:17 PM 0
Share

I know I'm 4 years late, but totally this. However, the example code is overkill for most situations.

 [ExecuteInEdit$$anonymous$$ode]
 public class YourBehaviour : $$anonymous$$onoBehaviour {
     public int oldProperty;
     public int newProperty;
     void Update() {
         newProperty = oldProperty;
     }
 }

Return to the Editor, let the code recompile, watch the new properties copy the values of the old properties - you might need to tweak something in the scene to cause Update() to fire. Finally, delete your old properties. Boom, you're done.

avatar image
27

Answer by Democide · Apr 16, 2015 at 01:00 PM

You might want to look into the [FormerlySerializedAs("m_MyVariable")] attribute

Blog: http://blogs.unity3d.com/2015/02/03/renaming-serialized-fields/

API: http://docs.unity3d.com/460/Documentation/ScriptReference/Serialization.FormerlySerializedAsAttribute.html

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image mactyr · Apr 16, 2015 at 06:15 PM 0
Share

Excellent, I wish this had existed when I first asked the question! Thanks for the tip. Seems like this will likely be the best solution for folks using more recent versions of Unity.

avatar image
0

Answer by chris_taylor · Feb 28, 2014 at 05:54 PM

To copy values of a component right click and click copy Component. With the component copied you can now past it as new or past its values into another one of those components.

as far as renaming I assume you are wanting to rename in the script. The problem with keeping the values is to serialization there is no way to tell that the new variable name is the same as it was, I suggest if you found a value you like making it the default when renaming the variable

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image mactyr · Feb 28, 2014 at 07:58 PM 0
Share

Thanks Chris. It sounds like a direct rename might be impossible for serialization reasons, but maybe we can figure out something with the copying.

I don't think your copy component suggestion will help since I'm not trying to copy a component's values into another component, but rather to copy a field's value into another field, for all instances of a component. In other words, let's say in my Car class I have a field speed, I add a field newSpeed, and now I want all instances of newSpeed to have the same inspector values that speed has, for each instance of Car. Let's say I already have many Cars in my scene with speed values customized in the inspector, so copying manually is time consu$$anonymous$$g.

It seems like there ought to be a way to automate this (with an editor script?) but I'm not sure what it is!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

26 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Loss of GO selection 2 Answers

How to make an inspector field that is only set on submit? 0 Answers

Make a field in inspector hold inheriting classes 2 Answers

Insert enum breaking existing inspector values 2 Answers

How to expose a field of type Interface in the inspector? 10 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges