dagochan
(dagochan)
1
初心者の質問です。
パブリックな配列を参照してアクタをスポーンしているのですが、そのあとにAdd Impulseのターゲットピンへつなぐにはどうしたらよいのでしょうか? 次のようにしようとしたところ、ターゲットピンにつなげることが出来なくなり、エラーが出てしまいました。
ちなみに、スポーンアクターのClassへ、配列を介さずに直接入れた場合はちゃんとつながります。
Unityのある参考書のサンプルを参考にUE4で作ろうとしています。
未熟な質問で恐縮ですが、どなたかご教授くださいませんか。
Chori
(Chori)
2
結論だけ先に言いますと、Spawn Actor from Class ノードの仕様で「ノード内に直接クラスを指定した場合は戻り値の型が自動でその指定した型に変わりますが、外部から指定した場合は型が判別できずシンプルに Actor 型になる」という特性があります。
※特性というか対応しきれていないというか・・・
つまり、画像1枚目は戻り値が Actor 型になっていて、いわゆる CandyBlueBP の基底クラスが返ってきている状態なので、そのままでは StaticMeshComponent にはアクセスできないという状況ですね。
単に解決するだけであれば Cast ノードを使い、CandyBlueBP に変えてあげれば1枚目と同様の処理が可能になります。
dagochan
(dagochan)
3
Choriさんお忙しい中、ご回答ありがとうございます。
Castノードを用いてCandyBlueBPに変えるというのは次のような処理でよろしいでしょうか?
確かに、この方法でCandyBlueBPをインパルスへ送ることは可能ですが、スポーンアクターの前にある
配列には、色違いの他のCandy XXX BPが入ってくる可能性があるのです。そうなったときにCastTo~の
対象を動的に変化させるようなことは可能ですか?
もしくは、また別のアプローチを考えるべきでしょうか。。
よろしければ、再度お知恵を貸していただければ幸いです。
Chori
(Chori)
4
「色違いの他のCandy XXX BP」ということは、色別にクラスを分ける実装を想定されているという事ですね。
そこまで具体的に考えているのであれば、実装する上でいくつかの選択肢が浮かんできます。
- Candy XXX BP の共通の基底クラスを作成し、StaticMeshComponent を取得する仮想関数を用意する
- Candy XXX BP の共通の基底クラスを作成し、Add Impulse を実行する仮想関数を用意する
上記のように共通の基底クラスを設けるならば、キャストする時にその基底クラスを指定すれば、同じ処理で異なるオブジェクトにそれぞれの振る舞いを実装できますね。
C++であれば、BlueprintImplementableEvent か BlueprintNativeEvent と検索してもらえればやり方が出てきます。
ブループリントのみならば、クラスのメンバ関数は全て仮想関数となっているので、基底クラスを設けることで多くは解決できると思います。
プログラム経験がなく難しいと感じる場合は、以下のリンクの下部にオブジェクト思考のサンプルプロジェクトがあります。
https://answers.unrealengine.com/questions/753210/ウィシェットを切り替える.html
また、UE4 のインターフェースという機能を使って表現することもできます。
Unreal Engine のインターフェース | Unreal Engine 5.1 ドキュメント
盛りだくさんで混乱してしまうかもしれませんが「共通の処理で異なる振る舞いをする」という考え方はゲーム開発を円滑に進める部分において大事なことなので、焦らずゆっくりじっくり勉強して挑んでもらえればと思います。
まずはリンク先のプロジェクトを開いて、どんな実装をしているか確認してもらえると良いと思います。
dagochan
(dagochan)
5
Choriさん、丁寧に質問に答えてくださって本当にありがとうございます。
初心者なだけに共通の基底クラスを作成するという発想が無かったです。
これらをヒントに何かしら発展出来そうな気がしてきました。
この問題を解決出来るか、自分の中で消化出来れば必ずRESOLVEDを押しに来るので、
もう少し試行錯誤させてください。
Chori
(Chori)
6
オブジェクト思考→オブジェクト指向、こちら誤字です。失礼しました。
手引きのヒントになればですが・・・
一般的にこのようなクラス設計を「多態性がある」「多態性を得る」みたいな用語で語っていたりします。
先ほど書いたように「共通の処理で異なる振る舞いをする」という読んで字のごとくですね。
class CandyBase{
virtual void DoAction() = 0; // 何かアクションしてください
};
class CandyBlue : public CandyBase{
void DoAction()override{ 青く光った後に壊れます; }
};
class CandyRed : public CandyBase{
void DoAction()override{ 赤く光りながら消えていきます; }
};
上記はプログラムにした時の実装イメージです。
今回はこの CandyBase という基底のクラスをブループリントで作ってみましょう、という感じですね。
考え方はこのゲームエンジンだけでなく、プログラムやスクリプトのありとあらゆる場面で活かすことができます。
良いきっかけだと思いますので、サンプルを参考にモノにしてもらえればと。
dagochan
(dagochan)
7
すみません、あれからいろいろゴチャゴチャ考えていまだうまくいってないのですが、
ぼくは基底クラスというものも、ちゃんと理解出来てない気がしてるんですが
コンテンツブラウザから新たにブループリントクラスを作るときに親クラスを指定しますよね、
ぼくはあの親クラスのことを基底クラスなんだと思い込んでいたんですが、
それは間違った認識なんでしょうか。。
Chori
(Chori)
8
その認識で大丈夫です。
呼び方の方言程度のものですね。
では仮想関数とかいう難しそうなものはひとまず忘れてもらって、簡単な解決方法を紹介します。
- Actor を親にして新規ブループリントを作成
- 名前は CandyBaseBP としておきましょう。
- その CandyBaseBP を開き、StaticMeshComponent を追加します。
コンポーネントには何も設定しなくて良いです。
- また新規にブループリントを作成し、今度は親を CandyBaseBP にしましょう。
- そのブループリントを開き、StaticMeshComponent に何らかのメッシュを設定します。
これだけでもう準備は完了です。
いくつかの種類が必要なら 4 と 5 を繰り返しましょう。
本回答の先頭内容を改めて確認してもらって、SpawnActor の戻り値を CandyBaseBP にして処理を組み込んでみましょう。
配列も同然 CandyBaseBP クラスの配列にしてみましょう。
これで全ての目的が達成できるかと思います。
dagochan
(dagochan)
9
Choriさん、何度も丁寧に教えていただき本当にありがとうございます。
上記の教えていただいた方法で一連の流れを作り直してみました。
今回はCandyBaseBPを発射位置とし、冒頭と同様の流れを作りました。最初と変更した部分は
CandyBaseBPクラスで配列を作って、その配列の長さを取得してからランダムにインデックスを
決め、そこで選定されたアクターがスポーンされるような流れにしました。
ただ、そこまではいいのですが、インパルスに送る道中でうまくいってないようで、
飛んでくれません。なかなかうまくいかないものですね。。
それと、いままでビューのSSを全く載せていなかったですね。すみません。
手前に配置した白い球はCandyBaseBPで、今回はこれの位置から配列に入れたCandy数個を
ランダムに選定し、ステージに向けて飛ばすようなものです。
Chori
(Chori)
10
CandyBaseBP が発射台になってしまっている事から、まだ理解しながら組み込んでいる感じではないようです。
急がば回れとなりますが、投稿者さんはまずUE4のチュートリアルをこなすことをオススメします。
Unreal Engine のブループリント ビジュアル スクリプティング | Unreal Engine 5.1 ドキュメント
最短の学習方法としてはBlueprint入門から、特にクラスという概念をより真剣に学び、インターフェースという項目が理解できるようになれば、この手の実装は自然と頭に浮かんでくるようになります。
ひとまず本件は一番最初にお伝えしたキャストの方法で解決はできます。
分からないまま組み込んでしまい別の問題が発生している状況ですので、問題の切り分けをするためにもまず本題だけを片付ける事としましょう。
チュートリアルを一通りさらい、ご自身が「正しいと思って実装してみたが意図した動作ができない」時に、また AnswerHUB を利用いただくと、より質の高い質問と、質の高い回答が得られるかと思います。
dagochan
(dagochan)
11
そうですね。
Choriさんのおっしゃる通り、自分でも基礎的な部分がまだ及んでない気がします。
実際、一番最初はShooterという発射台専用のクラスを用意して、
それに変数や配列の定義をしていたんですが、よりシンプルにしようとした結果、
今回はこれを、取り除いていました。
他のCandyの基となるCandyBaseBPを発射台として利用するのは、なんとなく違
和感を感じていたことは事実なのですが、ただその違和感を説明できないのが
今の自分のレベルなんですよね。。
おそらく理解出来てる人がChoriさんの説明を読めば解決できる問題なのだと思いま
すので、ここはひとまずRESOLVEDとさせていただくことにします。
今回は勉強の仕方まで教えていただき、本当にありがとうございました。
もっと基礎を固めてから問題にぶち当たったら、また質問させてくださいね!