Keywords: UE4, UObject, Construct, Construction, Instantiating, UObject-derived, Config, DefaultGame.ini

NewObject using a Blueprint class

1st way:
header:

UPROPERTY(EditAnywhere, Category = "Player")
TSubclassOf<AMyActor> AMyActorClass;

cpp:

MyActor = NewObject<AMyActor>(this, TEXT("MyActor"), RF_NoFlags, AMyActorClass->GetDefaultObject(), true);

2nd way:
header:

UPROPERTY(EditAnywhere, Category = "Player")
TSubclassOf<AMyActor> AMyActorClass;

cpp:

MyActor = NewObject<AMyActor>(this, AMyActorClass);

Reference:
https://forums.unrealengine.com/development-discussion/c-gameplay-programming/1712081-newobject-using-a-blueprint-class

Different ways to instantiate the object
  • UObject::CreateDefaultSubobject is only callable in a class constructor, and takes care of creating an instance of the CDO of the subobject’s class, setting its outer class as the caller object, among other things. The created object then becomes the default object for the property when its object class is instantiated.

  • NewObject<T> is the function normally used to instantiate objects after engine initialisation, during normal gameplay. It provides several convenience overloads to handle most scenarios.

  • UWorld::SpawnActor<T> is a convenience method to spawn actors in a level with the specified location and rotation, spawn collision settings, and checks to ensure it’s a spawnable actor class, and is nothing more than a wrapper of NewObject.

  • ConstructObject has been removed in favour of NewObject.

Orign:
Unreal Engine 4. Different ways to instantiate the object
https://stackoverflow.com/a/60030248/1645289

Check Types

Class:

UClass::IsChildOf();

Actor:

AActor::IsA();
Initialize members of UObject from ini configuration file

Engine\Source\Runtime\CoreUObject\Public\UObject\Object.h

/**
 * Imports property values from an .ini file.
 *
 * @param    Class                the class to use for determining which section of the ini to retrieve text values from
 * @param    Filename            indicates the filename to load values from; if not specified, uses ConfigClass's ClassConfigName
 * @param    PropagationFlags    indicates how this call to LoadConfig should be propagated; expects a bitmask of UE4::ELoadConfigPropagationFlags values.
 * @param    PropertyToLoad        if specified, only the ini value for the specified property will be imported.
 */
void LoadConfig( UClass* ConfigClass=NULL, const TCHAR* Filename=NULL, uint32 PropagationFlags=UE4::LCPF_None, class UProperty* PropertyToLoad=NULL );

/**
 * Wrapper method for LoadConfig that is used when reloading the config data for objects at runtime which have already loaded their config data at least once.
 * Allows the objects the receive a callback that it's configuration data has been reloaded.
 *
 * @param    Class                the class to use for determining which section of the ini to retrieve text values from
 * @param    Filename            indicates the filename to load values from; if not specified, uses ConfigClass's ClassConfigName
 * @param    PropagationFlags    indicates how this call to LoadConfig should be propagated; expects a bitmask of UE4::ELoadConfigPropagationFlags values.
 * @param    PropertyToLoad        if specified, only the ini value for the specified property will be imported
 */
void ReloadConfig( UClass* ConfigClass=NULL, const TCHAR* Filename=NULL, uint32 PropagationFlags=UE4::LCPF_None, class UProperty* PropertyToLoad=NULL );

/** Import an object from a file. */
void ParseParms( const TCHAR* Parms );
How do I create a blueprint that can inherit from a UObject

Examples:

UCLASS(Blueprintable, BlueprintType) 
class ENGINE_API UMyObject : public UObject 
{

Reference:
https://answers.unrealengine.com/questions/35953/view.html

LoadClass

Example
UClass* TestClass = LoadClass<AActor>(nullptr, TEXT("Blueprint'/Game/Blueprints/MapPathBrush_BP.MapPathBrush_BP_C'"));
UClass* AnimClass = LoadClass<UAnimInstance>(nullptr, TEXT("AnimBlueprint'/Game/ABP_Test.ABP_Test_C'"));
UClass* WidgetClass = LoadClass<UUserWidget>(nullptr, TEXT("WidgetBlueprint'/Game/NewWidgetBlueprint.NewWidgetBlueprint_C'"))
LoadClass触发构造函数的问题

如果项目中使用了LoadClass,那么蓝图相关的class构造函数中不要执行和实例化对象相关的操作,因为当执行LoadClass时也会把对应class的构造函数执行一遍(即使我们没有手动执行spawn或者create等函数,原因是LoadClass执行了LoadObject,而LoadObject内部又会执行ConstructorHelpers::FObjectFinder(),所以会触发class的构造函数,比如自己新建了一个UserWidget class,这个class的默认构造函数会在LoadClass时被执行一次),建议将初始化操作放在Initialize、BeginPlay等函数中。

Config (ini file)

How to add GUI for custom ini file in Project Settings

It’s much easier to create custom project settings using DeveloperSettings (Custom ‘Project Settings’), example:

UCLASS(Config = Game, DefaultConfig, meta = (DisplayName = "My Custom Settings"))
class MYGAME_API UMySettings : public UDeveloperSettings
{
    GENERATED_BODY()

public:

    UPROPERTY(Config, EditAnywhere, Category = "Info")
    FString Foo = TEXT("test");

    UPROPERTY(Config, EditAnywhere, Category = "Info")
    int32 Bar = 222;
};

Then you can modify values in GUI panel (Project Settings -> Game -> My Settings), and values will be saved to [Project]/Config/DefaultGame.ini (in section [/Script/MyGame.MySettings]) automatically when modify them in project settings panel.

If want to save values in custom ini file, not Game.ini, you should change

UCLASS(Config = Game, DefaultConfig, meta = (DisplayName = "My Custom Settings"))

to

UCLASS(Config = MySetting, DefaultConfig, meta = (DisplayName = "My Custom Settings"))

but then the GUI panel moved into Project Settings -> Engine -> My Custom Settings.

ini file was saved in [Project]/Config/DefaultMySetting.ini automatically when values was modified in GUI (if the default value wasn’t changed), but if change value and save it using C++ code: LoadConfig() then SaveConfig(), then ini file will be saved in FPaths::GeneratedConfigDir() (e.g. [Project]/Saved/Config/WindowsNoEditor/MySetting.ini)

Change values and save them using C++ at run-time (LoadConfig(), SaveConfig()):

static const FString ConfigFileName = TEXT("MySettings.ini");
FString Path = FPaths::GeneratedConfigDir() + ConfigFileName;

UMySettings* Settings = GetMutableDefault<UMySettings>();
//load values from [Project]/Saved/Config/WindowsNoEditor/MySettings.ini
Settings->LoadConfig(nullptr, *Path);

Settings->Foo = TEXT("jjjj");
Settings->Bar = 6666;
//save values into [Project]/Saved/Config/WindowsNoEditor/MySettings.ini
Settings->SaveConfig(CPF_Config, *Path);
DefaultConfig vs ConfigDoNotCheckDefaults

一般一个ini对应的config class长这样:

UCLASS(Config = Game, DefaultConfig, meta = (DisplayName = "My Custom Settings"))
class MYGAME_API UMySettings : public UDeveloperSettings
{

其中DefaultConfig表示ini文件的读取和存储方式,另外一种方式是ConfigDoNotCheckDefaults

读取方式区别:

  • DefaultConfig: 使用LoadConfig()接口获取的配置,或者编辑器首次启动时,都是从FPaths::SourceConfigDir()目录下的ini读取,比如:[Project]/Saved/Config/WindowsNoEditor/MySettings.ini,而不是DefaultMySettings.ini(即使其内部有修改过的值)。但通过编辑器(Project Settings面板)修改后,会清掉[Project]/Saved/Config/WindowsNoEditor/MySettings.ini中所有内容,即使只修改了一项。同时,将修改过的值保存在[Project]/Config/MySettings.ini
  • ConfigDoNotCheckDefaults: 都是从[Project]/Saved/Config/WindowsNoEditor/MySettings.ini读取。

存储方式区别(两种情况):

  • 使用C++接口SaveConfig()触发的存储都存在FPaths::SourceConfigDir()目录下,比如:[Project]/Saved/Config/WindowsNoEditor/MySettings.ini
  • 通过编辑器(Project Settings面板)修改触发的存储:
    • DefaultConfig: ini文件存放在[Project]/Config/DefaultMySettings.ini中。[Project]/Saved/Config/WindowsNoEditor/MySettings.ini文件仍然存在,但是内容为空。
    • ConfigDoNotCheckDefaults: [Project]/Config/DefaultMySettings.ini文件不存在,且内容保存在[Project]/Saved/Config/WindowsNoEditor/MySettings.ini

参考:UE4中Config的使用
https://blog.ch-wind.com/ue4-config-usage/

How to add custom config in specified section in project settings

Credits to: UnLuaModule.cpp

1, Add C++ class for ini config:

UCLASS(Config = UnLua, DefaultConfig, Meta = (DisplayName = "UnLua"))
class UNLUA_API UUnLuaSettings : public UObject
{
    GENERATED_BODY()

public:
    UUnLuaSettings(const FObjectInitializer& ObjectInitializer);

    /** Entry module name of lua env. Leave it empty to skip execution on startup. */
    UPROPERTY(Config, EditAnywhere, Category="Runtime")
    FString StartupModuleName = TEXT("");
}

2, Use FModuleManager::RegisterSettings() to register custom ini settings in Project Settings on startup module:

void FMyPluginModule::StartupModule()
{
    RegisterSettings();
}

void FMyPluginModule::ShutdownModule()
{
    UnregisterSettings();
}

void FMyPluginModule::RegisterSettings()
{
#if WITH_EDITOR
    ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings");
    if (!SettingsModule)
        return;

    const auto Section = SettingsModule->RegisterSettings("Project", "Plugins", "UnLua",
        LOCTEXT("UnLuaEditorSettingsName", "UnLua"), LOCTEXT("UnLuaEditorSettingsDescription", "UnLua Runtime Settings"),
        GetMutableDefault<UUnLuaSettings>());
    //bind callback for value changed
    Section->OnModified().BindRaw(this, &FMyPluginModule::OnSettingsModified);
#endif
}

void FMyPluginModule::UnregisterSettings()
{
#if WITH_EDITOR
    ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings");
    if (SettingsModule)
        SettingsModule->UnregisterSettings("Project", "Plugins", "UnLua");
#endif
}
Plugins Config file(ini)

You can put config files into plugin’s Config directory. e.g.:
[Porject]\Plugins\[Plugin]\Config\CustomSettings.ini

If there’s a config with same file name in the directory [Porject]\Config\, then the content of [Porject]\Plugins\[Plugin]\Config\ will be merged into [Porject]\Config\ automatically when packaging.


生如夏花之绚烂,死如秋叶之静美。----泰戈尔《生如夏花》