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

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

新規登録して質問してみよう
ただいま回答率
85.35%
継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

Unity

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

Q&A

解決済

1回答

1926閲覧

UnityでInstantiateによる複製をした際、アタッチされたComponent内変数のインスタンス化された派生クラスが、基底クラスにならないようにすることは可能でしょうか?

Tar0u

総合スコア1

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

Unity

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

0グッド

1クリップ

投稿2020/09/27 11:08

編集2020/09/27 11:14

前提・実現したいこと

UnityでInstantiateによる複製をした際、アタッチされたComponent内変数のインスタンス化された派生クラスが、基底クラスにならないようにすることは可能でしょうか?
GameOnjetにアタッチされたObject.csの変数objClassに、SubClassをインスタンス化、代入した後、GameOnjetをInstantiateで複製すると、objClassの中身がBaseClassになってしまいます。

該当のソースコード

C#

1using UnityEngine; 2 3public class Main : MonoBehaviour 4{ 5 public Object obj; 6 void Start() 7 { 8 obj.objClass = new SubClass(); 9 obj.Act(); 10 11 Object dObj = Instantiate( obj ).transform.GetComponent<Object>(); 12 dObj.Act(); 13 } 14} 15 16[System.Serializable] 17public class BaseClass { 18 public virtual void Action() { 19 Debug.Log( "BaseClass" ); 20 } 21} 22 23[System.Serializable] 24public class SubClass : BaseClass { 25 public override void Action() { 26 Debug.Log( "SubClass" ); 27 } 28}

C#

1using UnityEngine; 2 3public class Object : MonoBehaviour { 4 public BaseClass objClass; 5 6 public void Act() { 7 objClass.Action(); 8 } 9}

表示されるメッセージ

SubClass Main:Start() (at Assets/DupricateTest/Main.cs:12) BaseClass Main:Start() (at Assets/DupricateTest/Main.cs:15)

バージョン

Unity 2019.3.2.f1

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

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

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

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

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

guest

回答1

0

ベストアンサー

Instantiateした時にUnityEngine.Objectを継承していない型のフィールドはコピーされるのではなくコンストラクタが呼ばれるようです。なのでObject.objClassをSubClassクラスと認識させるためにジェネリック型で宣言して、それを継承したクラスで型をSubClassに固定します。
また、ObjectクラスはSystem.ObjectやUnityEngine.Objectなどに同名のクラスがあるので別の名前にした方が良いです。

以上を踏まえて以下のように修正してMainクラスのobjをSubObjectに変更するとdObj.objClassもSubClassになります。

csharp

1// SubObject.cs 2using System; 3using UnityEngine; 4 5/// <summary> 6/// ジェネリック型はアタッチできないので継承したクラスを作る 7/// </summary> 8public class SubObject : BaseObject<SubClass> 9{ 10} 11 12/// <summary> 13/// TはBaseClassを継承したクラスに限定する 14/// </summary> 15public class BaseObject<T> : MonoBehaviour where T : BaseClass 16{ 17 public T objClass; 18 19 public void Act() 20 { 21 objClass.Action(); 22 } 23}

投稿2020/09/27 13:59

shiena

総合スコア1827

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

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

Tar0u

2020/09/27 14:40

ご回答ありがとうございます。試してみます。
Tar0u

2020/09/27 15:16

実際に試してみたところ、SubClassの関数が呼ばれることを確認しました。 ただ、この方法ですとSubObjectはSubClassのみにしか対応できず、BaseClassを基底とした別の派生クラスを受け付けません 自分の説明不足で申し訳ないのですが、派生クラスを1つに限定しない方法、実際の運用で言えばBaseClass派生クラスを配列で保持する方法はございますでしょうか?
shiena

2020/09/27 15:37

なるほど。以下の3つくらいしかなさそうです。 1. ObjectクラスのAwakeやStartでobjClass = new SubClass()する 2. MainでInstantiateする度にdObj.objClass = new SubClass()する 3. BaseObjectもMonoBehaviourを継承してobjClassはMainクラスから代入する代わりにInspectorから設定する
Tar0u

2020/09/27 15:57

承知しました。ご考察いただきありがとうございました。 もしかしたら派生クラスを保持する方法が存在するかもしれないので、ベストアンサーの選出は保留とさせてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問