{"id":3095,"date":"2021-01-02T13:56:29","date_gmt":"2021-01-02T05:56:29","guid":{"rendered":"http:\/\/blog.coolcoding.cn\/?p=3095"},"modified":"2021-01-02T19:43:48","modified_gmt":"2021-01-02T11:43:48","slug":"creating-a-new-asset-type","status":"publish","type":"post","link":"https:\/\/blog.coolcoding.cn\/?p=3095","title":{"rendered":"Creating a new Asset type"},"content":{"rendered":"\n<p> At some point in your project, you might need to create a new custom Asset class, for example, an Asset to store conversation data in an RPG. To properly integrate these with\u00a0Content Browser, you&#8217;ll need to create a new\u00a0Asset type. <\/p>\n\n\n\n<h1 class=\"wp-block-heading\">How to do it&#8230;<\/h1>\n\n\n\n<ol><li>Create a new C++ class based on&nbsp;UObject&nbsp;called&nbsp;MyCustomAsset:<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/blog.coolcoding.cn\/wp-content\/uploads\/2021\/01\/d4eb0573-b97d-4470-90e8-3627adcf9c0d.png\" alt=\"\"\/><\/figure>\n\n\n\n<ol><li>Open up the script and update the code of the&nbsp;.h&nbsp;file to the following:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">#pragma once<br><br>#include \"CoreMinimal.h\"<br>#include \"UObject\/NoExportTypes.h\"<br>#include \"MyCustomAsset.generated.h\"<br><br>\/**<br> * <br> *\/<br>UCLASS()<br>class CHAPTER_10_API UMyCustomAsset : public UObject<br>{<br>  GENERATED_BODY()<br><br><strong>public:<\/strong><br><strong>    UPROPERTY(EditAnywhere, Category = \"Custom Asset\")<\/strong><br><strong>    FString Name;<\/strong><br>  <br>};<\/pre>\n\n\n\n<ol><li>Next, create a class based on&nbsp;UFactory:<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/blog.coolcoding.cn\/wp-content\/uploads\/2021\/01\/e3e7c79e-3eeb-4cc4-a1e2-cd8e5371e942.png\" alt=\"\"\/><\/figure>\n\n\n\n<ol><li>Give the script a name of&nbsp;CustomAssetFactory&nbsp;and press the&nbsp;Create Class&nbsp;button.<\/li><li>Open the script in Visual Studio and update the&nbsp;CustomAssetFactory.h&nbsp;file to the following:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">#pragma once<br><br>#include \"CoreMinimal.h\"<br>#include \"Factories\/Factory.h\"<br>#include \"CustomAssetFactory.generated.h\"<br><br>UCLASS()<br>class CHAPTER_10_API UCustomAssetFactory : public UFactory<br>{<br>    GENERATED_BODY()<br>    <br>public:<br>    UCustomAssetFactory();<br><br>    virtual UObject* FactoryCreateNew(UClass* InClass,<br>        UObject* InParent, FName InName, EObjectFlags Flags,<br>        UObject* Context, FFeedbackContext* Warn, FName<br>        CallingContext) override;<br>};<br> <\/pre>\n\n\n\n<ol><li>Then, switch over to the&nbsp;CustomAssetFactory.cpp&nbsp;file and implement the class:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">#include \"CustomAssetFactory.h\" <br><strong>#include \"Chapter_10.h\"<\/strong><br><strong>#include \"MyCustomAsset.h\" <\/strong><br><br><br><strong>UCustomAssetFactory::UCustomAssetFactory()<\/strong><br><strong>    :Super()<\/strong><br><strong>{<\/strong><br><strong>    bCreateNew = true;<\/strong><br><strong>    bEditAfterNew = true;<\/strong><br><strong>    SupportedClass = UMyCustomAsset::StaticClass();<\/strong><br><strong>}<\/strong><br><br><strong>UObject* UCustomAssetFactory::FactoryCreateNew(UClass*<\/strong><br><strong>    InClass, UObject* InParent, FName InName, EObjectFlags<\/strong><br><strong>    Flags, UObject* Context, FFeedbackContext* Warn, FName<\/strong><br><strong>    CallingContext)<\/strong><br><strong>{<\/strong><br><strong>    auto NewObjectAsset = NewObject&lt;UMyCustomAsset&gt;(InParent,<\/strong><br><strong>        InClass, InName, Flags);<\/strong><br><strong>    return NewObjectAsset;<\/strong><br><strong>}<\/strong><\/pre>\n\n\n\n<ol><li>Compile your code and open the editor.<\/li><li>Right-click in&nbsp;Content Browser, from the&nbsp;Content&nbsp;folder and, under the&nbsp;Miscellaneous&nbsp;tab of the&nbsp;Create Advanced Asset&nbsp;section, you should see your new class and be able to create instances of your new custom type:<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/blog.coolcoding.cn\/wp-content\/uploads\/2021\/01\/df0751b0-3259-47e3-b851-07fd9e1401ba.png\" alt=\"\"\/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">How it works&#8230;<\/h1>\n\n\n\n<p>The first class is the actual object that can exist in the game at runtime. It&#8217;s your texture, data file, or curve data&nbsp;\u2013&nbsp;whatever you require.<\/p>\n\n\n\n<p>For the purpose of this recipe, the simplest example is an asset that has an&nbsp;FString&nbsp;property to contain a name.<\/p>\n\n\n\n<p>The property is marked as&nbsp;UPROPERTY&nbsp;so that it remains in memory, and additionally marked as&nbsp;EditAnywhere&nbsp;so that it is editable on both the default object and on instances of it.<\/p>\n\n\n\n<p>The second class is&nbsp;Factory. Unreal uses the&nbsp;Factory&nbsp;design pattern to create instances of assets.<\/p>\n\n\n\n<p>This means that there is a generic base&nbsp;Factory&nbsp;that uses virtual methods to declare the interface of object creation, and then&nbsp;Factory&nbsp;subclasses are responsible for creating the actual object in question.<\/p>\n\n\n\n<p>The advantage of this approach is that the user-created subclass can potentially instantiate one of its own subclasses if required; it hides the implementation details regarding deciding which object to create away from the object requesting the creation.<\/p>\n\n\n\n<p>With&nbsp;UFactory&nbsp;as our base class, we include the appropriate header.<\/p>\n\n\n\n<p>The constructor is overridden, because there are a number of properties that we want to set for our new factory after the default constructor has run.<\/p>\n\n\n\n<p>bCreateNew&nbsp;signifies that the factory is currently able to create a new instance of the object in question from scratch.<\/p>\n\n\n\n<p>bEditAfterNew&nbsp;indicates that we would like to edit the newly created object immediately after creation.<\/p>\n\n\n\n<p>The&nbsp;SupportedClass&nbsp;variable is an instance of&nbsp;UClass&nbsp;containing reflection information about the type of object the factory will create.<\/p>\n\n\n\n<p>The most significant function of our&nbsp;UFactory&nbsp;subclass is the actual factory method&nbsp;\u2013&nbsp;FactoryCreateNew.<\/p>\n\n\n\n<p>FactoryCreateNew&nbsp;is responsible for determining the type of object that should be created, and using&nbsp;NewObject&nbsp;to construct an instance of that type. It passes a number of parameters through to the&nbsp;NewObject&nbsp;call.<\/p>\n\n\n\n<p>InClass&nbsp;is the class of object that will be constructed.&nbsp;InParent&nbsp;is the object that should be containing the new object that will be created. If this isn&#8217;t specified, the object is assumed to go into the transient package, which means that it won&#8217;t be automatically saved.&nbsp;Name&nbsp;is the name of the object to be created.&nbsp;Flags&nbsp;is a bitmask of creation flags that control things such as making the object visible outside of the package it is contained in.<\/p>\n\n\n\n<p>Within&nbsp;FactoryCreateNew, decisions can be made regarding which subclass should be instantiated. Other initialization can also be performed; for example, if there are sub-objects that require manual instantiation or initialization, they can be added here.<\/p>\n\n\n\n<p>An example from the engine code for this function is as follows:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">UObject* UCameraAnimFactory::FactoryCreateNew(UClass* <br> Class,UObject* InParent,FName Name,EObjectFlags <br> Flags,UObject* Context,FFeedbackContext* Warn) \n{ \n  UCameraAnim* NewCamAnim = <br>   NewObject&lt;UCameraAnim&gt;(InParent, Class, Name, Flags);  NewCamAnim-&gt;CameraInterpGroup = <br>   NewObject&lt;UInterpGroupCamera&gt;(NewCamAnim); \n  NewCamAnim-&gt;CameraInterpGroup-&gt;GroupName = Name; \n  return NewCamAnim; \n} <\/pre>\n\n\n\n<p>As we can see, there&#8217;s a second call to&nbsp;NewObject&nbsp;to populate the&nbsp;CameraInterpGroup&nbsp;member of the&nbsp;NewCamAnim&nbsp;instance.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>At some point in your project, you might need to create [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27,1],"tags":[26],"_links":{"self":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/3095"}],"collection":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3095"}],"version-history":[{"count":1,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/3095\/revisions"}],"predecessor-version":[{"id":3102,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/3095\/revisions\/3102"}],"wp:attachment":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3095"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3095"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3095"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}