本文主要介绍了在虚幻引擎中创建资源的方法,包括创建工具创建资源、初始化资源、管理资源等需求。文章详细描述了创建不同类型资源(如Mesh Asset、Material Instance Asset、Texture等)的过程,并提供了相应的代码示例。此外,文章还概述了如何通过AssetTools提供的AssetFactory来创建资源。
文章介绍了在虚幻引擎中创建资源的固定格式,包括创建Package、创建对应的UObject、填充数据、通知资源浏览器等步骤。
文章提供了创建Mesh Asset的详细步骤和代码示例,包括创建Package、创建Object、初始化资源等。
文章介绍了创建Material Instance Asset和Texture的方法,包括使用AssetTools提供的AssetFactory来创建资源的过程。
文章给出了在编辑器时间内创建数据(如Texture)的示例代码,并解释了如何填充Source数据。
MY BLOG DIRECTORY:
INTRODUCTION:
有时候我们需要写工具创建资源,初始化资源,管理资源等需求,比如合并DC的时候需要重新创建贴图,管理材质的时候需要创建并指认材质球,设置材质球等。
在一切开始之前需要清楚虚幻的资源结构以及合编辑器的关系。首先虚幻中有大量的类型,UMaterial,MaterialInstance,Texture,StaticMesh等等,这些资源从外部导入到引擎的时候做了一次数据抽取,如贴图资源模型资源等。这些数据被放在了一个UObject里,然后这个UObject放在一个Package里。
拿贴图的数据导入为例,如下图所示。
引擎会抽取数据然后创建对应的UTexture。使用创建的UTexture填充其Source。所以Unreal的资源创建有一个固定格式
(1)New一个Package
(2)New一个对应的UObject,在此时指认Package合UObject
(3)向这个UObject里填充数据
(4)MarkDirty,通知资源浏览器这里创建了一个新资源,然后保存。
MAIN CONTENT:
(1)Create Mesh Asset with c++
先来一段简单的
按下按钮后创建一个新的模型资源,代码如下:
FString CreatedMeshName = TEXT("TestMesh");
FString AssetPath = AssetDatas[0].PackagePath.ToString() + TEXT("/Content");
UPackage* NewMeshPack = CreatePackage(nullptr, *AssetPath);
UStaticMesh* NewStaticMesh = NewObject<UStaticMesh>(NewMeshPack, FName(*CreatedMeshName), RF_Public | RF_Standalone);
FAssetRegistryModule
::AssetCreated(NewStaticMesh);
NewMeshPack->MarkPackageDirty();
过程也是非常简单的,首先先创建一个Package,然后New一个mesh,在NewObject方法中就会把这个新创建的UObject和Package指认,然后通知ContentBrower我们创建了这个新资源,请求它加载即可。
这里创建的是一个空的MeshAsset,如果想要给MeshAsset里加模型的顶点信息等,可以通过设置NewStaticMesh->SourceModels来给MeshAsset增加资源信息。
然后是我写的:
【1】创建Package
【2】创建Object
【3】初始化资源
/************************************************************************/
/* Init Static Mesh */
/************************************************************************/
StaticMesh->InitResources();
StaticMesh->LightingGuid = FGuid::NewGuid();
// Determine which texture coordinate map should be used for storing/generating the lightmap UVs
const uint32 LightMapIndex = FMath::Min(MaxInUseTextureCoordinate + 1, (uint32)MAX_MESH_TEXTURE_COORDS - 1);
// Add source to new StaticMesh
for
(FRawMesh& RawMesh : RawMeshes)
{
if (RawMesh.IsValidOrFixable())
{
FStaticMeshSourceModel& SrcModel = StaticMesh->AddSourceModel();
SrcModel.BuildSettings.bRecomputeNormals = false;
SrcModel.BuildSettings.bRecomputeTangents = false;
SrcModel.BuildSettings.bRemoveDegenerates = true;
SrcModel.BuildSettings.bUseHighPrecisionTangentBasis = false;
SrcModel.BuildSettings.bUseFullPrecisionUVs = false;
SrcModel.
BuildSettings.bGenerateLightmapUVs = true;
SrcModel.BuildSettings.SrcLightmapIndex = 0;
SrcModel.BuildSettings.DstLightmapIndex = LightMapIndex;
SrcModel.SaveRawMesh(RawMesh);
}
}
// Copy materials to new mesh
//for (UMaterialInterface* Material : Materials)
//{
// StaticMesh->StaticMaterials.Add(FStaticMaterial(Material));
//}
//Force to use one material to render this mesh, reducing draw call on ceil phong platform
StaticMesh->StaticMaterials.SetNum(1);
StaticMesh->StaticMaterials[0] =
FStaticMaterial(MergeOneMaterial);
//Set the Imported version before calling the build
StaticMesh->ImportVersion = EImportStaticMeshVersion::LastVersion;
// Set light map coordinate index to match DstLightmapIndex
StaticMesh->LightMapCoordinateIndex = LightMapIndex;
// setup section info map
for (int32 RawMeshLODIndex = 0; RawMeshLODIndex < RawMeshes.Num(); RawMeshLODIndex++)
{
const FRawMesh& RawMesh = RawMeshes[RawMeshLODIndex];
TArray UniqueMaterialIndices;
for (int32 MaterialIndex : RawMesh.FaceMaterialIndices)
{
UniqueMaterialIndices.AddUnique(MaterialIndex);
}
int32 SectionIndex = 0;
for (int32 UniqueMaterialIndex : UniqueMaterialIndices)
{
StaticMesh->SectionInfoMap.Set(RawMeshLODIndex, SectionIndex, FMeshSectionInfo(UniqueMaterialIndex));
SectionIndex++;
}
}
StaticMesh->OriginalSectionInfoMap.CopyFrom(
StaticMesh->SectionInfoMap);
// Build mesh from source
StaticMesh->Build(false);
StaticMesh->PostEditChange();
【4】MarkDirty然后通知资源浏览器
StaticMesh->MarkPackageDirty();
告知资源浏览器
FAssetRegistryModule::AssetCreated(StaticMesh);
(2)Create Material Instance Asset with c++
FString MaterialInsBaseName = "MI_";
MaterialInsBaseName += AssetDatas[i].AssetName.ToString();
FString AssetPath = AssetDatas[i].PackagePath.ToString() + TEXT("/Content");
UPackage* NewMatInsPack = CreatePackage(nullptr, *AssetPath);
UMaterialInstanceConstantFactoryNew* Factory = NewObject<UMaterialInstanceConstantFactoryNew>();
FAssetToolsModule& AssetToolsModule = FModuleManager