Is it possible to set a Format Text that can be referenced in Class Default Value?

I would like to assign a weapon description created using Format Text based on parameters to a Text variable, but is it possible to make this in a form that can be referenced using Class Default Value?

Editing such variables is usually only possible by executing a function at runtime. However, I thought that it might be possible to set pre-edited Text by defining the format in advance, just like the Default Value of other variables, and assigning other Default Values ​​that already exist there.

Is something like this possible?

Why not just use the constructor to append the needed prefix => name => suffix to a new variable that holds the combined string of all of the attributes?

Changes in editor of an actor

It would probably be a good idea to populate the information via data assets.

You can of course the set default values of the prefix, name and suffix in this case and it will propagate to the combined name.

Can data created in this way be retrieved via Get Class Default? This is the most important thing. I did a quick test assigning a variable from the Construction Script and failed to get it.

Also, I can’t use data asset. Some of the data I want to make variables are component-specific, like the Mass of a mesh.

text is hard in many ways especially when you want to concatenate/append it.
the default value is not necessarily Ever going to be the actual value of the member variable (that is without talking about Floating Point Approximation)
so even though in your C++ class or blueprint you set the default value of “MyInteger” to be 7, every instance of that member variable might be a 10, or some other random value. Not because the Editor or Engine is doing tricks and losing the value, but because the default value given to a variable is just a guess of “whit it is most likely to be” at the time when we gave it that value. Then after testing and iteration the value changes to something else.
so even though the default value should be like 7, but all the instances have been modified to 10 you would still need to quarry the instance for the real value, and to prevent potentially needing to hot load something new into memory at runtime just to quarry a value, and then unload it (maybe it is already loaded, that helps, but still isn’t great). then there is the issue of where the value is coming from, some values don’t fully exist on the Entity until it is Instantiated into the level. for example any value defined in a blueprint, but not modified on the level instance is stored in the blueprint, but once modified on the Level Instance that value now lives on the Level Instance, and that value in the Blueprint doesn’t do anything.
so when you quarry the “default value” of MyInteger which one are you expecting to get: the C++ baseclass if it exists, the Blueprint declaration, or the one given to the Level Instance each one could be different.

Then technically for things marked non-static in the thing in the level is only tangentially related to the object placed into the level outside of PIE. where during PIE anything in the world Hierarchy that is in Yellow-gold text has been created from scratch with a copy of the data from the object put into the level.
if you MUST have the default values defined on say the Blueprint you will need to directly quarry the Reflection system, for unloaded assets that means loading them either though blocking load or Async, and then do a String Compare on the reflection symbol to get at the value on the blueprint, which is slow, and prone to name issues, and can easily break on packaging, so Please really really consider DataTable and DataAsset.


I am guessing that each of these component substrings has a meaning; either at runtime to determine something or to compare against something else.

the best answer would be maybe a dictionary type DataTable, that way if you define a struct where your string is pared with other data bits, and that can include a soft class reference to a component, or UObject, and then when the DataTableRow is given to the object it goes into the DataTableRow, and gets the Component. Just bare in mind that accessing a SoftClassReference, or SoftObjectReference is a blocking load unless you explicitly do AsyncLoad, and to the best of my knowledge that is technically C++ exclusive (it can get into blueprints through some tricks, but it is dynamic delegate callbacks, so C++).
and if the name needs to be appended/Concatenated you can assign it to a different String, and just keep either copies or references to the DataTableRows (maybe just the String key, where if the DataTable is held in a unified place then you can look it up again)

if you do prefer not to use DataTable Or DataAsset then instead of Strings maybe have each one be an enumeration; you are limited to 255 values, but DataTable, and DataAsset will allow for unifying where you are going to be looking for the values in the event something, or everything needs to change.

for the strings specifically after they are appended if you don’t want to keep the pieces separate then looking for a part of a string there are 2 answers, depending on your consistency, and how sure you are about what you are looking for.

  • you can either use “Substrings” to look for something specific, but that is one string at a time, and does character by character compares (if the test string is longer then the String being tested it does auto fail, so you get that, but where we are talking about concatenated strings this is a 1 in a million thing),
  • if you have consistent delineators like in 3DRaven’s example you could use the delineator of [Space] and use the other option of “Parse into Array” where you feed the string, and the delineator in, and get out an array of strings which you can feed into a Switch or Select both of these options is more or less a joke in terms of optimization, and should be done very sparingly.

Hmm, this information confuses me. I don’t know much about the technical side of things.

I think that defaults literally refer to default values ​​that are pre-entered into variables, but is that wrong? My guess is that the defaults are defined before the Construction Script. And this is probably why i can’t override the value from the Construction Script.

For tables I’m using a String Table for translations. By preparing variables that follow certain rules in the template, the translated words can be substituted into them from Format Text. However, the value it references is within the actor.

But as you say, if the default is not necessarily the default, then using Get Class Default might not be a good idea…

a default value of a variable not marked “const” is The value of the variable, or thing up until it is given some other value, and that default value should be expected to change at any time. I am thinking that your intent is that you are going to be changing the value of the variable, and want to know what the starting value was, so you can either do math on the starting value, or reset it to the default.

for that the class default still might not be the correct value, considering that there are up to 3 different “default values” you could be talking about, before we even consider a blueprint inheriting from another blueprint.
for example the C++ class could declare a variable of MyInteger, and set a default value of 9

  • then the first level blueprint could change the “default value” to be 7
  • then in the instance placed in the world that one could have its starting value (similar to a default) to be 2

if you were looking for which value to “reset it to” which one do you actually want, because the C++ class writer could have though 9 was reasonable, and then the person putting the Blueprint together might have though 7 was better, and then the person doing a bunch of testing might have reigned in to the value of 2 being “just right”, and set that for the level instance. The fun fact is on a small team that might all be the same person working multiple weeks apart.

getting the “class default” SHOULD return the one set in the Blueprint, but that would neglect that value set to the level instance (the only way to even try and get the value from the level instance would be to somehow get a hold of the asset data of that specific instance, which would mean probably referencing the Asset’s file which has a completely different meaning in a packaged application), and all of these could be overridden in an instant in a constructor, ConstructionScript(), or even BeginPlay(), and those changes just happen, and getting “Class default” values will never find those.


if you are looking for the “measure of truth”, and want consistency then have a unified place to look up the data from like a DataTable.

a Localization table is a very specialized TMap (dictionary, HashTable if you want to look it up), which is similar to a DataTable. A DataTable is also built on top of a TMap, but it designed not only for structs accessed by FName (a slightly specialized string that is never meant to be modified out of ASCII), but is designed to not be optimized down to binary (so it is almost always human readable even as a raw file)

for example a dataTable for a weapon could have

Key=[Name]
struct WeaponPrefixes
{
    float weightModifier;
    float DurabilityModifier;
    float BaseDamageModifier;
    float ElementalModifier;
    EElementType ElementType;
    ...
    SoftClassReference<UActorComponent> PrefixDefinition;
};

remember to never trust a float to be an exact value except at precisely 2:38.03pm on Tuesday, at a city in Europe chosen at random each week.

then for setting the starting values on the object, after it is spawned have it just request the relevant DataTableRow, and set its values from that. When it comes time to reset or compare against the starting point reference that DataTableRow and use those values.

I think I remember you requesting how to get the Mass from a staticMesh, well if that can be determined from the base value+modifiers from the other components then you don’t really need to look it up from the item specifically.

for runtime stuff DO NOT reference a localized string, because Localization Tables do not work in reverse, and your runtime logic should almost never care what language the user is using (sometimes localization setting does more stuff with meshes and shaders, but that is well outside of this question). if you must reference a string that will presented to the player, localize a copy of it.

  • for DataTables I know I said that the keys are strings, but it just needs to be a string when it is feed into the request. it could be any datatype (except floats because of “approximation”),
    • so you could have it be say an integer so the user would see “Odyn’s Mighty Lighting” as the prefix, but internally it is 28.
    • this helps in 2 ways setting a default value for what DataTable key to use is not prone to human consistency issues in spelling or punctuation, and also the names are a lot easier to change if you need to later.
    • there is technically a small trade off for packing on the Hash function, but that would only have a major impact when you have a LOT of entries.

The reason I have avoided using data tables is because I have encountered issues where editing the custom structures required to create a data table can, in the worst case scenario, destroy the entire project. This was a known bug in UE4 and may have since been fixed, but I’ve since switched to always setting the variables directly in the Blueprint.
During the development phase, it is impossible to know all the variables that will ultimately be needed. I’ve added and removed variables more times than I can count, and I don’t want to deal with the risk of my project collapsing each time.

Anyway, for me, data tables are too slow to use. Instead of sticking to class defaults, I’ll edit from the instance.

use DataAssets, you can edit them as much as you like and create a function to ReturnFormattedText