Измениение CDO с помощью блюпринта
Иногда возникает ситуация, когда база блюпринтов одного типа разрастается до десятков и сотен, например, в игре большое количество оружия и амуниции, или заклинаний и зелий.
Для геймдизайнера это страшный ад, даже если все блюпринты хорошо рассортированы по папкам - искать нужный среди них, потом искать нужную переменную и вручную менять каждую из них крайне утомительное занятие.
К счастью, мы можем немного облегчить его страдания.
Главный вопрос в том, как поменять значение переменной блюпринта не собственными руками, а, например, другим блюпринтом.
Именно об этом я напишу в этом посте.
CDO (Class Default Object)
CDO или Class Default Object - это шаблон конкретного класса, который будет использоваться движком в качестве прототипа для создания объектов этого класса. По сути это полная копия этого класса со значениями по умолчанию.
CDO создается совершенно для любого блюпринта и С++ класса, помеченного макросом UCLASS(). В большей степени он необходим Reflection (Unreal Property System) системе движка.
Я не буду углубляться в эти системы, так как для данного поста достаточно информации выше. В конце статьи я приведу ссылки на полезные материалы по этим темам.
Добавление функции GetCDO
Вернемся к главному вопросу: “Как поменять переменную блюпринта другим блюпринтом?”, сейчас нам очень пригодятся знания о существовании CDO.
Можно ли сказать, что когда мы меняем значение переменной блюпринта, мы меняем его CDO? Да, конечно, ведь по сути именно это мы и делаем.
Внезапно наш вопрос меняется: “Как изменить CDO блюпринта другим блюпринтом?”. К сожалению, в блюпринтах есть возможность только лишь получить CDO с помощью функции “Get Class Defaults”,
но не изменить его. Досадно…
Однако сделать это в коде очень просто.
Нам нужно создать BlueprintFunctionLibrary, куда мы добавим функцию, которая будет возвращать CDO блюпрнта.
MyBlueprintFunctionLibrary.h:
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MyBlueprintFunctionLibrary.generated.h"
UCLASS()
class THIRDPERSONPROJ_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable, Category = "MyBlueprintFunctionLibrary")
static UObject* GetCDO(UClass* Class)
{
return Class->GetDefaultObject();
}
};
GetDefaultObject() как раз та самая C++ функция, которая возвращает CDO блюпринта и позволяет нам с ним делать все, что мы хотим.
Изменение CDO блюпринта
Теперь представим, что у меня в проекте есть два предмета для восстановления здоровья: BP_Medicine и BP_Medicine_2 (унаследованный от BP_Medicine), и у них будет переменная HealCount, которая означает количество восстанавливаемого здоровья при подборе (100 у BP_Medicine и 150 у BP_Medicine_2). Далее главной целью будет сделать инструмент внутри движка, который позволит мне увеличивать значение этой переменной одновременно у обоих предметов на одинаковую величину нажатием одной кнопки.
Теперь возвращаемся к движку. Дальнейшую логику буду писать в EditorUtilityWidget, поэтому создаем новый блюпринт этого класса.
О том, что это такое есть отдельная статья
Теперь добавляем кнопку и поле для ввода текста:
Переходим в Event Graph, добавляем ивент нажатия на кнопку и пишем логику:
В первую очередь, нам нужно каким-то образом получить класс наших блюпринтов. Есть два пути:
1 - Создать массив классов и добавить туда нужные нам классы блюпринтов.
2 - Создать массив строк и добавить туда текстовые ссылки на классы.
Чтобы получить ссылку на класс, нужно нажать ПКМ на блюпринт и выбрать “Copy Reference”. Второй способ так же потребует использования функции LoadBlueprintClass, чтобы получить класс по ссылке.
Этот способ очень полезен, если вы храните и настраиваете все значения блюпринтов вне движка, а загружаете их в него.
Далее буду рассматривать только первый способ.
Итак, у нас есть массив, в который я добавил классы BP_Medicine и BP_Medicine_2. По нему нужно пройти циклом, поэтому добаляю функцию ForEachLoop и на LoopBody вызываю нашу функцию GetCDO.
Важно понимать, что GetCDO возвращает указатель на UObject, поэтому нам нужно сделать каст на нужный нам тип (в нашем случае это BP_Medicine). Далее получаем переменную HealCount и умножаем её на
содержимое поля ввода ( к сожалению в UE в блюпринтах нельзя сразу получить из FText float, только через чепочку FText->FString->float ) и полученное значение назначаем этой же переменной.
В принципе, все готово - можно компилировать и запускать виджет. Для запуска виджета нужно нажать по нему ПКМ и выбрать “Run Editor Utility Widget”.
Теперь указываем нужное значение (я указал 1.5) и жмем. Проверяем значение HealCount в блюпринтах:
Значения увеличились ровно в 1.5 раза, мы добились той цели, которую поставили раньше. Этот инструмент позволяет увеличивать значение переменной HealCount у всех классов в массиве нажатием одной кнопки.
Заключение
Возможность менять значения переменных блюпринтов с помощью других блюпринтов открывает большие возможности по написанию инструментов для упрощения разработки. Все ограничивается только вашей фантазией.