- Home /
Adding new script, copying values, removing old script without selecting GO.
Hi, here is my problem. I have old system(script) attached to 300 GO in "random" folders. I need to find all object with this script in my project, add new system(script), copy values from old one to new one and remove old one. Do I have to do it manualy or it is possible to use script?
Are all these objects the same? Sounds like you should be using a prefab.
Why not just update the old script to include new script functionality?
Cause there is a mess and i have 3 scripts doing this same thing. I want to replace them using one script (with a lot of changes, but variables will be the same)
Answer by Scribe · Jan 06, 2015 at 02:49 PM
Hey, here is an Editor script that should do this.
WARNING: I would suggest you thoroughly test this on a small number of assets first to make sure everything is working as you expect. I have tested it somewhat and it seems to be working nicely, but if it goes wrong, you will have permanently changed those assets, possibly even duplicate your project first to make sure you don't loose 300 lots of data!
I will feel very sorry if it goes wrong but I take no responsibility if that happens :D
So create a new C# script named 'ScriptReplacer' and add the code to it. Once it is saved when you click somewhere on the top menu bar it should update to have a drop down called 'EditorUtility' (if it doesn't appear, restart unity).
Click the dropdown and select the (probably) only option 'Script Replacer' and an editor window should show up.
The first (left) object field is the script that you want to change to (I will refer to this as script B), the second object field is the script to copy and then delete (and refer to this as script A).
Once you have selected two scripts you should have a list on the left of the changeable values in B (public variables) and a set of drop-down selections containing the public variables of A and finally a set of text boxes for default values.
You should select from the drop-downs the values you want to set the respective B variable to or select ' use default' to automatically use the value in the default box. ~Hopefully~ it should stop you trying to set a value to an incompatible type, e.g. it should let you set an Int variable in B to a Int of Float variable in A, but it should not let you set an Int to a string.
Once you have set up everything and double-checked what you are setting to what is sensible then hit replace and then yes.
Note: if an object has both script B and A already attached, it will copy the values from A into the existing instance of B and delete the A component
Code:
using UnityEngine;
using UnityEditor;
using System;
using System.Collections;
using System.Reflection;
public class ScriptReplacer : EditorWindow {
static ScriptReplacer window;
static MonoScript oldOriginalScript;
static MonoScript oldReplacerScript;
static MonoScript originalScript;
static MonoScript replacerScript;
System.Type t;
static int GOcount = 0;
static System.Reflection.FieldInfo[] originalVariableList;
static System.Reflection.FieldInfo[] replacerVariableList;
static UnityEngine.Object[] gameobjectList;
static System.Object[] defaultVal;
static int[] replacerIndex;
static string[] replaceOptions;
bool checkPrompt = false;
[MenuItem("EditorUtility/Script Replacer")]
static void OpenScriptFinder(){
window = (ScriptReplacer)EditorWindow.GetWindow(typeof(ScriptReplacer));
}
void OnGUI(){
EditorGUILayout.LabelField(GOcount.ToString() + " script instance(s) to be replaced");
EditorGUILayout.BeginVertical();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.BeginVertical();
oldReplacerScript = replacerScript;
replacerScript = (MonoScript)EditorGUILayout.ObjectField("Use Script", replacerScript, typeof(MonoScript), false);
if(oldReplacerScript != replacerScript){
t = replacerScript.GetClass();
replacerVariableList = t.GetFields(BindingFlags.Instance | BindingFlags.Public);
}
if(replacerVariableList != null){
for(int i = 0; i < replacerVariableList.Length; i++){
EditorGUILayout.LabelField(string.Format("set value of {0} ({1}) in {2} to", replacerVariableList[i].Name, replacerVariableList[i].FieldType.Name, replacerScript.name));
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
EditorGUILayout.BeginVertical();
oldOriginalScript = originalScript;
originalScript = (MonoScript)EditorGUILayout.ObjectField("to replace", originalScript, typeof(MonoScript), false);
if(oldOriginalScript != originalScript){
t = originalScript.GetClass();
gameobjectList = Resources.FindObjectsOfTypeAll(t) as UnityEngine.Object[];
GOcount = gameobjectList.Length;
originalVariableList = t.GetFields(BindingFlags.Instance | BindingFlags.Public);
defaultVal = new System.Object[replacerVariableList.Length];
replaceOptions = new string[originalVariableList.Length+1];
replacerIndex = new int[replacerVariableList.Length];
for(int k = 0; k < originalVariableList.Length; k++){
replaceOptions[k] = (originalVariableList[k].Name + " in " + originalScript.name);
}
replaceOptions[originalVariableList.Length] = "Use default";
}
if(replacerVariableList != null && originalVariableList != null && replacerIndex != null && replaceOptions != null){
for(int j = 0; j < replacerVariableList.Length; j++){
EditorGUILayout.BeginHorizontal();
replacerIndex[j] = EditorGUILayout.Popup(replacerIndex[j], replaceOptions);
if(replacerIndex[j] != originalVariableList.Length){
try{
System.Type oT = originalVariableList[replacerIndex[j]].FieldType;
System.Type rT = replacerVariableList[j].FieldType;
System.Object tester;
try{
tester = Activator.CreateInstance(oT);
}catch{
tester = "";
}
var test = Convert.ChangeType(tester, rT);
}catch{
replacerIndex[j] = originalVariableList.Length;
}
}
EditorGUILayout.LabelField(" or default to ");
if(defaultVal[j] == null){
try{
defaultVal[j] = Activator.CreateInstance(replacerVariableList[j].FieldType);
}catch{
defaultVal[j] = "";
}
}
defaultVal[j] = EditorGUILayout.TextField(defaultVal[j].ToString());
try{
defaultVal[j] = Convert.ChangeType(defaultVal[j], replacerVariableList[j].FieldType);
}catch{
try{
defaultVal[j] = Activator.CreateInstance(replacerVariableList[j].FieldType);
}catch{
defaultVal[j] = "";
}
}
EditorGUILayout.EndHorizontal();
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
if(replacerScript != null && originalScript != null){
if(!checkPrompt){
if(GUILayout.Button("Replace")){
checkPrompt = true;
//Replace();
}
}else{
EditorGUILayout.LabelField("Are you sure you wish to continue? This will permanently change your assets!");
EditorGUILayout.BeginHorizontal();
if(GUILayout.Button("Yes")){
checkPrompt = false;
Replace();
}
if(GUILayout.Button("No")){
checkPrompt = false;
}
EditorGUILayout.EndHorizontal();
}
}
EditorGUILayout.EndVertical();
}
void Replace(){
GameObject[] gos = Resources.FindObjectsOfTypeAll<GameObject>() as GameObject[];
t = originalScript.GetClass();
gameobjectList = Resources.FindObjectsOfTypeAll(t) as UnityEngine.Object[];
GOcount = gameobjectList.Length;
for(int g = 0; g < gos.Length; g++){
GameObject go = gos[g];
if(go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave){
continue;
}
string assetPath = AssetDatabase.GetAssetPath(go.transform.root.gameObject);
if (String.IsNullOrEmpty(assetPath)){
continue;
}
System.Type tOld = originalScript.GetClass();
System.Type tNew = replacerScript.GetClass();
if(go.GetComponent(tOld) == null){
continue;
}
Component cOld = go.GetComponent(tOld);
Component cNew;
if(go.GetComponent(tNew) == null){
cNew = go.AddComponent(tNew);
}else{
cNew = go.GetComponent(tNew);
}
for(int j = 0; j < replacerVariableList.Length; j++){
if(replacerIndex[j] != originalVariableList.Length){
try{
System.Object obj = Convert.ChangeType(originalVariableList[replacerIndex[j]].GetValue(cOld), replacerVariableList[j].FieldType);
replacerVariableList[j].SetValue(cNew, obj);
}catch{
try{
replacerVariableList[j].SetValue(cNew, Activator.CreateInstance(replacerVariableList[j].FieldType));
}catch{}
}
}else{
try{
replacerVariableList[j].SetValue(cNew, defaultVal[j]);
}catch{}
}
DestroyImmediate(cOld, true);
}
}
}
}
Hope that helps and saves some time!
Scribe