Всем доброго времени суток!
Еще в универе на старших курсах начал увлекаться интеллектуальными агентами. Даже тема для диплома изначально была связана с созданием агентов, участвующих в боевых действиях, в среде, имитирующей поле боя. Но из-за работы пришлось сменить тему.
Давно хотел этим заняться, но все времени не было. Сейчас наконец-то дошли руки сделать среду для агентов, хотя и не в таком масштабе. Так что если кому-нибудь интересно, присоединяйтесь! Репозитарий открытый, ссылка внизу.
Интеллектуальный агент.
Говоря простыми словами, агент — это сущность, помещенная в среду обитания, умеющая воспринимать среду с помощью датчиков и воздействовать на нее с помощью актуаторов.
Схема простейшего агента, как говорит википедия, выглядит так:
У такого агента нет никакого разума, он действует исключительно по списку простейших правил if-then. Есть несколько видов гораздо более сложных агентов, которые умеют анализировать свои действия и обучаться. Но до них мне еще далеко.
Unity3d
Я создал в Unity3d проект, в котором есть поле боя (квадрат) и несколько танков. Текстуры танков я взял из старой-доброй игры Battle City. Все, что умеет каждый танк — это ездить по полю и стрелять.
Так выглядит весь проект:
К каждому танку привязаны 2 управляющих скрипта:
— TankBehavior
— BasicTankControls (или его подкласс)
TankBehavior — это главный скрипт, который полностью описывает один танк. В этом скрипте реализованы методы перемещения, стрельбы и все остальные. Также этот скрипт содержит ссылку на BasicTankControls, в котором реализовано управление танком. Базовый скрипт выглядит так:
public class BasicTankControls : MonoBehaviour
{
public void Init(TankBehavior tank)
{
this.tank = tank;
}
public virtual void Act(List<TankData> tanksData)
{
// no operation
}
protected TankBehavior tank;
}
Так происходит инициализация скрипта-управления в скрипте TankBehavior:
void Start ()
{
...
controls = GetComponent<BasicTankControls>();
if(controls != null)
{
controls.Init(this);
}
...
}
Этот метод вызывается каждый физический тик:
void FixedUpdate()
{
if(controls != null)
{
GameObject[] tankObjects = GameObject.FindGameObjectsWithTag("Tank");
List<TankData> tanksData = new List<TankData>();
foreach (var item in tankObjects)
{
if (item.GetInstanceID() != this.GetInstanceID())
{
tanksData.Add(item.GetComponent<TankBehavior>().GetData());
}
}
controls.Act(tanksData);
}
}
Сначала собираются данные обо всех танках на поле. Таким образом имитируется сбор информации о среде датчиками агента. Затем эта информация передается скрипту-управлению, который уже на основе полученных данных будет оказывать воздействие на среду.
Данные об одном танке выглядят так:
public class TankData
{
public TankData(int instanceId, Vector2 position, float health, Direction direction)
{
this.InstanceID = instanceId;
this.Position = position;
this.Health = health;
this.Direction = direction;
}
public readonly int InstanceID;
public readonly Vector2 Position;
public readonly float Health;
public readonly Direction Direction;
}
Вот в принципе и все. Теперь задача состоит лишь в том, чтобы написать для танков управляющий скрипт. Я написал один скрипт для управления человеком, если вдруг кто-нибудь захочет вмешаться в ход событий:
public class HumanControls : BasicTankControls
{
public override void Act(List<TankData> tanksData)
{
if(Input.GetButton("Up"))
{
tank.MoveForward();
}
else if (Input.GetButton("Down"))
{
tank.MoveBackward();
}
if (Input.GetButtonDown("Left"))
{
tank.RotateLeft();
}
else if (Input.GetButtonDown("Right"))
{
tank.RotateRight();
}
if (Input.GetButton("Fire"))
{
tank.Fire();
}
}
}
Поведения танков
Для начала планирую сделать простейшие автономные поведения, например ездить и стрелять в случайные стороны. Потом есть идея добавить стены (может быть, разрушаемые) и тот самый штаб, который одним нужно защищать, а другим разрушить. Может быть, даже будет совместное планирование действий.
Но это очень оптимистичные планы. Сам еще такого никогда не писал, так что придется изучать. Любая помощь и советы приветствуются! :)
Ссылка на репозитарий.