void ACMap::ClearMap()
{
UE_LOG(LogTemp, Warning, TEXT("ClearMap"));
TArray<AActor*> FoundActors;
// получаем список всех акторов с таким классом как наш блупринт BP_Wall
UGameplayStatics::GetAllActorsOfClass(GetWorld(), bpwallClass, FoundActors);
for (AActor *actor : FoundActors)
actor->Destroy(false, true);
}
void ACMap::BuildMap()
{
UE_LOG(LogTemp, Warning, TEXT("CreateMap"));
// проверка на вшивость, если bpwallClass не установлен, то всё остальное просто крашнется, лучше вообще ничего тыды не делать
// так уж и быть, сообщим в консоли об этом
if (bpwallClass)
{
// вызываем полную очистку мира от наших блоков
ClearMap();
int x = 0;
int y = 0;
FActorSpawnParameters params;
FTransform transform;
FVector Location;
FOutputDeviceNull ar;
FOutputDeviceDebug debug;
FString command;
for (int i = 0; i < Map.Num(); i++)
{
int blockID = Map[i];
Location = FVector(x * 100, y * 100, 0);
transform.SetLocation(Location);
AActor* wall = GetWorld()->SpawnActor<AActor>(bpwallClass, transform, params);
// для вызова функций блупринта, существует CallFunctionByNameWithArguments
// более подробнее можно почитать в оф. документации
command = FString::Printf( TEXT("UpdateBlockID %d"), blockID );
wall->CallFunctionByNameWithArguments(*command, debug, this, true);
x++;
if (x >= map_width)
{
x = 0;
y++;
}
}
}
else
UE_LOG(LogTemp, Error, TEXT("Set BP_Wall value!"));
}
Компилим Ctrl_Shift+B (у меня это на автомате). Ну и наверное пока всё по коду, что нам осталось, это внутри BP_Map, установить переменную bpwallClass. Что мы и сделаем, открывайте его в редакторе.
Делаем мы это в конструкторе, тяните нить (судьбы))) от конструктора и пишите set bp wall остальное она выдаст сам
Задайте значение BP_Wall (наш блупринт).
ну вот мы и подружили С++ и наши блупринты.
Теперь давайте откроем вкладку Events в BP_Map, там у нас щас стоит только LoadMap, надо ещё добавить блок BuildMap, тянем от LoadMap и пишем BuildMap. Если помните, то мы как раз её описали в CMap и сделали видимой для блупринта.
Сделали? Гуд. Компилим блупринт.
Теперь декоративная составляющая, но не менее важная. Так уж получилось что блок стен, дверей, стекла имеет положение. И если рядом поставить два из них в разных направлениях, то они могут не сойтись. Поэтому нам надо сделать так, что если рядом с нашим блоком, стоит какой нибудь блок, мы должна его повернуть. Поэтому открываем BP_Wall, и идем в UpdateBlockID. Вот как раз И для этого мы сделали видимым GetBlockID. Описывать по шагам не буду, просто добейте как на картинке.
Ещё такой момент, у нас по сути аж 4 блока. А у нас сделано лишь 3, как то я упустил этот момент, так что тут он уже исправлен.
Давайте в начале добавим новый блок, который мы упустили, смотрите на значение NewMesh, потому что разница лишь в нём.
Значения должны быть BlockWall, BlockWall_01, BlockWall_02_glass, Block_Wall_03_plate
Теперь нажмите ПКМ в пустом месте пространства и наберите Get Actor Location, далее ПКМ по желтому кругу (значению) и там выбираем Split Struct
вместо значения вектора, появится привычные обывателю X,Y,Z. Нам нужны от сюда X и Y. По ним мы будем определять позицию в карте. Проще говоря, все блоки ставятся в позиции (X*100, Y*100), если поделить на 100, то как разу будет значение (X,Y) в CMap->Map
Тянем от X и пишем / (знак деления), там выбираем float/float. В появившимся блоке пишем вторым значение 100. Также делаем для Y, должно получится примерно так.
Ну и теперь от блоков SetStaticMesh ID блока которых 2,3,4, сделаем такую штуку.
ПКМ в пустом месте и пишем Get All Actors of Class, в поле выбираем наш BP_Map, этот блок ищет все блупринты в мире такого класса и возвращает их (если они вообще есть, а у нас на карте он есть в единственном экземпляре). Возвращает в виде списка, поэтому мы достаем из списка первое же значение. Тянем за OutActors и пишем Get. Так как он возвращает массив типа AActor, нам ещё придется сделать Cast. Тянем синий кружок и пишем Cast To BP_Map.
Берем за синий кружок BP_Map и тянем, пишем там GetBlockID (то есть вызываем метод)
Чуть чуть отводим вправо блок GetBlockID, ну и подсоединяем наши деленные значения X и Y. Так как GetBlockID(int32 X, int32 Y), просит целые числа, редактор сам сделает перевод из float в int32.
Ошибку допустил, ну ничего щас поправим.
И так снова опишу: нам надо знать есть ли блоки от нас по соседству. Сверху и Снизу (остальные нас не интересуют). И если есть, то повернуть нашу стену к ним также. Чтобы рядом стоящие смотрелись едино.
Поэтому всё что нам надо. это из ЦЕЛЫХ значений вычесть 1 в начале по Y (верхняя стена), затем Y+ (нижняя стена от нас).
Теперь от блока GetBlockID тянем и пишем Branch (этот тот же IF в коде, только он может сверять лишь булевые переменные, то есть либо истина, либо ложь).
Тянем от GetBlockID->ReturnVaule (зеленого) и знак >= и результат соединяем с Branch
Я наверное уже не буду писать что от чего тянуть, просто смотрите картинки.
Ну и добавим для проверку на нижний блок, в том случае если сверху оказался пустым.
Ну и теперь самый важный момент, надо соединить 2,3,4 с нашей созданной цепочкой.

Ещё такой момент. Я упустил из виду, когда мы сюда попадаем из конструктора, то blockID уже задан и мы лишь меняем модель. А вот когда мы строим блок из карты, blockID не меняется, это бы надо поправить от тянув от функции и написав SetBlockID, ну и соеденить значения

Ну что, возрадуйтесь!
Давайте дам вам перевести дух...
Вы дошли, добрались до этого гребанного Евереста. Время пришло.
Компилируем блупринт BP_Wall.
Закрываем его и
Запускаем игру. Ну а что вы увидите, останется только между нами 8)
С уважением, Ваш Salamandr ;)
* Для тех кто начал проходить урок до того как появилась 4 страница.
Просьба перекачать файл карты https://drive.google.com/open?id=0Bzl8pH3p1mHRdWx0VlVNdVlVaWc и файл с моделями https://drive.google.com/open?id=0Bzl8pH3p1mHRcFBseWxBekg5cFU
Также, если вы хотите сами поучаствовать в создании этой ММО. Например вы 3д моделлер или текстурщик, или художник, оставляйте координаты в комментариях.
В каждой статье будет упоминание о Вас, о вашей безвозмездной помощи проекту в роли 3д моделлера (к примеру).
Сделаем эту ММО силами форума GameDev.ru все вместе! 8)
Все статьи безвозмедно передаются форуму gamadev.ru с полными полномочиями на исправление ошибок.
PS: Знания это сила! Но лишь тогда, когда ими делятся с другими.
#Blockmap, #debug, #MMO, #Tilemap, #Unreal
23 мая 2017
(Обновление: 28 мая 2020)
Комментарии [5]