Вторник, 19 Марта 2024, 12:55

Приветствую Вас Гость

Меню сайта
Категории каталога
Создание игр [354]
Статьи об общих понятиях связанных с созданием игр.
Программирование [82]
Гайды по программированию на разных ЯП.
Движки и Гейммейкеры [144]
Статьи о программах для создания игр, уроки и описания.
Софт [39]
Различные программы, в том числе в помощь игроделам.
2D-графика [14]
Уроки по рисованию, растр, пиксель-арт, создание спрайтов и пр.
3D-графика [16]
Уроки по моделированию, ландшафт, модели, текстурирование и пр.
Моддинг игр [5]
Модификация компьютерных игр, создание дополнений, перевод, хакинг.
Игры [160]
Статьи об играх, в том числе и сделанных на гейммейкерах.
Разное [128]
Статьи, которые не вошли в определённые разделы.
Наш опрос
Игры какого типа вы предпочитаете делать?
Всего ответов: 16668
Главная » Статьи » Создание игр

Создание простого ИИ с помощью 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". Теперь создадим ещё строчку:
Code

  if(Vector3.Distance(_agent.transform.position, player.transform.position) < 100){

}

Тут мы проверяем, если дистанция от агента до игрока меньше ста. В скобочках ("{", "}") мы укажем что будет.
ЗАПОМНИТЕ! _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. Итак. Мы видим:
Code

if(Vector3.Distance(_agent.transform.position, player.transform.position) < 100){
_target = player.transform;
}
else{
  _target = _home;
}

Вот. Теперь проверяем. И пошли дальше...
Теперь мы сделаем саму атаку врага. Сначала вычислим дистанцию, на которой он будет нас атаковать. Это будет:
Code

  if(Vector3.Distance(_agent.transform.position, player.transform.position) < 50){

}

А сейчас мы укажем, что будет происходить. Мы просто остановим противника. Указав ему скорость на ноль. И получим:
Code

  if(Vector3.Distance(_agent.transform.position, player.transform.position) < 50){
  _agent.speed = 0;
}

Теперь ставим else. В ней мы восстановим скорость. У меня изначальная была 3.5. Вот я и ставлю _agent.speed = 3.5f;
И у нас получилось в итоге:
Code

if(Vector3.Distance(_agent.transform.position, player.transform.position) < 50){
  _agent.speed = 0;
  }
  else{
  _agent.speed = 3.5f;  
  }

Вот. Теперь опять проверяем. Должно работать без ошибок.
Теперь добавим стрельбу врага. Для начала создадим пустой 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; // Вычитаем из хп переменную, указанную в начале метода

  if (hp <= 0) // Если хп меньше или равно 0
  {

  Detonate(); // Вызываем метод Detonate

  }

  }

  void Detonate() // Вот он
  {

  Application.Quit(); // Выключаем игру

  }

  void OnGUI() //Метод GUI
  {

  GUI.Label(new Rect(1, 1, 150, 50), "HP: " + hp, myStyle); // Отображаем хп

  }
}

Вешаем скрипт на игрока.
Теперь создадим скрипт столкноввения пули с игроком. Создадим метод 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);. Тестим! Вуаля! Враг ходит и стреляет.
А об анимации и дополнительных эффектах в следующем уроке.
Категория: Создание игр | Добавил: Nekit_Aut (21 Марта 2012)
Просмотров: 19525 | Комментарии: 4 | Рейтинг: 5.0/8 |
Теги: ИИ, искуственный интелект, Unity3D, fps, Enemy, NavMesh, C#, AI, Player, скрипты
Дополнительные опции:
Также если вы считаете, что данный материал мог быть интересен и полезен кому-то из ваших друзей, то вы бы могли посоветовать его, отправив сообщение на e-mail друга:

Игровые объявления и предложения:
Если вас заинтересовал материал «Создание простого ИИ с помощью NavMesh(для FPS). Часть 1», и вы бы хотели прочесть что-то на эту же тему, то вы можете воспользоваться списком схожих материалов ниже. Данный список сформирован автоматически по тематическим меткам раздела. Предлагаются такие схожие материалы: Если вы ведёте свой блог, микроблог, либо участвуете в какой-то популярной социальной сети, то вы можете быстро поделиться данной заметкой со своими друзьями и посетителями.

Всего комментариев: 4
+0-
3 MyACT   (10 Апреля 2012 04:26) [Материал]
MyACTЯ тебя не много не понял в скрипте с пулей....
У тебя там переменных в нем нету,и у меня куча ошибок:

Assets/Scripts/AI/AIAttack.cs(20,37): error CS0103: The name `_damage' does not exist in the current context

Странно но он не может понять что такое Damage

+0-
4 Nekit_Aut   (16 Апреля 2012 18:36) [Материал]
Nekit_AutDamage - урон happy

+3-
1 MyACT   (21 Марта 2012 15:07) [Материал]
MyACTЯ первый!
Спасиб +

+2-
2 Nekit_Aut   (21 Марта 2012 15:59) [Материал]
Nekit_AutПжалста)

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск по сайту
10 случ. движков
  • Asphyre Sphinx
  • Bitty
  • Castle Game Engine
  • NES Maker
  • Visionaire Studio
  • Cafu
  • Jolt3d!
  • Tululoo HTML5 Game Maker
  • Novelty
  • Ignifuga
  • Друзья сайта
    Игровой форум GFAQ.ru Перевод консольных игр
    Все права сохранены. GcUp.ru © 2008-2024 Рейтинг