質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

1回答

2823閲覧

Unityでコンポーネントを簡単に置き換える方法

yrema

総合スコア286

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2019/05/19 07:54

シーンやプレハブでUnityEngine.UI.Textをアタッチしている部分をすべて
それを継承したMultilingualTextというコンポーネントに置き換えたいのですが、
手動で1つ1つRemoveしてAddしてフォント等の設定を変更して・・と手作業していくしかないのでしょうか。
もっと簡単な方法があれば教えてください。

◆環境
Unity2017 3.1f1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

数が多いと面倒ですし、修正漏れも起こりそうですよね...
EditorUtility.CopySerializedでコンポーネントの設定を書き写すことができるそうですので、これを使って楽ができるんじゃないでしょうか。

プロジェクトに「Editor」フォルダを用意して下記のようなスクリプトを置き...

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using UnityEditor; 5using UnityEditor.AnimatedValues; 6using UnityEngine; 7using UnityEngine.UI; 8 9public class ComponentReplacer : EditorWindow 10{ 11 // ウィンドウを開いたときのデフォルトの置き換え元、置き換え先を変える場合はこの2つを書き換える 12 private static readonly Type DefaultFromType = typeof(Text); 13 private static readonly Type DefaultToType = typeof(MultilingualText); 14 15 private AnimBool showInfo; 16 private string fromTypeString = $"{DefaultFromType.FullName}, {DefaultFromType.Assembly.GetName().Name}"; 17 private string toTypeString = $"{DefaultToType.FullName}, {DefaultToType.Assembly.GetName().Name}"; 18 19 // 「Utility」→「Replace Components」で置き換えウィンドウを開く 20 [MenuItem("Utility/Replace Components")] 21 private static void OpenWindow() 22 { 23 var window = GetWindow<ComponentReplacer>("Replace Components"); 24 window.Show(); 25 } 26 27 // エラーメッセージ表示用のAnimBoolを作成 28 private void OnEnable() 29 { 30 this.showInfo = new AnimBool(true); 31 this.showInfo.valueChanged.AddListener(this.Repaint); 32 } 33 34 private void OnGUI() 35 { 36 using (new EditorGUILayout.VerticalScope()) 37 { 38 // 「From Type」、「To Type」の文字列と対応する型を探す 39 var infoMessage = string.Empty; 40 var infoType = MessageType.None; 41 Type fromType = null; 42 Type toType = null; 43 try 44 { 45 this.fromTypeString = EditorGUILayout.TextField("From Type", this.fromTypeString); 46 fromType = Type.GetType(this.fromTypeString, true); 47 if (!typeof(Component).IsAssignableFrom(fromType)) 48 { 49 // 置き換え元の型がComponentから派生していなければ失敗 50 throw new Exception($"{this.fromTypeString} is not compatible with {typeof(Component)}."); 51 } 52 53 this.toTypeString = EditorGUILayout.TextField("To Type", this.toTypeString); 54 toType = Type.GetType(this.toTypeString, true); 55 if (!fromType.IsAssignableFrom(toType)) 56 { 57 // 置き換え先の型が置き換え元の型から派生していなければ失敗 58 throw new Exception($"{this.toTypeString} is not compatible with {fromType}."); 59 } 60 } 61 catch (Exception exception) 62 { 63 infoMessage = exception.Message; 64 infoType = MessageType.Error; 65 } 66 67 // もしエラーメッセージが出ていたら表示する 68 this.showInfo.target = !string.IsNullOrEmpty(infoMessage); 69 using (var fadeGroup = new EditorGUILayout.FadeGroupScope(this.showInfo.faded)) 70 { 71 if (fadeGroup.visible) 72 { 73 EditorGUILayout.HelpBox(infoMessage, infoType, true); 74 } 75 } 76 77 // 選択されているゲームオブジェクトやそれらの子階層からfromTypeコンポーネントを探し、 78 // 1つ以上見つかって、かつエラーが出ていなければ「Replace」ボタンを使用可能にする 79 var selectedObjects = Selection.gameObjects; 80 var selectedComponents = 81 selectedObjects.SelectMany(gameObject => gameObject.GetComponentsInChildren(fromType)).Distinct(); 82 using (new EditorGUI.DisabledScope((infoType == MessageType.Error) || !selectedComponents.Any())) 83 { 84 if (GUILayout.Button("Replace")) 85 { 86 this.Replace(fromType, toType, selectedComponents); 87 } 88 } 89 } 90 } 91 92 private void Replace(Type fromType, Type toType, IEnumerable<Component> components) 93 { 94 Debug.Log($"{fromType} -> {toType}"); 95 foreach (var component in components) 96 { 97 var gameObject = component.gameObject; 98 Debug.Log($"\t{gameObject.name}"); 99 Undo.SetCurrentGroupName($"Replace Components"); 100 101 // まず元のコンポーネントをゲームオブジェクトごと複製 102 var cloneObject = Instantiate(gameObject, gameObject.transform.parent); 103 var cloneComponent = cloneObject.GetComponent(fromType); 104 105 // 元のコンポーネントは削除し、置き換え先のコンポーネントをアタッチ 106 Undo.DestroyObjectImmediate(component); 107 var newComponent = Undo.AddComponent(gameObject, toType); 108 109 // 複製しておいた元コンポーネントから新しいコンポーネントにデータをコピー 110 EditorUtility.CopySerialized(cloneComponent, newComponent); 111 112 // 複製は不要になったので削除する 113 DestroyImmediate(cloneObject); 114 } 115 } 116}
  • 処理対象のオブジェクトを選択する(複数選択、あるいは親オブジェクトを選択してもけっこうです)。
  • 「Utility」→「Replace Components」で置き換えウィンドウを開く。
  • 「From Type」に置き換え元、「To Type」に置き換え先の型を入力する(完全修飾・アセンブリ名付きでないと型が見つからないという不便な作りですが、そんなに多用するものでもないかと思いますのでご容赦ください...)。
  • 処理対象が1つ以上選択されており、エラーもなければ「Replace」ボタンが使用可能になるのでクリックする。
  • 取り消す場合はメニューの「Edit」→「Undo Replace Components」を実行する。

というのはどうでしょう。

投稿2019/05/19 13:04

Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yrema

2019/05/19 13:20

参考にさせていただきます。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問