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

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

新規登録して質問してみよう
ただいま回答率
85.36%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

Q&A

解決済

2回答

1419閲覧

Unity(C#)AddComponentを使わずに、クラスを生成しコルーチンを使用する方法

moon_peta

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

0グッド

0クリップ

投稿2020/08/30 22:03

前提・実現したいこと

Unity(C#)で、カードゲームを作っています。
カードの能力(カードを引くなど)をStrategyパターンで実装しました。

AddComponentでカード能力のクラスをアタッチし、コルーチンを動かすような作りになっています。

しかし、1個や2個の能力でしたら問題ないのですが将来的にカードの能力は100を超える可能性もあり、
100個クラスをAddComponentでアタッチするのはおかしな実装なのではないかと思っております。
(おかしくなければ解決です)

そこで、下記のコードでAddComponentが並ばないような実装方法などありますでしょうか?
よろしくお願いします。

該当のソースコード

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using System; 5 6public class AbilityManager : MonoBehaviour 7{ 8 Dictionary<string,AbilityStrategy> strategyDic = new Dictionary<string,AbilityStrategy>(); 9 10 void Start() 11 { 12 // 【該当箇所】能力が1つ増えるごとにここのAddComponentが増えていきます…… 13 AbilityDraw ad = gameObject.AddComponent<AbilityDraw>(); 14 strategyDic.Add("draw", ad); 15 } 16 17 /// <summary> 18 /// アビリティを実行する 19 /// <summary> 20 /// <param name="ability">アビリティが書かれた文字列</param> 21 /// <param name="param">アビリティのパラメータ</param> 22 /// <param name="card">使用カード</param> 23 public IEnumerator RunAbility(string[] ability, string[] param, CardController card){ 24 bool isPlayer = GameManager.instance.IsPlayerTurn; 25 // 省略 26 27 // アビリティを実行する 28 int i = 0; 29 foreach(string abl in ability){ 30 if(abl != null && abl != ""){ 31 yield return StartCoroutine(strategyDic[abl].AbilityInterface(param[i],isPlayer)); 32 } 33 i++; 34 } 35 36 // 省略 37 } 38}

C#

1using UnityEngine; 2using System.Collections; 3using System.Collections.Generic; 4 5abstract public class AbilityStrategy : MonoBehaviour 6{ 7 public abstract IEnumerator AbilityInterface(string param,bool isPlayer); 8}

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class AbilityDraw : AbilityStrategy 6{ 7 public AbilityDraw() 8 { 9 } 10 11 public override IEnumerator AbilityInterface(string param,bool isPlayer) 12 { 13 yield return StartCoroutine(DrawHand(int.Parse(param),isPlayer)); 14 } 15 // DrawHandの中身は省略 16}

試したこと

AbilityManagerのStart()で、
strategyDic.Add("draw", new AbilityDraw());
と書いたところ、MonoBehaviourを継承したクラスをnewしてはいけません、
と警告された上にnullが返ってきてしまうためコルーチンが実行できませんでした。

AddComponentを使いなさいとも警告に出ていたので、ほかに方法はないのかもしれませんが……

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

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

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

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

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

guest

回答2

0

ベストアンサー

AbilityStrategyクラスがMonoBehaviourクラスを派生しなければいいのでは?

StartCoroutineMonoBehaviourのメソッドなのでMonoBehaviourを継承したクラスに対して呼び出す必要がありますが、コルーチン自体は別にどのクラスだろうが関係ありません。

投稿2020/09/01 11:31

katsuko

総合スコア3536

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

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

moon_peta

2020/09/01 13:07

ありがとうございます! AbilityStrategyクラスがMonoBehaviourクラスを派生しないようにしたところ、 AbilityDrawのAbilityInterfaceでStartCoroutineを使用していたため、エラーは出たのですが、 そもそもなぜ、AbilityInterfaceをStartCoroutineで呼び出したあとに、さらに AbilityDrawのAbilityInterfaceでStartCoroutineを呼び出しているのだろう? という自分の実装の変な箇所に気づき、AbilityInterfaceの中にあったStartCoroutineを外したところ 無事、動作することができました。 この方法ですとコンポーネントを追加していくことがなくなるため、 ベストアンサーとさせていただきます。 また、私のコードの中に不必要なStartCoroutine(AbilityInterfaceの中にあったStartCoroutine)も入っていて、 回答者の方にはご迷惑をおかけしました。 どうもありがとうございました!
guest

0

1つのGameObjectに大量にAddComponentするのではなく、以下のようにPrefab化するのはどうでしょうか?

  1. AbilityDrawをアタッチしたGameObjectをPrefabにする
  2. AbilityManagerにフィールドを追加してInspectorからPrefabを入れる
  3. RunAbility内のループでInstantiate、GetComponent<AbilityDraw>、StartCoroutineする

投稿2020/08/31 21:19

shiena

総合スコア1827

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

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

moon_peta

2020/09/01 13:01

ありがとうございます! もう一つ回答いただいた、MonoBehaviourを継承しない、という方法が うまくいきそうなため、MonoBehaviourを継承しない方法で進めていこうと思いますが、 Prefab化という発想がなかったため、とてもためになりました。
shiena

2020/09/01 13:37

補足するとカードゲームという事で、カードの画像とAbilityDrawがアタッチされたPrefabをイメージしたものでカード削除する時も Destroy(gameObject); で済むので楽そうという考えでした。ぜひやりやすい方法で進めてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問