Создание простого ИИ с помощью NavMesh(для FPS). Часть 1
Итак... Всем привет! И сейчас я буду рассказывать, как можно реализовать искуственный интеллект в юнити при помощи NavMesh для FPS (First Personal Shooter). Как он работает - читайте в моей предыдущей статье. А сейчас, опираясь на то, что мы сделали в ней, мы будем делать саму логику врага. Сейчас я буду рассказывать и писать на C#. На JS я напишу в следующей части урока. Приступим. Мы создали объект и сделалиего передвижение. Вот:
Code
public class AINavMesh : MonoBehaviour { public Transform _target; // Указываем переменную, к которой будет двигаться наш агент NavMeshAgent _agent; // Указываем переменную агента
void Start () { _agent = (NavMeshAgent)this.GetComponent("NavMeshAgent"); // Указываем, что переменная _agent - это наш агент. }
void Update () { _agent.SetDestination(_target.position); // Заставляем агента двигаться в сторону _target'а } }
А теперь сделаем так, чтобы не пришлось указывать в инспекторе игрока. Но для этого объекту игрока нужно поставить тэг "Player". Это делается почти там же, где и указывается слой (Layer), только чуть левее (Tag). Вот мы указали тэг. Прописываем в скрипте ИИ Новую трочку в методе (void) Update:
Code
GameObject player = GameObject.FindGameObjectWithTag("Player");
Тут мы создаём переменную, и ищем (и помещаем) в неё GameObject с тэгом "Player". Теперь создадим ещё строчку:
Тут мы проверяем, если дистанция от агента до игрока меньше ста. В скобочках ("{", "}") мы укажем что будет. ЗАПОМНИТЕ! _agent.SetDestination(_target.position); оставляем за проверкой расстояния! Теперь вернёмся к проверке. Тут мы укажем, что _target - это наш Player. Мы пишем:
Code
_target = player.transform;
Мы указали, что _target равен координатам нашей переменной player (та, у которой тэг). Проверям. Теперь враг идёт на нас, если мы подошли на определённое расстояние. Едем дальше. Теперь сделаем так, чтобы враг, как потерял игрока, возвращался на стартовую точку. Создадим переменную public Transform _home;. И создадим void Awake(){}. Поясняю. Этот метод при загрузке игры. И пишем:
Code
_home = transform.parent.transform;
То есть указываем координаты материнского объекта. Теперь переходим в редактор, создаём новый (пустой) GameObject. И помещаем в него нашего агента. Теперь опять к коду. После проверки дистанции делаем else (то есть иначе). И прописываем там:
Code
_target = _home;
Тут мы указываем, что объект, к которому движется агент - _home. Итак. Мы видим:
Вот. Теперь опять проверяем. Должно работать без ошибок. Теперь добавим стрельбу врага. Для начала создадим пустой GameObject, откуда будут вылетать пули. Назовём его weapon. Создадим переменную public Transfom _weapon; и поместим объект weapon в переменную. Теперь создадим метод стрельбы. public void Fire(){}. Теперь зоздадим (не в void Fire()) переменную, отвечающую за префаб пули. Это будет public Rigidbody _bullets;. И в Fire() прописываем:
Code
Rigidbody ins = Instantiate(_bullets, _weapon.position, _weapon.rotation) as Rigidbody; ins.rigidbody.AddForce(transform.forward * 5000);
Тут я сделал так, чтобы пулю не было заметно. И чтобы вылетал префаб и летек из переменной _weapon. Итак... Теперь создадим отдельный скрипт, даже два! Один отвечает за смерть игрока, а другой за столкновение пули. Итак... Создаём скрипт смерти... Думаю, я понятно закомментировал:
Code
using UnityEngine; using System.Collections;
public class PlayerDamageCSharp : MonoBehaviour {
public float hp = 100; // Переменная хп
public GUIStyle myStyle; // Переменная отображения хп
void ApplyDamage(float damage) // Метод ApplyDamage {
hp -= damage; // Вычитаем из хп переменную, указанную в начале метода
Вешаем скрипт на игрока. Теперь создадим скрипт столкноввения пули с игроком. Создадим метод OnCollisionEnter(). И вот, собственно, он:
Code
void OnCollisionEnter(Collision col) //Создаём метод с коллизией col { ContactPoint contact = col.contacts[0]; //Создаём контакт коллизии Quaternion rot = Quaternion.FromToRotation(Vector3.up, contact.normal); // Поворот коллизии Vector3 pos = contact.point; // Позиция коллизии - это позиция контакта Vector3 direct = transform.TransformDirection(Vector3.forward); // Дирекция
if (col.rigidbody) // Если коллизия с ригидбоди (rigidbody) col.rigidbody.AddForceAtPosition(direct * force, col.transform.position); // Придаём импульс этому rigidbody
if(col.collider.tag == "Player"){ // Если коллизия - плеер player.SendMessage("ApplyDamage", _damage); Вызываем у плеера метод ApplyDamage } Destroy(gameObject); // Удаляем пулю
}
Вешаем скрипт на префаб пули. Теперь указываем в инспекторе ИИ этот префаб пули. И опять идём в скрипт ИИ. Там прописываем в дистанции меньше 50 наш метод (то есть вызываем его) Fire(); Теперь зададим точный поворот в сторону противика. Создадим в void Update() переменную Vector3 pos = player.transform.position; и указываем: pos.y = transform.position.y;. Теперь указываем в проверке дистанции меньше 100: transform.LookAt(pos);. Тестим! Вуаля! Враг ходит и стреляет. А об анимации и дополнительных эффектах в следующем уроке.
Также если вы считаете, что данный материал мог быть интересен и полезен кому-то из ваших друзей, то вы бы могли посоветовать его, отправив сообщение на e-mail друга:
Игровые объявления и предложения:
Если вас заинтересовал материал «Создание простого ИИ с помощью NavMesh(для FPS). Часть 1», и вы бы хотели прочесть что-то на эту же тему, то вы можете воспользоваться списком схожих материалов ниже. Данный список сформирован автоматически по тематическим меткам раздела.
Предлагаются такие схожие материалы:
Если вы ведёте свой блог, микроблог, либо участвуете в какой-то популярной социальной сети, то вы можете быстро поделиться данной заметкой со своими друзьями и посетителями.