Assets disappearing after creation

I’ve been trying to set up a custom asset. I’ve set up a UFactory and I can create the assets from the right-click content menu, but if I create two the first one disappears, and then a short time later the second one also disappears. They’ve never saved.

They are not marked as transient and I’ve been trying to figure out what they need to persist. Does anyone know?

You have to make sure that your code is actually generating a valid UPackage* asset.

Is that necessary if nothing is being imported? It’s just a blueprint. I’ve been copying UProceduralFoliageSpawner so far since it pretty much has the same asset behaviour that I want. None of the examples require it.

Apart from what happens in the UFactory this isn’t code-based or being created in code. It’s being done through the editor UI like a normal asset.

Fixed. I’ll leave this up so it can help someone else because this was pretty obscure without an error of any sort.

Add the module “AssetTools” to your build.cs file. Now it’ll just work.

False alarm, it’s still disappearing. Is it related to the below thing? The right asset persisted.

I still have one weird thing. What’s the difference between these two assets?

The left one was created through the content menu. Only the right one appears in the dropdown. What’s the difference between these two things?

And just like that they started saving. Still not sure what I did to fix it. Weirdest thing as well, before when I created them there was a hang for about 10-20 seconds then it’d proceed. Now though it creates them without hanging.

Still can’t add right-click created assets to the dropdown, so I might just take them out of the menu entirely and force inline creation.

“HyperFoliageFlora” is saved inside the HyperFoliage package.
“NewHyperFoliageFlora” on the left doesn’t have any valid package, it’s just an UObject saved into a directory.

Also the one to the right is a Blueprint generated class.

For example this will save an UObject into a valid UPackage asset:



UObject* UMGC_ScriptFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
{
    check(Class->IsChildOf(UMagicNodeScript::StaticClass()));

    return NewObject<UMagicNodeScript>(InParent,Class,Name,Flags,Context);
}


And this will save a new generated Blueprint class based on the same class:



UObject* UMGC_ScriptFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
{
    check(Class->IsChildOf(UMagicNodeScript::StaticClass()));

    return FKismetEditorUtilities::CreateBlueprint(Class,InParent,Name,BPTYPE_Normal,UBlueprint::StaticClass(),UBlueprintGeneratedClass::StaticClass(),TEXT("AssetTypeActions"));
}


This also creates a valid package and saves an UObject within:



void FMagicNodeEditor::CreateNewScriptAsset()
{
    IAssetTools &AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();

    FString PackageName = FString(TEXT("/Game/"));
    FString AssetName = FString(TEXT("NewMagicNode"));
    AssetTools.CreateUniqueAssetName(PackageName, AssetName, PackageName, AssetName);

**UPackage* Package = CreatePackage(nullptr,*PackageName);**
**UPackage* OuterPack = Package->GetOutermost();**

    auto ScriptFactory = NewObject<**UMGC_ScriptFactory**>();
    UObject* NewScript = ScriptFactory->FactoryCreateNew(UMagicNodeScript::StaticClass(), OuterPack, *AssetName, RF_Standalone|RF_Public, nullptr, GWarn);

    FAssetRegistryModule::AssetCreated(NewScript);
    NewScript->MarkPackageDirty();
    NewScript->PostEditChange();
    NewScript->AddToRoot();

    Package->SetDirtyFlag(true);
}


Odd, I was already doing all of that.


#pragma once

#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Factories/Factory.h"
#include "HyperFoliageCollection.h"

#include "HyperFoliageCollectionFactory.generated.h"

UCLASS()
class UHyperFoliageCollectionFactory : public UFactory
{
    GENERATED_UCLASS_BODY()

public:

    virtual UObject * FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
    virtual uint32 GetMenuCategories() const override;
    virtual bool ShouldShowInNewMenu() const override;
};


#pragma once

#include "HyperFoliageCollectionFactory.h"

#include "AssetTypeCategories.h"
#include "HyperFoliageCollection.h"


UHyperFoliageCollectionFactory::UHyperFoliageCollectionFactory(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    bCreateNew = true;
    bEditAfterNew = true;
    SupportedClass = UHyperFoliageCollection::StaticClass();
}

UObject * UHyperFoliageCollectionFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
{
    auto NewHyperFoliageCollection = NewObject<UHyperFoliageCollection>(InParent, Class, Name, Flags | RF_Transactional);
    return NewHyperFoliageCollection;
}

uint32 UHyperFoliageCollectionFactory::GetMenuCategories() const
{
    return EAssetTypeCategories::Misc;
}

bool UHyperFoliageCollectionFactory::ShouldShowInNewMenu() const
{
    return true;
}

This is the collection and the other type is the flora that goes in the collection, but they both have identical factories. In both cases if I right-click and use the context menu I get what you saw in the screenshot that you said wasn’t packaged. This seems to be how UProceduralFoliageSpawner works, which is the functionality I’m basing it on.

Flora is like FoliageType, and if create either of them using the context menu they both do the same thing. But if I use the create-inline functionality I get the one you say is packaged. But they’re all packaged. And yet only the one with the circle icon shows up in the list, which might be because of how I’ve set up the list:


    UPROPERTY(EditAnywhere, SimpleDisplay, Category = "HyperFoliage")
        TArray <TSubclassOf <UHyperFoliageFlora>> HyperFoliageFloraTypes;

Actually I didn’t read your whole post before replying. I’m going to try the second block of code now. I don’t need the third block as I’m not creating assets from within the code itself.

Yeah that worked brilliantly, cheers! This doesn’t seem to really be mentioned anywhere.

The
FKismetEditorUtilities::CreateBlueprint() method registers the generated class within engine’s asset reflection system. If you just packed a UObject it usually will not show up on dropdown lists unless you write some custom Widgets for Details Panel. I built Widgets for MagicNodes because they’re not Blueprints, just packed UObjects. But I don’t remember now the classes I used to make the custom dropdown which shows non-blueprint packs.