Enemyの行動AI

GameManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
public static GameManager instance;
BoardManager boardManager;
public bool playerTurn = true;
public bool enemyTurn = false;
public int Level = 1;
private bool doingSetup;
public Text levelText;
public GameObject levelImage;
public int foodPoint = 100;
private List<Enemy> enemies; //Enemyを管理するリスト作成
private void Awake()
{
if(instance == null)
{
instance = this;
}
else if(instance != this)
{
Destroy(gameObject);
}
DontDestroyOnLoad(gameObject);
enemies = new List<Enemy>();//リストのインスタンス化
boardManager = GetComponent<BoardManager>();
//Map生成
InitGame();
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
static public void Call()
{
SceneManager.sceneLoaded += OnSceneLoded;
}
static private void OnSceneLoded(Scene next,LoadSceneMode a)
{
instance.Level++;
instance.InitGame();
}
public void InitGame()
{
doingSetup = true;
levelImage = GameObject.Find("LevelImage");
levelText = GameObject.Find("LevelText").GetComponent<Text>();
levelText.text = "Day:" + Level;
levelImage.SetActive(true);
Invoke("HideLevelImage", 2f);
enemies.Clear();//リストの初期化(次のシーンにEnemyを持ち越させないため)
boardManager.SetupSecene(Level);
}
public void HideLevelImage()
{
levelImage.SetActive(false);
doingSetup = false;
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(playerTurn || enemyTurn || doingSetup)
{
return;
}
//エネミー関数
StartCoroutine(MoveEnemies());
}
public void AddEnemy(Enemy script)//リストにenemyを追加する関数
{
enemies.Add(script);//Addで引数をリストに追加
}
IEnumerator MoveEnemies()
{
enemyTurn = true;
yield return new WaitForSeconds(0.1f);
if(enemies.Count == 0)//リストの要素数が0か確認する(Enemyがいないかどうか)
{
yield return new WaitForSeconds(0.1f);//いなくてもディレイを行う
}
for(int i = 0; i < enemies.Count; i++)//リストの要素数分ループを回す
{
enemies[i].MoveEnemy();//enemyを動かす
yield return new WaitForSeconds(0.1f);//1体ごとにディレイを行う
}
enemyTurn = false;
playerTurn = true;
}
public void GameOver()
{
levelText.text = "GameOver";
levelImage.SetActive(true);
enabled = false;
}
}

PR

Enemy

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour//Playerと同じ個所はコメントを割愛します
{
public bool isMoving = false;
private BoxCollider2D boxCollider2;
public LayerMask blockingLayer;
public int attackDamage = 1;
private Animator animator;
private Transform target;//playerのポジションを格納する変数
private bool skipMove = false;//enemyのターンをスキップさせる関数
// Start is called before the first frame update
void Start()
{
GameManager.instance.AddEnemy(this);//リストに登録
boxCollider2 = GetComponent<BoxCollider2D>();
animator = GetComponent<Animator>();
target = GameObject.FindGameObjectWithTag("Player").transform;//タグからプレイヤーを判定し、位置情報を取得
}
// Update is called once per frame
void Update()
{
}
public void MoveEnemy()//Player追跡AI
{
if(!skipMove)//動けるターンか確認
{
skipMove = true;//次のターンは動けないようにする
int xDir = 0;//enemyを動かす数値を格納する変数
int yDir = 0;//enemyを動かす数値を格納する変数
if(Mathf.Abs(target.position.x - transform.position.x) < float.Epsilon)//x軸の差を求め、イプシロン(ほぼ0)と比較
{
yDir = target.position.y > transform.position.y ? 1 : -1;//y軸の判定を行い、playerが高い位置にいれば変数に1,低ければ-1が入る
}
else
{
xDir = target.position.x > transform.position.x ? 1 : -1;//x軸の判定を行い、playerが高い位置にいれば変数に1,低ければ-1が入る
}
ATMove(xDir, yDir);//上記の判定で取得した数値を引数にATMoveを呼ぶ
}
else//動けなかったとき
{
skipMove = false;//次のターンは動けるようにfalseに
}
}
public void ATMove(int x, int y)
{
RaycastHit2D hit;
bool canMove = Move(x, y, out hit);
if (hit.transform == null)
{
return;
}
Player hitComponent = hit.transform.GetComponent<Player>();//Enemyが攻撃したいのはPlayerなのでPlayerに
if (!canMove && hitComponent != null)
{
OnCantMove(hitComponent);
}
}
public bool Move(int x, int y, out RaycastHit2D hit)
{
Vector2 start = transform.position;
Vector2 end = start + new Vector2(x, y);
boxCollider2.enabled = false;
hit = Physics2D.Linecast(start, end, blockingLayer);
boxCollider2.enabled = true;
if (!isMoving && hit.transform == null)
{
StartCoroutine(Movement(end));
return true;
}
return false;
}
IEnumerator Movement(Vector3 end)
{
isMoving = true;
float remainingDistance = (transform.position - end).sqrMagnitude;
while (remainingDistance > float.Epsilon)
{
transform.position = Vector3.MoveTowards(this.gameObject.transform.position, end, 10f * Time.deltaTime);
remainingDistance = (transform.position - end).sqrMagnitude;
yield return null;
}
transform.position = end;
isMoving = false;
}
void OnCantMove(Player hit)//引数をplayerに変更
{
return;//攻撃の処理は次やるので、今回はコメントアウトしてreturnしておく
//hit.AttackDamage(attackDamage);
//animator.SetTrigger("Attack");
}
}
view raw Enemy_ver1.cs hosted with ❤ by GitHub

 

p.s

Udemyの他のオススメ講座や

いろいろな質問に答えられる様に
LINE@を始めました!

一人でゲーム開発するのが不安な方は

このリンクを覗いてみて下さい!