Показать сообщение отдельно
Старый 23.06.2010, 19:36   #1
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Unity3d - Простой AI

Данный урок является результатом поставленной задачи в этом посте.

Сначала немного теории.

Прежде всего, чтобы понять, как правильно создавать игровой мир в Unity3d, стоит рассказать о его составляющих.
Первое на что стоит обратить внимание – это объект игры (GameObject). Это основной элемент игрового мира, который содержит в себе компонент по умолчанию Transform, определяющий положение, размер и ориентацию объекта в сцене. Каждый объект игры может содержать любое количество компонентов (можно их назвать скриптами), которые определяют поведение данного объекта в сцене. Некоторые компоненты могут требовать наличие других компонентов для правильной работы. Например, в прошлой статье я приводил пример назначения компонента Rigid Body кубикам, которые уже имели компонент Box Collider. Взаимодействие между данными компонентами позволяло кубику вести себя в сцене как физическому объекту, который может падать и сталкиваться с другими кубиками и другими объектами сцены, имеющими компоненты Collider.

Как я уже говорил, каждый объект игры может иметь компоненты, определяющие его поведение. Поведение может быть не явное, как в приведенном выше примере, а выполнять какие-то действия разово или на протяжении какого-то времени. Например, игровой объект может создавать другие объекты при запуске сцены, играя роль «инициализатора» игрового мира; может выполнять какие-то действия периодически, например, уничтожил ли игрок всех врагов в сцене или нет, и если уничтожил, то выполнить действия по завершению уровня.
Префаб (Prefab) – подготовленный заранее объект игрового мира. Он может содержать в себе любой сложности заготовленную структуру. Создается он очень просто: 1) В сцене создается игровой объект любой сложности; 2) в окне Project создается Prefab так же как и создается любой скрипт; 3) перетаскиванием из окна сцены созданного игрового объекта на созданный в окне Project префаб в сцене этот объект становится экземпляром префаба, а та пустая заготовка ранее созданная в окне Project становится заготовленным объектом.

Здесь следует отметить, что если префабами являются игровые объекты, содержащие в себе компоненты для визуализации моделей (Mesh Filter и Mesh Renderer), то Unity3d автоматически использует технологию инстансинга для визуализации групп одинаковых объектов.
Думаю, данного введения будет достаточно для понимания данного урока, поэтому перейдем к практической части.

Начинаем делать заготовки.
  1. Для начала нам понадобится создать пустой проект, как это было описано в предыдущем уроке.
  2. Создадим в окне Project четыре папки: Scripts, Prefabs, Scenes и Materials.
  3. Создаем в папке Scripts два скрипта с названиями Player, Enemy.
  4. В папке Prefabs создаем два пустых префаба с такими же именами (Player, Enemy).
  5. В папке Materials создадим два материала PlayerMaterial и EnemyMaterial и дадим им зеленый и оранжевый цвет соответственно.
  6. В папку Scenes сохраняем текущую сцену под названием Game.

Должно получиться примерно так, как показано на следующем скриншоте:


Мы сначала реализуем поведение игрока, потом сделаем заготовку для поведения врага.
Итак, переходим в выбранный вами редактор кода (в моем случае Visual Studio) двойным щелчком по скрипту «Player» и помещаем в него следующий код:
using UnityEngine;

public class 
Player MonoBehaviour
{
    
// скорость ходьбы и скорость поворота в секунду
    
public float moveSpeed 2;
    public 
float turnSpeed 90;

    private 
CharacterController _controller;
    private 
Transform _thisTransform;

    public 
void Start()
    {
        
// Получаем контроллер
        
_controller GetComponent<CharacterController>();

        
// Получаем компонент трансформации объекта, к которому привязан данный компонент
        
_thisTransform transform;
    }


    public 
void FixedUpdate()
    {
        
// Рассчитываем позицию 
        
_controller.Move(_thisTransform.forward moveSpeed Time.deltaTime Input.GetAxis("Vertical") +
                        
Vector3.down 10.0f Time.deltaTime);

        
// Рассчитываем поворот
        
Quaternion rot Quaternion.AngleAxis(
            
turnSpeed Time.deltaTime Input.GetAxis("Horizontal"), Vector3.up);
        
_thisTransform.rotation *= rot;
    }

То же самое делаем со скриптом «Enemy»:
using UnityEngine;

public class 
Enemy MonoBehaviour
{
    
// скорость ходьбы и скорость поворота в секунду
    
public float moveSpeed 2;
    public 
float turnSpeed 90;

    private 
CharacterController _controller;
    private 
Transform _thisTransform;
    private 
Transform _playerTransform;

    public 
void Start()
    {
        
// Получаем контроллер
        
_controller GetComponent<CharacterController>();

        
// Получаем компонент трансформации объекта, к которому привязан данный компонент
        
_thisTransform transform;

        
// Получаем компонент трансформации игрока
        
Player player = (Player)FindObjectOfType(typeof(Player));
        
_playerTransform player.transform;
    }

    
// Все что связано с физикой выполняем в FixedUpdate
    
public void FixedUpdate()
    {
        
// направление на игрока
        
Vector3 playerDirection = (_playerTransform.position _thisTransform.position).normalized;

        
// угол поворота на игрока
        
float angle Vector3.Angle(_thisTransform.forwardplayerDirection);

        
// максимальный угол поворота на текущем кадре
        
float maxAngle turnSpeed Time.deltaTime;

        
// Вычисляем прямой поворот на игрока
        
Quaternion rot Quaternion.LookRotation(_playerTransform.position _thisTransform.position);

        
// поворачиваем врага на игрока с учетом скорости поворота
        
if (maxAngle angle)
        {
            
_thisTransform.rotation Quaternion.Slerp(_thisTransform.rotationrotmaxAngle angle);
        }
        else
        {
            
_thisTransform.rotation rot;
        }

        
// если дистанция до игрока больше трех метров
        
if (Vector3.Distance(_playerTransform.position_thisTransform.position) > 3.0f)
        {
            
// двигаемся к игроку
            
_controller.Move(_thisTransform.forward moveSpeed Time.deltaTime);
        }
        else 
// если меньше или равна трем метрам
        
{
            
// здесь например стреляем в игрока
        
}

        
// гравитация
        
_controller.Move(Vector3.down 10.0f Time.deltaTime);
    }

Подготавливаем сцену
На данном этапе Вы уже должны понимать, как работают скрипты поведения каждого из трех объектов, назначение каждого из используемых окон среды. Если что-то осталось непонятно, то попробуйте перечитать эту статью или вернуться к предыдущей статье.
  1. Возвращаемся в среду Unity3d и создаем три игровых объекта в сцене: два кубика и план.
  2. У кубиков удаляем Box Collider и добавляем компонент Character Controller, с помощью которого будем управлять игроком и врагами.
  3. Назначаем кубикам материалы перетаскиванием.
  4. Зададим плану масштаб(Scale) (100,1,100) для того, чтобы он принял размеры, требуемые по заданию (по умолчанию он размером 10х10) и поместим его в ноль координат, если он был создан не в нуле. На нем по умолчанию установлен компонент Mesh Collider, который позволит нашим кубикам не проваливаться.
  5. Выбираем первый кубик и добавляем ему компонент Player. Перетаскиваем этот кубик на префаб с названием Player.
  6. Выбираем второй кубик и добавляем ему компонент Enemy. Перетаскиваем этот кубик на префаб с названием Enemy.
  7. Переименовываем объекты в сцене в соответствии с их назначением.
  8. Вы должны уже были заметить, что после создания из объекта префаба – его название в сцене становится синего цвета.
  9. Расставляем наши объекты в сцене, так как нужно, создав заранее еще два экземпляра префаба Enemy просто перетащив его в сцену.
  10. Переименуем врагов так как в задании)).
    У меня получилось примерно так:

  11. Сохраняем сцену и запускаем.

Как всегда результат.
__________________
Blitz3d to Unity Wiki

Последний раз редактировалось pax, 16.02.2013 в 11:24.
(Offline)
 
Ответить с цитированием
Эти 14 пользователя(ей) сказали Спасибо pax за это полезное сообщение:
Amatsu (16.02.2013), ARA (13.08.2010), baton4ik (05.08.2010), burovalex (15.02.2013), den (20.07.2010), Dream (23.06.2010), Fatalix3d (23.06.2010), jfkkk (23.06.2010), mauNgerS (15.02.2013), maxturbo (22.10.2010), Nex (24.06.2010), Nuprahtor (23.06.2010), Radnk (17.07.2012), SaM_ (16.06.2011)