はじめに
さっきUnityをインストールして環境作ったので、昨日の記事を改めてUnityで実装してみました。
今回も最後に全文のソースコードを載せます。
また、今回掲載するソースは以前掲載した下記記事から一部流用しています。
こちらの記事もよろしくお願いします。
beatdjam.hatenablog.com
前回の記事の内容に合わせて簡単に解説します。
解説
動作のgif
changeDirection
前回の記事で実装したmoveEnemy
がchangeDirection
に対応します。
基本的な考えは変わらず、目標と自分自身の位置の差分を取得し、縮めるように動かすだけです。
ポイントはtransform.rotation
とQuaternion.Euler
ですかね。
transform.rotation
は、オブジェクトから見た相対的な回転ではなく、シーン全体から見た回転量を表します。
インスペクタに出てくるやつですね。
Quaternion.Euler
は、角度をtransform.rotation
に対応した値に変換するメソッドです。
Y軸のみを変えることで正面を常に移動したい方向に向けています。
//playerの座標に応じて向きを変える void changeDirection(GameObject player){ //playerとenemyの座標差分を取得する int xDistance = Mathf.RoundToInt(this.transform.position.x - player.transform.position.x); int zDistance = Mathf.RoundToInt(this.transform.position.z - player.transform.position.z); //向きたい角度 int rotateDir = 0; //x座標,z座標の差分から向きたい角度を取得する //playerとenemyに距離がある場合 if(xDistance == 0){ //x座標が同じ場合z座標のみ向き取得 rotateDir = this.getDirection(zDistance, "z"); }else if(zDistance == 0){ //z座標が同じ場合x座標のみ向き取得 rotateDir = this.getDirection(xDistance, "x"); }else{ //どちらも差がある場合、ランダムで進む向き取得 int rand = UnityEngine.Random.Range (0, 2); if(rand == 0){ //z座標向き取得 rotateDir = this.getDirection(zDistance, "z"); }else{ //x座標向き取得 rotateDir = this.getDirection(xDistance, "x"); } } //取得した方向にオブジェクトの向きを変える this.transform.rotation = Quaternion.Euler (0, rotateDir, 0); }
getDirection
前回の記事で実装したgetMovePos
がgetDirection
に対応します。
こちらは少し見栄えが変わったかなと思います。
渡された軸、距離から、どちらの軸を移動するか、軸に対してマイナス・プラスのどちらに移動するかを算出しています。
0 90 180 270 がそれぞれ4方向に対応しています。
//向きの角度を取得する int getDirection(int distance,string axis){ //距離がプラスかマイナスかを取得 int flag = distance > 0 ? 1 : 0; //角度を返却 if(axis == "x"){ return flag == 1 ? 270 : 90; }else{ return flag == 1 ? 180 : 0 ; } }
おわりに
わからないことがあればまずはググるかUnityのリファレンスを読んでみましょう。
できることや方法、考え方を知ることは、間違いなくプログラマーとしての力につながります。
自分なりに考えてみて、それでもわからなければ、コメント欄等で質問いただければ力になります!
というわけで、次回(があれば)は経路探索についてかけたらいいなと思います。
ソースコードは下記になります。
using UnityEngine; using System.Collections; public class nearTest : MonoBehaviour{ private GameObject nearObj; //最も近いオブジェクト private float searchTime = 0; //経過時間 void Start(){ //最も近かったオブジェクトを取得 this.nearObj = this.serchTag(gameObject, "Player"); } void Update () { //経過時間を取得 this.searchTime += Time.deltaTime; if (this.searchTime >= 1.0f) { //最も近かったオブジェクトを取得 this.nearObj = this.serchTag(gameObject, "Player"); //経過時間を初期化 this.searchTime = 0; //1秒おきに移動 //対象の方向を向く this.changeDirection(this.nearObj); //自分自身の位置から相対的に移動する this.transform.Translate(Vector3.forward * 1.00f); } } //playerの座標に応じて向きを変える void changeDirection(GameObject player){ //playerとenemyの座標差分を取得する int xDistance = Mathf.RoundToInt(this.transform.position.x - player.transform.position.x); int zDistance = Mathf.RoundToInt(this.transform.position.z - player.transform.position.z); //向きたい角度 int rotateDir = 0; //x座標,z座標の差分から向きたい角度を取得する //playerとenemyに距離がある場合 if(xDistance == 0){ //x座標が同じ場合z座標のみ向き取得 rotateDir = this.getDirection(zDistance, "z"); }else if(zDistance == 0){ //z座標が同じ場合x座標のみ向き取得 rotateDir = this.getDirection(xDistance, "x"); }else{ //どちらも差がある場合、ランダムで進む向き取得 int rand = UnityEngine.Random.Range (0, 2); if(rand == 0){ //z座標向き取得 rotateDir = this.getDirection(zDistance, "z"); }else{ //x座標向き取得 rotateDir = this.getDirection(xDistance, "x"); } } //取得した方向にオブジェクトの向きを変える this.transform.rotation = Quaternion.Euler (0, rotateDir, 0); } //向きの角度を取得する int getDirection(int distance,string axis){ //距離がプラスかマイナスかを取得 int flag = distance > 0 ? 1 : 0; //角度を返却 if(axis == "x"){ return flag == 1 ? 270 : 90; }else{ return flag == 1 ? 180 : 0 ; } } //指定されたタグの中で最も近いものを取得 GameObject serchTag(GameObject nowObj,string tagName){ float tmpDis = 0; //距離用一時変数 float nearDis = 0; //最も近いオブジェクトの距離 GameObject targetObj = null; //オブジェクト //タグ指定されたオブジェクトを配列で取得する foreach (GameObject obs in GameObject.FindGameObjectsWithTag(tagName)){ //自身と取得したオブジェクトの距離を取得 tmpDis = Vector3.Distance(obs.transform.position, nowObj.transform.position); //オブジェクトの距離が近いか、距離0であればオブジェクト名を取得 //一時変数に距離を格納 if (nearDis == 0 || nearDis > tmpDis){ nearDis = tmpDis; targetObj = obs; } } //最も近かったオブジェクトを返す return targetObj; } }