※非常にニュアンスだけのざっくりとしたソースに出来上がり非常に不本意ですが、
やりたい事はこんな感じです
- 敵はジャンプ、歩く、攻撃をランダムに選択
- ランダムに選択されたモーションをプレイヤーに対して行なう
- 方向も変わればオブジェクトの向きも変える
こんな物を書いてみました。
mob_AI
using UnityEngine; using System.Collections; public class mob_AI : MonoBehaviour { public GameObject firePrefab; private int move_type = 0; private Vector3 forward; private bool isIdle = true; private bool isAttack = false; private bool isWalk = false; private bool isJump = false; // JumpParams private float jumpPowor; public float jumpPoworConst = 0.8f; public float jumpGrvity = 0.05f; // Use this for initialization void Start () { } // Update is called once per frame void Update () { //アイドル状態 if(isIdle){ // ランダムでモーション種類基準となる番号を取得 move_type = Random.Range(0, 4); // 歩くフラグが立っていたら }else if(isWalk){ //playerオブジェクトをを取得して向きを決定 GameObject player2 = GameObject.Find("player"); Vector3 forward = player2.transform.position - transform.position; // 向きに対してモーションを行なう&向きも変える if(forward.x > 0){ transform.Translate(Vector3.right * 0.1f); transform.localScale = new Vector3(-2, 2, 2); }else{ transform.Translate(Vector3.left * 0.1f); transform.localScale = new Vector3(2, 2, 2); } return; // ジャンプフラグが立っていたら }else if(isJump){ //ジャンプ力を計算 jumpPowor = jumpPowor - jumpGrvity; transform.Translate(Vector3.up * jumpPowor); //地面に着地したら処理処理終了 if(jumpPowor < 0 && transform.position.y <= 1){ isIdle = true; isJump = false; } return; }else{ return; } //Attack if(move_type == 1){ isIdle = false; isAttack = true; //攻撃オブジェクトを生成 GameObject fire = Instantiate(firePrefab, new Vector3(transform.position.x, transform.position.y - 0.5f, 1), Quaternion.identity) as GameObject; // 攻撃オブジェクトのタグを変える fire.gameObject.tag = "mob"; // 攻撃向きと飛ばす方向を決める GameObject player2 = GameObject.Find("player"); Vector3 forward = player2.transform.position - transform.position; if(forward.x > 0){ fire.gameObject.SendMessage("setDirection", true); transform.localScale = new Vector3(-2, 2, 2); }else{ fire.gameObject.SendMessage("setDirection", false); transform.localScale = new Vector3(2, 2, 2); } //スリープ StartCoroutine("WaitFotAttack"); } // Walk if(move_type == 2){ isIdle = false; isWalk = true; StartCoroutine("WaitFotWalk"); } // Jump if(move_type == 3){ isIdle = false; isJump = true; jumpPowor = jumpPoworConst; } } IEnumerator WaitFotAttack() { yield return new WaitForSeconds(2.0f); isIdle = true; isAttack = false; } IEnumerator WaitFotWalk() { yield return new WaitForSeconds(0.5f); isIdle = true; isWalk = false; } }
こんなかんじですが、
非 常 に 雑 か つ 汎 用 性 の 無 い ソ ー ス !!
認めます。これじゃ正直今後の拡張には一切耐えられないでしょう。
ソースの問題点
モーションの処理を使い回せない
この敵の動きって正直playerと同じなんですよね、この処理をコピーしてるなんてダサすぎです
モーションが増える度にupdate内にソース行が増えていく
今はアイドル状態、攻撃、ジャンプ、歩くの4つの動きなのでまだ良いですけど。
こんなもんをいちいち持っていられません。
playerの向きを取得するのに毎回Findが走る
最初はplayerオブジェクトはメンバにセットされていたのですが、
実際に動かしてみると、最初にソースが読み込まれた時のplayerの位置情報をキャッシュしてしまい、
playerが動いても敵はずっと同じ方向にplayerがいるという認識をしました。
これをなんとかしたかったのですが、方法が見つからず非常に不本意ながらFindしてみました。
次回へ向けての課題
モーションを実行するソースは個別に作る
ただジャンプするというtransformを変更するスクリプトを作り
それを対象のオブジェクトにアタッチするのが普通だと思います。
オブジェクトの可変データに対するアプローチ方法の確立
public GameObject player;
で宣言したデータが可変する場合に毎フレーム毎に最新の情報を取得するのはこれしかできないのか?
をもう少し深く掘り下げたい