Найти тему
Iuliia

Выделение и перемещение объектов в UNIGINE

Оглавление

Разделы:

  1. Обработка нажатия мыши
  2. Создание курсора
  3. Получение первого пересеченного объекта
  4. Вывод информации об объекте при наведении
  5. Перемещение объектов
  6. Назначаем скрипты объектам

1. Обработка нажатия мыши

Создать компонент C# с название "MouseHandler". Функция возвращает название нажатой кнопки мыши.

public string IsMousePressed()
{
if (Input.IsMouseButtonPressed(Input.MOUSE_BUTTON.LEFT))
return "LeftPress";
if (Input.IsMouseButtonDown(Input.MOUSE_BUTTON.LEFT))
return "LeftDown";
if (Input.IsMouseButtonUp(Input.MOUSE_BUTTON.LEFT))
return "LeftUp";
return "None";
}

2. Создание курсора

Создать компонент C# с название "HUD".

public AssetLink crosshairImage = null;
public int crosshairSize = 16;

private WidgetSprite sprite = null;
private Gui screenGui = null;
private ivec2 prev_size = new ivec2(0, 0);

private void Init()
{
screenGui = Gui.GetCurrent();

sprite = new WidgetSprite(screenGui, crosshairImage.AbsolutePath);
sprite.Width = crosshairSize;
sprite.Height = crosshairSize;

screenGui.AddChild(sprite, Gui.ALIGN_CENTER | Gui.ALIGN_OVERLAP);
sprite.Lifetime = Widget.LIFETIME.WORLD;
}

private void Update()
{
ivec2 new_size = screenGui.Size;
if (prev_size != new_size)
{
screenGui.RemoveChild(sprite);
screenGui.AddChild(sprite, Gui.ALIGN_CENTER | Gui.ALIGN_OVERLAP);
}
prev_size = new_size;
}

Создадим NodeDummy и переместим в поле наш скрипт. В поле "Crosshair Image" поместим картинку курсора в .png, а в поле "Crosshair Size" выставим нужный нам размер.

3. Получение первого пересеченного объекта

Создаем компонент C# с названием "CameraCast". Этот скрипт предназначен для получения первого пересеченного объекта.

Добавим необходимые нам переменные.

public PlayerDummy shootingCamera = null;
[ParameterMask(MaskType = ParameterMaskAttribute.TYPE.INTERSECTION)]
public int mask = ~0;
private Unigine.dvec3 p0, p1;

Включим visualizer в функции init для управления настройками, связанными с визуализатором. В моем случае он необходим для выделения объектов.

Visualizer.Enabled = true;

Создаем функцию, которая пускает луч из камеры, находит первое пересечение с объектов и возвращает его.

public Unigine.Object GetObject()
{
p0 = shootingCamera.WorldPosition;
p1 = shootingCamera.WorldPosition + shootingCamera.GetWorldDirection() * 100;

WorldIntersectionNormal hitInfo = new WorldIntersectionNormal();
Unigine.Object hitObject = World.GetIntersection(p0, p1, mask, hitInfo);

return hitObject;
}

4. Вывод информации об объекте при наведении

Создать компонент C# с название "SelectObject".

Создадим необходимые переменные WidgetCanvas будем использовать для вывода названия объекта.

public CameraCast cameraCast = null;
private Unigine.Object selectedObject;
private WidgetCanvas textOfObject;
private Gui gui;
private int x, y;

В функцию Init напишем следующий код. Он созданию WidgetCanvas для будущей информации.

gui = Gui.GetCurrent();
textOfObject = new WidgetCanvas(gui);
textOfObject.Clear();

x = textOfObject.AddText(1);

vec4 color = new vec4(x, 1, 1, 0.5);
textOfObject.SetTextColor(x, color);
textOfObject.SetTextSize(x, 30);
textOfObject.SetTextPosition(x, new vec2(10, 10));

y = textOfObject.AddPolygon(0);
textOfObject.SetPolygonColor(y, new vec4(0, 0, 0, 0.5));

textOfObject.AddPolygonPoint(y, new vec3(0, 0, 0));
textOfObject.AddPolygonPoint(y, new vec3(600, 0, 0));
textOfObject.AddPolygonPoint(y, new vec3(600, 100, 0));
textOfObject.AddPolygonPoint(y, new vec3(0, 100, 0));

gui.AddChild(textOfObject, Gui.ALIGN_EXPAND);
textOfObject.Hidden = true;

В функцию Update напишем код, который получает пересеченный объект и вывод информацию об этом объекте. Причем вывод информации будет только у дочерних элементов элемента "Engine" (мой собственный объект). А также будет выделять этот объект с помощью visualizer.

selectedObject = cameraCast.GetObject();
if (selectedObject != null && selectedObject.RootNode.Name == "Engine")
{
Visualizer.RenderObjectSurfaceBoundBox(selectedObject, 0, vec4.BLUE, 0.05f);

textOfObject.Hidden = false;
string info = $"{selectedObject.Name}";
addText(info);

Visualizer.RenderMessage3D(selectedObject.WorldPosition + new vec3(0, 0, 0.05f), 0, info, vec4.GREEN, 0, 20,0);
}

Допишем функцию addText.

private void addText(string text)
{
textOfObject.SetTextText(x, text);
}

5. Перемещение объектов

Создадим скрипт, с помощью которого вы будет перемещать выбранные объекты. Назовем его "drugObject".

Создадим необходимые переменные.

public CameraCast cameraCast = null;
private Unigine.Object drugObject;
private Unigine.Object mainObject;
public MouseHandler mouseHandler = null;
private dmat4 transform;
private bool flag;

В функции Init поставим значение flag на false.

flag = false;

В функции Update напишем код, который при нажатие на левую кнопку будет перемещать объекты. При отпускании кнопки перемещение прекращается.

drugObject = cameraCast.GetObject();
if (flag)
mainObject.WorldTransform = cameraCast.shootingCamera.OldWorldTransform * transform;
string mouse = mouseHandler.IsMousePressed();
if (drugObject != null && drugObject.RootNode.Name == "Engine")
{
if (mouse == "LeftPress")
{
if (!flag && drugObject != null && drugObject.RootNode.Name == "Engine")
{
mainObject = drugObject;
transform = cameraCast.shootingCamera.IWorldTransform * drugObject.WorldTransform;
}
flag = true;
}
}
if (mouse == "LeftUp")
{
flag = false;
}

6. Назначаем скрипты объектам

Добавим основную камеру игрока PlayerDummy, от которой будем пускать луч для получения пересеченного объекта, назовем ее "player". Сделаем ее дочерней для "first_person_controller". Нажмем Edit у "first_person_controller" и изменить раздел "Camera". В "Camera Mode" выберем "USE_EXTERNAL", а в поле "Camera" перенесем камеру "player" из древа объектов.

-2

Перенесем компоненты к объектам, согласно скринам ниже.

player_person_controller

-3

player

-4