C#

Нужна помощь с созданием первой игры на Unity

Я делаю что-то вроде смеси шахмат и боевой системы из героев 3. На шахматном поле 8x8 будут сражаться 8 различных видов фигур.
По задумке должно работать так:
Когда игрок в свой ход нажимает на свою фигуру, фигура обращается к скрипту (расположеном на объекте поле) сообщая ему информацию о нажатии и свой порядковый номер, скрипт ищет в трёхмерном массиве, в котором содержатся координаты по горизонтали, координаты по вертикали и порядковый номер, позицию фигуры на поле, затем скрипт по листу (я про List<имя листа>) определяет к какому виду фигур принадлежит фигура отправившая порядковый номер и создаёт объекты из префаба (кнопки) на клетках с нужным положением на поле, при нажатии на такую кнопку положение фигуры (в масиве) изменяется, а затем сама фигура плавно, через функцию X+=(target - X)*0.1, переезжает на выбраню клетку.

вопросы:
1. Как передать и записать свою информацию в переменную другого объекта по нажатию?
2. Как можно это можно реализовать более оптимально и проще?
Как же много вы насобирали сущностей! Давайте по порядку. По пути отвечу на заданные вопросы.

> Когда игрок в свой ход нажимает на свою фигуру, фигура ...
*никуда не обращается*! Для кого в C# встроены события?
---
[RequireComponent(typeof(Figure))]
public class FigureClickHandler : MonoBehaviour {
public delegate void ClickEvent(Figure figure);
public event ClickEvent OnClick;
public void Click(){
OnClick?.Invoke(GetComponent< Figure >());
}
}
---
Теперь при старте игры контроллер должен подписаться на события OnClick для всех фигур на поле - и сама фигура не будет знать ничего лишнего.

Это был по сути ответ на вопрос 1, дальше по вопросу 2:

> скрипт ищет в трёхмерном массиве, в котором содержатся координаты по горизонтали, координаты по вертикали и порядковый номер, позицию фигуры на поле ...
Жесть. Храните позиции фигур в коллекции Dictionary< Figure, Vector2Int >, и пожалуйста, никаких трехмерных массивов.

> затем скрипт по листу (я про List<имя листа>) определяет к какому виду фигур принадлежит фигура...
Слово полиморфизм вам о чём-нибудь говорит? Если нет, на крайняк, пусть Figure имеет enum-поле с конкретным значением своего типа. Что ж вас так тянет по листам и массивам всё искать.

> создаёт объекты из префаба (кнопки) на клетках с нужным положением на поле...
Какие нафиг кнопки? Оставьте кнопки для UI. На поле просто меняете спрайт сетки с пустого на символизирующий доступное для клика место, а сам клик отслеживайте по рейкасту.

> фигура плавно, через функцию X+=(target - X)*0.1, переезжает на выбраню клетку...
Куда читабельнее был бы такой код в апдейте или корутине:
---
t += speed * Time.deltaTime;
transform.position = Vector3.Lerp(a, b, t)
---
А вообще опытные программисты используют Tween-плагины для таких задач, именно чтобы не засорять код описанием плавного передвижения объектов.
AA
Ablai Anesov
5 779
Лучший ответ
Макат Касымбаев я до этого создавал лишь пару игр на чистом коде на языке Pascal и простенькие текстовые игры на C# для консоли, а в ютити 2 игры по видео-урокам, у меня мало опыта
Макат Касымбаев вы можете объяснить:
[RequireComponent(typeof(Figure))] <--- что это? (перевод "требуется компонент (тип (фигура))")
public class FigureClickHandler : MonoBehaviour {
public delegate void ClickEvent(Figure figure);
public event ClickEvent OnClick;
public void Click(){
OnClick?.Invoke(GetComponent< Figure >()); <--- что за компонент фигура?
}
}

как я понял нужно каким то образом добавить компонент Figure, но как я не понял
Ablai Anesov 1) RequireComponent - это атрибут, через который можно прописать зависимость данного компонента от другого. В данном примере указано, что компонент FigureClickHandler требует наличия компонента Figure на объекте.
2) Для справки. Движок Unity реализует шаблон Entity-Component-System (ECS), обозначая в качестве сущностей - GameObject-ы, а в качестве совокупности компонентов и систем - Behaviour-ы. По умолчанию все C# скрипты, которые вы создаёте в Unity, реализуют абстрактный класс MonoBehaviour, унаследованный от класса Behaviour. Следуя шаблону ECS, рекомендуется разбивать структуру игровых сущностей на как можно более компактные модули (компоненты).
3) Создаёте компонент Figure, который отвечает за самые фундаментальные свойства вашей абстракции "фигура", и добавляете его на объект.
Ничего не понял..
То есть игрок тыкает на фигуру, которая, как существующий объект, ничего о себе не знает, но через скрипт и массив, которые завязаны на поле, начинает узнавать свои свойства, относительно которых появятся какие-то действия, которая эта фигура может совершить, основываясь на своих свойствах?

Это что-то типа класса, который, когда программа начинает его использовать, начинает спрашивать у другого класса о своих функциях/переменных/константах..?))))

Наверное, я просто как-то не так прочитал. Надо больше спать.
МК
Максим Ка
10 661
Макат Касымбаев фигуры как марионетки у общего скрипта, всё обрабатывает скрипт, а марионетки отправляют свой номер и получают информацию о том куда надо передвинутся
1. Как передать и записать свою информацию в переменную другого объекта по нажатию?
В "другом" объекте объявить переменную с модификатором public, найти его экземпляр и менять эту переменную как хочешь. В юнити, классы унаследованные от MonoBehaviour можно найти по имени объекта в сцене (GameObject.Find(string name)). Но ещё лучше хранить собственный экземпляр (this) в статической переменной. Получится как-то так:
public class Main_Engine : MonoBehaviour {
public static Main_Engine inst;
public int variable_to_change = 0;

void Awake() { inst = this; }
}

public class Piece : MonoBehaviour {
Update() {
Main_Engine.inst.variable_to_change += 15;
}
}

А что касается детекта нажатия на 3х мерный объект - это уже несколько сложнее. Нужно рейкастить луч из камеры в сторону курсора мыши (предварительно пересчитав координаты из экранного пространства в мировые), и смотреть во что он попал.

2. Как можно это можно реализовать более оптимально и проще?
Если задача просто двигать фигуры (т. к. только про эту написал), то это всё вообще лишнее и не нужное :(. Скрипт на фигуре должен хранить все её свойства и заниматься передвижением, это как-то больше соответствует принципам ООП. В головном скрипте нужно хранить рефы на все фигуры на доске, а при необходимости получить какую-то информацию о фигуре обращаться уже непосредственно к ней. Ну, ещё можно проверять, может-ли фигура в то место вообще ходить...

как-то так...
Макат Касымбаев Я думаю если реализовать скрипт на каждой фигуре это дополнительно нагрузит игру, а если реализовать так чтобы фигуры были как марионетки подконтрольны управляющему скрипту скрипт будет всего 1 или 2(возможно я разделю математику атаки и движения), а также у меня будет возможность изменять карту (блокировать клетки)
Мурат Жандыгулов Не нагрузит. Скрипт который ничего не делает, если у него нет Update()/FixedUpdate() не даёт нагрузки. Это хорошо видно если инстанциировать, скажем, 1000 скриптов и посмотреть в профайлер. Памяти немного берёт, да. Но совсем чуть-чуть, потому что инстансы...
В юнити, сотня врагов в сцене, со скриптами, которые каждый кадр проверяют как минимум должны они что-то делать или нет - обычное дело. Спроектирован он так.