Initialization Code in UDataAsset Constructor or Somewhere Else?

My goal is to have a class that can read the pixels of a texture, store reformatted information about which pixels were not white, and later use that data to respond to queries.
My attempt was to inherit from UDataAsset and scan the texture in the constructor. Then an actor with a reference to that class would query it. Unfortunately, the constructor never seems to run so the pixel information is always empty. An instance of the class does exist, though, because the query functions aren’t on a null object. I’m guessing the constructor only runs when you create a new data asset instance in the content hierarchy, and changes to the code of the constructor afterwards have no effect.
How can I get my class to re-read the texture pixels if I change the code or referenced texture? Do UDataAsset’s have some function that will always run at start-up I can implement? Am I wrong to inherit from UDataAsset, and should it be AActor instead?

1 Like

Do you need to scan in the constructor? Are these textures something you can scan at edit time and simply store the data in a UDataAsset rather than actually scanning the data each time? You could potentially use PostEditChangeProperty to rescan a texture as you assign / change it (or on other actions depending on what you need).

If this is something you need to scan dynamically at runtime then I’d probably opt to have a manager which maintains a list / map of structs (which contain your processed data). Simply ask the manager to process a new texture, or retrieve the results on an existing one. There’s less overhead for allocation this way and potentially its easier to multi-thread if needed.

1 Like

Thanks for the good suggestions; I wasn’t aware of PostEditChangeProperty. It works, but each time I close and relaunch the editor I have to change a property for the data from reading the texture to be there. Do you know how I can fix that? I tried performing the same computation in PostInitProperties, but that didn’t work.

How are you storing the data? I’d make sure you decorate it with a UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category=“My Cat”) (or similar, just to be sure it’s serailised properly. If you don’t want it to be displayed in the asset for human editing then you can add a hidecategory meta tag (I forget the exact naming).

You also might want to make sure that within your PostEditChangeProperty you’re calling Modify(true) before you read your texture in, and possibly PostEditChange() after you have reassigned the data. You’d then need to save the asset too.

I modify a few things in this way and not seen issues with the data being lost between sessions.

Ah, I hadn’t marked it with UPROPERTY because I didn’t need it visible in the editor, but I didn’t realize that means it isn’t serialized. Adding UPROPERTY without any specifiers fixed things. Thanks for all your help.