Теперь открываем BP_Wall и добавляем новую переменную, BlockID.
Обратите внимание на правую панель Details, там надо выбрать что тип Integer (зелененький такой), ну а первоначальное значение появится лишь после компиляции. Плюс надо поставить галку на Editable, это даст возможность редактировать значение прямо в редакторе (без запуска или в процессе запуска игры). Компилим, и видим что появился 0 в Default Value, мы его менять не будем, нас он устраивает.

Помните я упомянул про первую вкладку Viewport, нам в принципе сейчас именно туда. Можно её не открывать, но так сложнее будет выставлять значения. У нашего Actor, слева есть такое поле Components
Именно там и будут располагаться все визуальные составляющие такие как модель. Так что давайте туда и добавим. Жмём на Add Component и набираем слово Static, выбираем Static Mesh.
Получилось добавить? Отлично, всё таки текстом куда дольше передавать данные, но точнее (да и всегда можно перечитать 8))
Когда у нас выбран Static Mesh, в Details (справа) у нас теперь совсем другие вещи. Жмякаем на второй None (который со стрелкой вниз, то есть выпадающий список). Выбираем там наш BlockWall. И.. о чудо, у нас появилась наша модель. Но мы слишком близко к ней, можно скроллингом мыши находясь в Viewport откатиться назад. Также при зажатой ПКМ можно использовать традиционные WASD, Space, Ctrl. На первое время этого должно хватить для изменения вида.
Теперь давайте добавим второй Static Mesh, как они располагаются в иерархии - это очень важно, если второй будет внутри первого, то при перемещении ... потом распишу. Они так и легли сейчас, нам пока это не важно.
появился StaticMesh1, переименуйте его сразу во MeshFloor (то бишь пол, по которому ходим). А верхний, давайте в просто Mesh. Теперь MeshFloor даем модель BlockWall_plate. Если обратите внимание, он находится в том же месте по координатам (0,0,0) но при этом расположен ниже их. Специальный блок для тех участков карты где нет никакого блока.
Снова выбираем StaticMesh, и вместо BlockWall, пропишите BlockWall_02_glass. Это я щас для проверки, что вы всё сделали правильно. Это должно выглядеть вот так:
Если выглядит по другому, имеется ввиду что позиция блоков расположена по другому, или их нет вообще, перечитайте снова. Достаточно удалить и тот и другой, и начать заново этот абзац.
Если всё хорошо, то выберите верхнему блоку Clear в списке моделей. Останется лишь нижний маленький кубик.
Теперь переходим во вкладку Constuct Sript, видим там один единственный блок. Перетягиваем нашу переменную слева BlockID поближе и выбираем GET. От BlockID тянем и набираем switch to int. Соединяем блок конструктора и Switch, Default оставим пустым. А вот ниже есть плюсик, жмем на него начинаем ответвлять. На 0 нам ничего не надо делать, жмешь ещё раз плюсег. Гуд. Теперь из окна Компоненты (где у нас Mesh и MeshFloor), тянем Mesh. От блока Mesh тянем и пишем set static mesh. И соединяем этот блок с единицей у Switch
Теперь в блоке set static mesh, в переменной New Mesh выбираем BlockWall. Тем самым мы говорим что при значении BlockID = 1, модель первого блока сделать BlockWall.
Теперь, снова от Mesh делаем ещё один set static mesh, и в New Mesh выбираем BlockWall_02_glass
А теперь выберем set static mesh и при его выделенным нажмем Ctrl+W, должен появится ещё один блок set static mesh. Если этого не произошло (такое бывает), выберите другой блок и снова set static mesh, и нажимаем Ctrl+W. Блок появится именно в том месте где стоит курсор мыши. Обратите внимание у этого блока Target будет self, в данном случае это не совсем правильно. Протяните линию от Mesh до SetStaticMesh->Target. В третьем блоке New Mesh надо выбрать BlockWall_03_door. Доделайте до этого варианта сами:
Это в принципе окончательная его форма. Нажимаем Compile, ну и всё, закрываем этот блупринт.
Для проверки, перетащите блупринт на сцену и попробуйте выставить разные значения BlockID. Блок должен мгновенно менять свою модель.
Как наиграетесь, не забудьте удалить его со сцены (уровня, карты), он нам там пока ни к чему.
Ну и давайте пока мы тут, сделаем вот что, откроем блупринт блока BP_Wall. Зайдем в конструктор, выделим мышкой всё, кроме блоков: конструктора и BlockID, жмем ПКМ, Collapse to Function, и слева переименуем её в UpdateBlockID.
Правило #2: Если у Вас есть набор комманд который вы используете дважды, не надо копировать кусок текста и выставлять, просто создайте метод и вызывайте через него. Это избавит Вас от необходимости править код как минимум в двух местах если что-то поменяется, а если этих мест не два а больше? Представили. Ок
Эту функцию мы будем вызывать из CMap, передавая в неё ID нашего блока, делать это будем уже когда блок на карте, это позволит нам изменять ID уже не на этапе построения, а в любой момент времени.
Так же откройте эту функцию, нам надо кое что подправить. Потому что есть ещё одно значение блока, это -1. Сейчас мы должны добавить состояние для 0 и -1. В Switch нет -1, но есть Default, им мы и воспользуемся.
Сделайте от Default ещё один блок SetStaticMesh от Mesh, а от него ещё один SetStaticMesh от MeshFloor. New Mesh, оставьте None у обоих блоков.
ну и добавьте от 0 тоже два SetStaticMesh, также от Mesh и от MeshFloor. У SetTaticMesh от MeshFloor->New Mesh сделайте BlockWall_plate. Должно получится вот так.
Компилим. Мы ещё сюда вернемся, когда добавим возможность получать из карты: "а какой блок стоит в таких то координатах?" (GetBlockID).
Ну а теперь опять вернемся в студию и посмотрим что там нам "боженька принес". В начале откроем CMap.h и добавим две переменные. Одна будет иметь ссылку на наш блупринт BP_Wall, чтобы мы смогли создавать такой объект внутри CMap, а вторая это переменная Map, в которой мы будем хранить нашу карту ID блоков в виде целых чисел.
Ах да, мыж договорились ещё добавить метод GetBlockID(), добавляем его сразу видимым из блупринтов.
Ну и будет ещё две переменных, которые нам очень нужны, это map_width и map_height. Одна из них будет хранить ширину карты, другая высоту.
Открываем CMap.h, ищем public и добавляем в конец:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = References)
TSubclassOf<AActor> bpwallClass;
TArray<int32> Map;
UFUNCTION(BlueprintCallable, Category = Game)
int32 GetBlockID(int32 X, int32 Y);
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = References)
int32 map_width;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = References)
int32 map_height;
Открываем CMap.cpp, ползём в метод LoadMap и пишем там следующий код, в этот раз весь выложу и просто объясню чё там происходит.