みなさんこんにちは🌚
ゴッドイーターが面白くてアニメゲームアプリと全部やってしまっているブルーノです。ディストピア世界って好きなんですよねー。3が楽しみです!
さて今回はスクリプトからのコンポーネントの操作についての基礎を学んでいきたいと思います。コンポーネントといえば、シーン上から追加するには画面上部の[Component]もしくはゲームオブジェクトのインスペクター上の[Add Component]ボタンから追加することができ、目に見えるものからその性質まで色々な機能を持たせることができましたね。
コンポーネントの追加
全てのコンポーネントはUnityEngine.Componentクラスから派生しています。スクリプトを書く際に派生させているMonobehaviourクラスもまたこのComponentクラスから派生しており、スクリプトもコンポーネント(部品)として扱われることを表しています。さて、そのコンポーネントの追加ですが、スクリプトでこれを行うにはAddComponent()メソッドを使用します。
AddComponent()メソッド
public Component AddComponent(Type componentType)
public T AddComponent<T>() where T : Component
一つめのcomponentTypeにはコンポーネントの型を表すTypeオブジェクトを指定します。
二つめは前にやったジェネリックを使って型を指定しています。
dreameaters5239.hatenablog.com
dreameaters5239.hatenablog.com
ジェネリックメソッドは中身の型をメソッド名の<>で表すことで中の同じ名前の部分が全て型パラメータの型になる便利なメソッドでしたね。言葉で今回の例を表すならば「<T>のコンポーネントを追加する」のTの部分に<スクリプトの名前>だったり<摩擦係数の名前>だったりを入れるといったとこでしょうか。
例の上の文は、斜線の部分にコンポーネント名を入力します。また、componentTypeを入力する際は「typeof」キーワードをつけて戻り値はComponent型となります。例をちょっとみてみましょう
今回はスクリプトを二つ用意し、2つめのスクリプトには常にy軸を回転させることしか書いていません。一つめのスクリプトの9行目でまずCubeを生成し、次の10行目でBruno_Script02を追加しています。
くるくる回っていますね。
さて、先ほども言いましたが、AddComponent()メソッドで返される値はComponent型になって返ってきます。もちろんコンポーネントは皆Componet型を基として派生しているので動作上何も問題はありませんが、それを取得したり編集したりする場合その派生先、今回だったらBruno_Script02型として運用できた方が安全性も高まります。型キャストやas演算子を用いて2行で書くこともできますが、ジェネリックを使用すれば一行で収められます。例をみてみましょう。
Bruno_Script02にAnglesプロパティを追加し、回転量をBruno_Script01から設定しています。これができるのもBruno_Script02型として扱っているためその中のAnglesにアクセスできています。ちなみにさっきのメソッドで扱おうとしたら
「Component型にはAnglesなんてものはないよ!」と怒られました。やはり基底クラスの中で探すようですね。。。
コンポーネントの取得
では次にオブジェクトに付いているコンポーネントの取得をしてみます。
コンポーネントの取得はGetComponent()メソッドで行います。
GetComponent()メソッド
public Component GetComponent(Type componentType)
public T GetComponent<T>() where T : Component
AddComponent()メソッドの時の「Add」部分が「Get」に置き換わっただけですね。使い方も同じです。例を書いてみます。
今度はcubeにあるBruno_Script02の情報を取得し、その情報がなければAddComponentで追加するという流れです。
結果は同じですね。
コンポーネントの削除
スクリプトからオブジェクトを削除するにはDestroy()メソッドを使用します。
使い方はゲームオブジェクト編の時と同じです。
dreameaters5239.hatenablog.com
例を作成してみます。
15行目にDestroy()メソッドを作り、5秒後に回転量が格納されているrot変数を削除します。
5秒後に止まりました。
プロパティをエディタから編集
コンポーネントの状態はインスペクターから覗くことができ、変数をpublicにしておけば変数の値をインスペクター上に表示することもできます。しかし参照型のフィールドをpublicにしておくのはどこからでも容易にアクセスできる状態にしてしまうことに他なりません。そこで、privateな変数をインスペクター上に表示して編集できるようにすることができます。そこで使われるのがUnityEngine.SerializeField属性になります。
UnityEngine.SerializeField属性
public sealed class SerializeField : Attribute
また長い名前ですね。使い方の例を載せます。
private変数の手前に[SerializeField]とつけています。
インスペクターから値を入力することで回ります。
これにより、privateな変数である_x, _y, _zがインスペクターに表示されました。紛らわしいのですが、このインスペクターの名前は_(アンダースコア)の後のものを大文字にしているのでこのインスペクターには9行目は表示されていません。アクセッサの仕様ということでしょうか。これで安全性を強化できますね。
必須コンポーネントの指定
では最後に、先ほどやった属性の別のものも重要そうだったのでまとめておきます。
今まで作ったスクリプトの中にも、別のスクリプトが必要なものがいくつもありました。そのスクリプトだけをつけても意味がない場合、もしくは他のコンポーネントが必要な場合、普通であればコンパイルエラーを起こしますよね。その時に何が足りないかがすぐわかると良いですよね。そこで今度はUnityEngine.RequireComponent属性を使うことでそのスクリプトが依存しているコンポーネントを明示することができます。
UnityEngine.RequireComponent属性
public sealed class RequireComponent : Attribute
実際に見てみましょう
Bruno_Script01のクラスよりも頭に[RequiredComponent(typeof(Bruno_Script02))]とありますね。このスクリプトがBruno_Script02に依存していることを表します。そしてBruno_Script02はDebug.Logで"I'm awakend"と言うだけです。
実行するとメッセージが表示されました。さあ本番はここからです。エディタからBruno_Script02を除こうとすると...
Bruno_Script01は02に依存しているため削除できません。と表示されました。こういったゲーム内だけでなく開発側からのサポートをスクリプトから行うこともできるんですね。今回はここまでにしておきます。
いやーどうしても毎回この勉強は記事が長くなりがち&ハテナの山です。最近は講義の方も忙しくなってきて、英語の勉強もしなければならなくなってきました。別に英語は嫌いじゃないんですがどうしても単調になりがちですね。根気のない私にはプログラミングの勉強の方が山あり谷ありで楽しいです😊
今日講義で聞いたのですが、英語の勉強は「将来役立つから」とか「学校で覚えなきゃいけないから」といった直接的な理由だと苦手な人は続かないそうです。そういったときは自分の好きなことに結びつけて考え、実際に活用してみると良いそうです。私だったら洋ゲーに多く触れる、とかスクリプトの理解を容易にする、とかですかね。実際英語が少しできるだけでだいぶ助かってます😀
まーでも勉強をやる理由は自分の世界を広げるために他ならないですよね。自分のしたいことができたとき、自分の中にどれだけあらゆることに知識があるか、見聞があるかでその中身の充実度が変わってきますから。それに大学入るまで気づかないなんて勿体無かった....°(ಗдಗ。)°.