【Unity7】キャラクターを動かすための抽象クラス作成【2Dローグライク6】
Unity5.0.0f4 Personal(2015年6月)
前回の続きです〜
今回は移動するオブジェクト、つまりPlayer、Enemy1、Enemy2の3オブジェクトに付けるスクリプトの、継承クラスを書いたMovingObjectスクリプトを作成していきます〜
継承については以下エッセンスをご参照下さい〜
【Unity開発】継承まとめ① 基本編【ひよこエッセンス】 - ひよこのたまご Unity5(C#)でゲーム開発入門
【Unity開発】継承まとめ② virtualとoverride【ひよこエッセンス】 - ひよこのたまご Unity5(C#)でゲーム開発入門
【Unity開発】継承まとめ③ abstract【ひよこエッセンス】 - ひよこのたまご Unity5(C#)でゲーム開発入門
【目標】キャラクターを動かすための抽象クラスを作成する!
2D Roguelike 6 of 14 : Moving Objects - YouTube
①抽象クラスのMovingObjectスクリプト作成
早速ソースを見てみます〜
Startメソッド
まずはStartメソッドにてGetComponentを先に行い、BoxCollider2DとRigidbody2Dをスクリプト内で使い回せるようにしています〜
また、SmoothMovementメソッドで使うinverseMoveTimeを先に計算しておきます〜
MovingObjectスクリプトはAttemptMoveメソッド→Moveメソッド→SmoothMovementメソッドの順番で進んでいるようなので、その順番通りに見ていきましょう〜
AttemptMoveメソッド
AttemptMoveメソッドの修飾子としてvirtualが付いています〜これは継承を意味し、サブクラスに同名のメソッドがある場合、スーパークラスであるこのスクリプトのAttemptMoveメソッドも使えるという意味です〜
使う際には「base.スーパークラスのメソッド名」という形で使います〜
また、メソッド名の右に<T>という文字があります〜
これはジェネリックというC#の機能で、初めは型を決めておかず後から型を指定するという機能です〜指定はサブクラスで行っているので今はまだどんな型が指定されるのかは分かりません〜
が、イメージしやすいように先に言っておきますと、Playerが移動するスクリプトの場合はWall型が、Enemyが移動するスクリプトの場合はPlayer型がこの<T>に入ってきます〜
メソッド内ではまず、RaycastHit2D型の変数hitを作成しています〜
RaycastHit2Dは、Linecastによって取得したオブジェクト情報を保存しておく用の型です〜LinecastはMoveメソッドにて出てきます〜
続いて引数にxDir(移動先x)yDir(移動先y)、変数hitを指定してMoveメソッドを呼び出しています〜
hitの左にoutという文字がついていますが、これは変数情報がメソッドをまたいで保持するという意味です〜今回でいうと、Moveメソッド内で受け取ったオブジェクト情報はAttemptMoveメソッド内でも使えるということです〜
Moveメソッドはbool型の戻り値があるので、bool型のcanMove変数で結果を受け取ります〜trueの時は移動成功、falseの場合は移動失敗です〜
続きを見てみましょう〜hitにオブジェクトが何も入っていない場合はここでメソッド終了です〜
hitに何かオブジェクトが入っていた場合はジェネリックで指定された型(プレイヤーならWall型、EnemyならPlayer型)でGetComponentを行いオブジェクトを使えるようにします〜
canMoveがfalse(移動失敗)で、hitComponentに指定の型のオブジェクトが入っている場合、hitComponentを引数にOnCantMoveメソッドを呼び出します〜
Moveメソッド
Moveメソッドではまず現在地と移動先を求めています〜
続いてLinecastというメソッドを実行して、現在地から目的地までの間に、blockingLayerというレイヤーが指定されているオブジェクトがあった場合、そのオブジェクト情報を取得する処理を行っています〜
Linecastメソッド実行の前でboxCollider情報をOffに、実行後にOnにしているのは、自分自身(PlayerやEnemy)がLinecastに引っかかってしまうのを防ぐためです〜
次の行では、障害物が何も無かった場合に目的地情報(end)を引数に、SmoothMovementメソッドを呼び出しています〜そして、移動が成功したという意味でtrueをAttemptMoveメソッドへ返しています〜
障害物があった場合は移動に失敗したという意味のfalseを返しています〜
SmoothMovementメソッド
続いてSmoothMovementメソッドです〜
まずは2ベクトル間の近接度合いを表す値sqrRemainingDistanceを求めています〜
2ベクトル間の本来の距離を取得する時はmagnitudeという関数を使うのですが、magnitudeは計算が複雑で処理が重く、magnitudeを累乗した値を求めるsqrMagnitudeのほうが格段に処理が軽く、近接度合いをチェックするなら問題も無いため、今回はsqrMagnitudeを使用しています〜
続いてwhile文でループに入っています〜
ループを抜ける条件はEpsilon(ほとんど0に近い数値)よりもsqrRemainingDistanceが小さくなった時です〜ループ内で現在地と目的地はどんどんと近づいていきます〜
while文最初の行にて移動量newPositionを求めるMoveTowardsメソッドを使っています〜
MoveTowardsメソッドは第一引数と第二引数の間で、inverseMoveTime(デフォルトは10) * Time.deltaTime(直近1フレームにかかった時間)分だけ移動しています〜1秒50フレームだった場合は10×(1÷50)=0.2、つまり1フレームに0.2ずつ進む感じです〜
次に、求めた移動量分だけMovePositionメソッドにて移動します〜
最後に移動後の現在地で、再度2点間の近接度合いを求め、1フレーム待ってからwhile文の先頭に戻っている感じです〜
1フレームごとにちょっとずつ目的地に近づいていき、目的地に到達したら移動を終了するというアニメーションが、これで実現されました〜
OnCantMoveメソッド
最後にAttemptMoveメソッドから呼び出されていたOnCantMoveメソッドを見ていきましょう〜
このメソッドにはabstract修飾子がついています〜これは抽象メソッドと言い、メソッドの中身はサブクラスにて書く決まりがあります〜なので、OnCantMoveの解説については後述致します〜
<T>はAttemptMoveメソッドと同様、ジェネリック機能を表します〜こちらもサブクラス側で指定されますので、後述致します〜
今回は抽象クラスの説明であったため実際にキャラクターを動かして確認というわけにはいきませんでしたが、なんとなくキャラクターを動かす感じをイメージして頂けたら、今後スムーズに進められると思います〜
それでは今回はここまでです〜
ありがとうございました〜
【Unity開発7】Unity公式チュートリアル2Dローグライクの導入【2Dローグライク1】
【Unity開発7】アニメーションを作りたい!【2Dローグライク2】
【Unity開発7】Floorやアイテムを作成したい!【2Dローグライク3】
【Unity開発7】床や敵キャラ、アイテム等を自動生成させたい!【2Dローグライク4】
【Unity開発7】BoardManagerを呼び出すGameManagerを作成する【2Dローグライク5】
【Unity開発7】キャラクターを動かすための抽象クラス作成【2Dローグライク6】
【Unity開発7】破壊可能な壁(Wall)を作成したい!【ローグライク7】
【Unity開発7】プレイヤーのアニメーターを設定したい!【ローグライク8】
【Unity開発7】プレイヤー用のスクリプトを設定したい!【ローグライク9】
【Unity開発7】敵キャラクターのスクリプトを作成したい!【2Dローグライク10】
【Unity開発7】敵キャラクターのアニメーターを設定したい!【2Dローグライク11】
【Unity開発7】uGUIでUIの表示とレベル機能を実装したい!【2Dローグライク12】
【Unity開発7】BGMと効果音を付ける【2Dローグライク13】
【Unity開発7】タッチパネルに対応させたい!【2Dローグライク14(Fin)】