ブルーノのC#プログラミング & unity勉強日記

プログラミング素人、ブルーノの自主勉強ノートです。他のプログラミングを勉強したい方の助けになれば幸いです。その他趣味の雑記もしていきたいです

Unityスクリプト / コンポーネント編

f:id:covory10101101276:20180410215406j:plain

ケルン大聖堂

みなさんこんにちは🌚

ゴッドイーターが面白くてアニメゲームアプリと全部やってしまっているブルーノです。ディストピア世界って好きなんですよねー。3が楽しみです!

 

さて今回はスクリプトからのコンポーネントの操作についての基礎を学んでいきたいと思います。コンポーネントといえば、シーン上から追加するには画面上部の[Component]もしくはゲームオブジェクトのインスペクター上の[Add Component]ボタンから追加することができ、目に見えるものからその性質まで色々な機能を持たせることができましたね。

f:id:covory10101101276:20180411073906p:plain

f:id:covory10101101276:20180411073914p:plain

 

コンポーネントの追加

全てのコンポーネント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型となります。例をちょっとみてみましょう

f:id:covory10101101276:20180418102916p:plain

f:id:covory10101101276:20180418102921p:plain

今回はスクリプトを二つ用意し、2つめのスクリプトには常にy軸を回転させることしか書いていません。一つめのスクリプトの9行目でまずCubeを生成し、次の10行目でBruno_Script02を追加しています。

f:id:covory10101101276:20180418104419p:plain

くるくる回っていますね。

さて、先ほども言いましたが、AddComponent()メソッドで返される値はComponent型になって返ってきます。もちろんコンポーネントは皆Componet型を基として派生しているので動作上何も問題はありませんが、それを取得したり編集したりする場合その派生先、今回だったらBruno_Script02型として運用できた方が安全性も高まります。型キャストやas演算子を用いて2行で書くこともできますが、ジェネリックを使用すれば一行で収められます。例をみてみましょう。

f:id:covory10101101276:20180418110149p:plain

f:id:covory10101101276:20180418110200p:plain

Bruno_Script02にAnglesプロパティを追加し、回転量をBruno_Script01から設定しています。これができるのもBruno_Script02型として扱っているためその中のAnglesにアクセスできています。ちなみにさっきのメソッドで扱おうとしたら

f:id:covory10101101276:20180418110445p:plain

「Component型にはAnglesなんてものはないよ!」と怒られました。やはり基底クラスの中で探すようですね。。。

 

コンポーネントの取得

では次にオブジェクトに付いているコンポーネントの取得をしてみます。

コンポーネントの取得はGetComponent()メソッドで行います。

GetComponent()メソッド

public Component GetComponent(Type componentType)

public T GetComponent<T>() where T : Component

AddComponent()メソッドの時の「Add」部分が「Get」に置き換わっただけですね。使い方も同じです。例を書いてみます。

f:id:covory10101101276:20180418113958p:plain

今度はcubeにあるBruno_Script02の情報を取得し、その情報がなければAddComponentで追加するという流れです。

f:id:covory10101101276:20180418114256p:plain

結果は同じですね。

 

コンポーネントの削除

スクリプトからオブジェクトを削除するにはDestroy()メソッドを使用します。

使い方はゲームオブジェクト編の時と同じです。

 

dreameaters5239.hatenablog.com

 例を作成してみます。

f:id:covory10101101276:20180418153052p:plain

15行目にDestroy()メソッドを作り、5秒後に回転量が格納されているrot変数を削除します。

f:id:covory10101101276:20180418153203p:plain

5秒後に止まりました。

 

プロパティをエディタから編集

コンポーネントの状態はインスペクターから覗くことができ、変数をpublicにしておけば変数の値をインスペクター上に表示することもできます。しかし参照型のフィールドをpublicにしておくのはどこからでも容易にアクセスできる状態にしてしまうことに他なりません。そこで、privateな変数をインスペクター上に表示して編集できるようにすることができます。そこで使われるのがUnityEngine.SerializeField属性になります。

UnityEngine.SerializeField属性

public sealed class SerializeField : Attribute

また長い名前ですね。使い方の例を載せます。

f:id:covory10101101276:20180418183137p:plain

private変数の手前に[SerializeField]とつけています。

f:id:covory10101101276:20180418183553p:plain

インスペクターから値を入力することで回ります。

f:id:covory10101101276:20180418184256p:plain

これにより、privateな変数である_x, _y, _zがインスペクターに表示されました。紛らわしいのですが、このインスペクターの名前は_(アンダースコア)の後のものを大文字にしているのでこのインスペクターには9行目は表示されていません。アクセッサの仕様ということでしょうか。これで安全性を強化できますね。

 

必須コンポーネントの指定

では最後に、先ほどやった属性の別のものも重要そうだったのでまとめておきます。

今まで作ったスクリプトの中にも、別のスクリプトが必要なものがいくつもありました。そのスクリプトだけをつけても意味がない場合、もしくは他のコンポーネントが必要な場合、普通であればコンパイルエラーを起こしますよね。その時に何が足りないかがすぐわかると良いですよね。そこで今度はUnityEngine.RequireComponent属性を使うことでそのスクリプトが依存しているコンポーネントを明示することができます。

UnityEngine.RequireComponent属性

public sealed class RequireComponent : Attribute

実際に見てみましょう

f:id:covory10101101276:20180418190702p:plain

f:id:covory10101101276:20180418190712p:plain

Bruno_Script01のクラスよりも頭に[RequiredComponent(typeof(Bruno_Script02))]とありますね。このスクリプトがBruno_Script02に依存していることを表します。そしてBruno_Script02はDebug.Logで"I'm awakend"と言うだけです。

f:id:covory10101101276:20180418191030p:plain

実行するとメッセージが表示されました。さあ本番はここからです。エディタからBruno_Script02を除こうとすると...

f:id:covory10101101276:20180418191043p:plain

Bruno_Script01は02に依存しているため削除できません。と表示されました。こういったゲーム内だけでなく開発側からのサポートをスクリプトから行うこともできるんですね。今回はここまでにしておきます。

 

いやーどうしても毎回この勉強は記事が長くなりがち&ハテナの山です。最近は講義の方も忙しくなってきて、英語の勉強もしなければならなくなってきました。別に英語は嫌いじゃないんですがどうしても単調になりがちですね。根気のない私にはプログラミングの勉強の方が山あり谷ありで楽しいです😊

今日講義で聞いたのですが、英語の勉強は「将来役立つから」とか「学校で覚えなきゃいけないから」といった直接的な理由だと苦手な人は続かないそうです。そういったときは自分の好きなことに結びつけて考え、実際に活用してみると良いそうです。私だったら洋ゲーに多く触れる、とかスクリプトの理解を容易にする、とかですかね。実際英語が少しできるだけでだいぶ助かってます😀

まーでも勉強をやる理由は自分の世界を広げるために他ならないですよね。自分のしたいことができたとき、自分の中にどれだけあらゆることに知識があるか、見聞があるかでその中身の充実度が変わってきますから。それに大学入るまで気づかないなんて勿体無かった....°(ಗдಗ。)°.