Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для компьютеров > Unity > Уроки

Ответ
 
Опции темы
Старый 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)
Старый 15.02.2013, 18:36   #2
burovalex
Разработчик
 
Аватар для burovalex
 
Регистрация: 04.04.2012
Сообщений: 468
Написано 37 полезных сообщений
(для 60 пользователей)
Ответ: Unity3d - Простой AI

Помогите пожайлуста разобраться с синтаксисом, тяжело, я с блитца перехожу..

Пойду прямо по примеру.


private Transform _thisTransform;
private CharacterController _controller;


Так объявляются компоненты объектов?


_controller = GetComponent<CharacterController>();
Вот здесь вообще не понял, почему не в скобках, а рядом с ними и в треугольных. Нельзя както так писать _controller = This.GetComponent(CharacterController) ??

_thisTransform = transform;
переменной присвается трансформация понятно, но чья? самого себя?
Т.е. можно написать _thisTransform = This.transform


Player player = (Player)FindObjectOfType(typeof(Player));
Здесь вообще не понял,
1-й Player что означает, это чтото типа CharacterController или что??
2-й player (понятно что переменная)!
3-й (Player) тоже не понял, почему он в скобках?
4-й typeof(Player) это что значит, под типом подразумевается объект к которому скрипт с названием Player прикреплён ??


float angle = Vector3.Angle(_thisTransform.forward, playerDirection);
Vector3 означает взять 3-й компонент вектора чтоли? т.е. z или как??
_thisTransform.forward - это берется вектор в прямом направлении?


Ответь Пожалуйста кто на что сможет
БУДУ ОЧЕНЬ БЛАГОДАРЕН
__________________
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Sapik (07.05.2015)
Старый 15.02.2013, 19:28   #3
is.SarCasm
Бывалый
 
Аватар для is.SarCasm
 
Регистрация: 17.05.2009
Адрес: Днепропетровск
Сообщений: 672
Написано 180 полезных сообщений
(для 428 пользователей)
Ответ: Unity3d - Простой AI

Так объявляются компоненты объектов?
Так вообще объявляются объекты. Точно также как в блице Field int x; или как там.
Вот здесь вообще не понял, почему не в скобках, а рядом с ними и в треугольных. Нельзя както так писать _controller = This.GetComponent(CharacterController) ??
Можно написать This.GetComponent("CharacterController") , но это не круто. Смотри справку.
1-й Player что означает, это чтото типа CharacterController или что??
Это , похоже, заранее определенный класс.
3-й (Player) тоже не понял, почему он в скобках?
Это тоже самое что написать "as Player". То есть найденный объект переводится в Player (это как из float в int, например) или из найденного объекта берется компонент "Player"
4-й typeof(Player) это что значит, под типом подразумевается объект к которому скрипт с названием Player прикреплён ??
Смотри справку
Vector3 означает взять 3-й компонент вектора чтоли? т.е. z или как??
Это класс, такой же как string, gameObject или transform. По сути это класс состоящий из трех float'ов x,y,z и статических функций. Опять справка: http://docs.unity3d.com/Documentatio...e/Vector3.html
_thisTransform.forward - это берется вектор в прямом направлении?
Вектор вперед по Z, относительно этого объекта
(Offline)
 
Ответить с цитированием
Эти 2 пользователя(ей) сказали Спасибо is.SarCasm за это полезное сообщение:
burovalex (15.02.2013), Emixon (26.08.2020)
Старый 15.02.2013, 20:41   #4
burovalex
Разработчик
 
Аватар для burovalex
 
Регистрация: 04.04.2012
Сообщений: 468
Написано 37 полезных сообщений
(для 60 пользователей)
Ответ: Unity3d - Простой AI

СПАСИБО БОЛЬШОЕ!! Хоть чтото прояснилось.

Можете еще ссылку на пример или пример написать
Как можно создать массив и вего поместить какие-нибудь объекты (например кубики) и произвольно со временем удалять объекты.
__________________
(Offline)
 
Ответить с цитированием
Старый 15.02.2013, 21:06   #5
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Ответ: Unity3d - Простой AI

Тоже прокомментирую

1. В данном случае поля класса объявляются синтаксисом: модификатор тип имя_переменной. private значит не публичное поле класса, Transform или CharacterController это типы, _thisTransform и _controller имена переменных. Подробнее тут, потом можно почитать тут, но уже сложнее.

2. Метод GetComponent<CharacterController>(); шаблонный. Подробнее тут. В угловых скобках указывается тип (в данном случае тип компонента, который надо найти на объекте).

3. _thisTransform = transform; тоже самое что и _thisTransform = this.transform; Т.е. переменной присваивается значение свойства transform. Это свойство, хоть и выглядит как переменная, выполняет действие подобное описанному в пункте 2 - получает с объекта компонент типа Transform. Т.е. запись _thisTransform = GetComponent<Transform>(). Подробнее о свойствах тут. Какие свойства есть у скрипта тут.

4. Player player = (Player)FindObjectOfType(typeof(Player));
Все что перед "равно" это объявление переменной player типа Player. Справа выполняется функция поиска объекта типа Player в сцене (скрипт на каком-либо объекте сцены). Но так как функция возвращает тип UnityEngine.Object от которого наследуются все объекты Unity (в том числе и скрипты - MonoBehaviour унаследован от Component, Component от UnityEngine.Object) - чтобы присвоить полученное значение переменной типа Player, полученное значение нужно привести к типу Player - это как раз (Player). Подробнее об этом тут. C# это строго типизированный язык. Все переменные должны иметь тип и могут содержать экземпляры данных, соответствующие этим типам. Еще почитать.

5. float angle = Vector3.Angle(_thisTransform.forward, playerDirection);
дословно: посчитать угол между двумя векторами _thisTransform.forward и playerDirection.

UPD: тут я приводил пример создания поля из объектов, сохраняя ссылки на них в думерном массиве
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Эти 2 пользователя(ей) сказали Спасибо pax за это полезное сообщение:
burovalex (15.02.2013), mauNgerS (15.02.2013)
Старый 15.02.2013, 22:11   #6
burovalex
Разработчик
 
Аватар для burovalex
 
Регистрация: 04.04.2012
Сообщений: 468
Написано 37 полезных сообщений
(для 60 пользователей)
Ответ: Unity3d - Простой AI

Спасибо за помощь! не думал, но оказывается приколько когда язык известный - можно пользоваться в разных движках, буду учиться )

Поможете разобраться с примером, взял с Юнити, писал своими словами, но смысл тот же. Но почему то ругается что я пытаюсь конвертировать UnityEngine.Object в UnityEngine.Rigidbody. Я понимаю что это компонент объекта, а не объект.
Но подскажите плиз, как сделать чтоб не ругался.
Как я понял в примере должны появляться копии каждые две секунды в рандомных позициях

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
	
	public Rigidbody MeshToInstance;
	
	// Update is called once per frame
	void Launch() {
	Rigidbody instancer = Instantiate(MeshToInstance);
	instancer.velocity = Random.insideUnitSphere;
	}
	
	void Example()
	{
		Invoke("Launch",2);	
	}
}
__________________
(Offline)
 
Ответить с цитированием
Старый 15.02.2013, 22:13   #7
burovalex
Разработчик
 
Аватар для burovalex
 
Регистрация: 04.04.2012
Сообщений: 468
Написано 37 полезных сообщений
(для 60 пользователей)
Ответ: Unity3d - Простой AI

И еще вопросик )
А можно в консоле отображать данные - использовать как дебагер, или еще куда-нибудь в другое место печатать?

Я себя чуствую как полный нуб! Не думал что так сложно будет перейти с блитца на с# ...
__________________
(Offline)
 
Ответить с цитированием
Старый 16.02.2013, 01:09   #8
Andvrok
Бывалый
 
Регистрация: 26.07.2009
Сообщений: 785
Написано 362 полезных сообщений
(для 995 пользователей)
Ответ: Unity3d - Простой AI

Debug.Log("text"); 
(Offline)
 
Ответить с цитированием
Старый 16.02.2013, 10:49   #9
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Ответ: Unity3d - Простой AI

Rigidbody instancer = (Rigidbody)Instantiate(MeshToInstance); 
Тут необходимо явно привести тип UnityEngine.Object к Rigidbody. Для этого перед выражением ставится название типа в скобках. Но я обычно всегда инстанцирую геймобъекты, а не их компоненты.

void Start()
    {
        
Invoke("Launch",2);    
    } 
Функция Example сама по себе не запустится, запускаются определенные эвенты

Про консоль: Debug.Log(данные); или print(данные);

Сообщение от burovalex Посмотреть сообщение
не думал, но оказывается приколько когда язык известный - можно пользоваться в разных движках, буду учиться )
Это основная причина, по которой я советую изучать C# для скриптов Unity, а не js
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
burovalex (16.02.2013)
Старый 16.02.2013, 18:36   #10
burovalex
Разработчик
 
Аватар для burovalex
 
Регистрация: 04.04.2012
Сообщений: 468
Написано 37 полезных сообщений
(для 60 пользователей)
Ответ: Unity3d - Простой AI

Начал с нуля всё изучать, т.е. смотреть как типы даных объявляются и заодно для себя начал выкидывать инфу в chm. Как думаете, нужны такие наработки, или уже хватает?
Если да, то подскажите какой адрес надо писать для внутренних гиперссылок
Вот наброски: http://www.sendspace.com/file/j9g31y
Жмём Click here to start download from sendspace

И еще такая тема. Когда пользовался блитцом, при использовании буленовских переменных, для инвертации значения просто писал так:
boole=(1-boole)
НО в с# такое не канает. В нём нет такой конвертации.
Что делать в таких случаях?


ЮХУУУ, уже начинаю потихоньку втягиваться, сам догадался boole=!boole; ))
__________________

Последний раз редактировалось burovalex, 16.02.2013 в 23:03.
(Offline)
 
Ответить с цитированием
Старый 17.02.2013, 15:45   #11
burovalex
Разработчик
 
Аватар для burovalex
 
Регистрация: 04.04.2012
Сообщений: 468
Написано 37 полезных сообщений
(для 60 пользователей)
Ответ: Unity3d - Простой AI

Чёт тишина, так делать справку или нет?

Еще вопросик
Как задавать значения вручную для Vector2,Vector3,Color
Только не так Vector2.x=1; Vector2.y=2;
А типо так Vector2=Vector2(1,2);
Подскажите
__________________
(Offline)
 
Ответить с цитированием
Старый 17.02.2013, 21:20   #12
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Ответ: Unity3d - Простой AI

Vector2 myVec= new Vector2(1,2);
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Старый 15.04.2014, 13:11   #13
ЕвГен
AnyKey`щик
 
Аватар для ЕвГен
 
Регистрация: 31.01.2013
Сообщений: 10
Написано 6 полезных сообщений
(для 34 пользователей)
Ответ: Unity3d - Простой AI

Привет всем! Хочу сделать не большой проект в жанре FPS на Unity. До этого я не программировал, занимался только моделированием. Сейчас в сцене у меня Player у которого стандартный FPS_Controller и Enamy(Модель бота с анимацией, он может следовать за Player'ом с помощью NavMeshAgent и ему присвоен тэг "Enamy"), также есть перфаб Bullet(Игрок может стрелять физическими сферами) у Bullet есть скрипт:

void OnCollisionEnter(Collision collision){
if(collision.gameObject.tag=="Enamy" ){
Destroy(collision.gameObject);
Destroy(gameObject);
}

}
Т.Е. Игрок "выпускает" пулю и если она сталкивается с объектом у которого есть тэг "Enamy", тогда пуля и объект очищается.

Вопрос:

Как мне реализовать смерть "Enamy"( добавить ему жизни и при столкновение ее вычитать?)?
(Offline)
 
Ответить с цитированием
Старый 16.04.2014, 09:17   #14
Randomize
[object Object]
 
Аватар для Randomize
 
Регистрация: 01.08.2008
Адрес: В России
Сообщений: 4,354
Написано 2,470 полезных сообщений
(для 6,850 пользователей)
Ответ: Unity3d - Простой AI

Сообщение от pax Посмотреть сообщение
Vector2 myVec= new Vector2(1,2);
Вот, кстати, почему в Юнитях так принято создавать объекты сотнями? Там это дело хоть как оптимизируется (объектный пул, etc)?
Просто делать new в цикле по 500 раз и так каждый кадр - выглядит довольно страшно. А по инету сорсы гуляют и куда не глянь всюду ехал new через new. Понятно, что структуры копеечные, но если их скапливается достаточно много, то потом GC не охреневает с такого хламушника?
__________________
Retry, Abort, Ignore? █
Intel Core i7-9700 4.70 Ghz; 64Gb; Nvidia RTX 3070
AMD Ryzen 7 3800X 4.3Ghz; 64Gb; Nvidia 1070Ti
AMD Ryzen 7 1700X 3.4Ghz; 8Gb; AMD RX 570
AMD Athlon II 2.6Ghz; 8Gb; Nvidia GTX 750 Ti
(Offline)
 
Ответить с цитированием
Старый 16.04.2014, 11:19   #15
impersonalis
Зануда с интернетом
 
Аватар для impersonalis
 
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений
(для 20,935 пользователей)
Ответ: Unity3d - Простой AI

Теперь нам лень изощряться, оптимизировать код,
И интерфейс с дураками мы пишем из году в год,
Свыклись с мощной машиной, отвыкли от всякого риска.
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
(Offline)
 
Ответить с цитированием
Эти 2 пользователя(ей) сказали Спасибо impersonalis за это полезное сообщение:
Randomize (16.04.2014), St_AnGer (16.04.2014)
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 08:10.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com