龙空技术网

UE5开发室内设计软件之材质编辑器:第1篇

飞行小鱼 95

前言:

而今朋友们对“路径编辑器”大约比较关注,同学们都需要了解一些“路径编辑器”的相关内容。那么小编也在网络上网罗了一些关于“路径编辑器””的相关知识,希望咱们能喜欢,我们一起来学习一下吧!

目标:UE5在Runtime下现实自定义材质编辑器

先看这一期完成的效果如下:

这一节可以对于新手学到很多干活,高手跳过,废话不多说,直接开始吧!

步骤1. 创建UE5工程

新建UE5的C++空白项目,记得选择C++,初学者包可以根据自己需要选择是否勾选

项目创建完成后,打开IDE编辑器,我这边是使用RD开发的,据了解UE5可以配置的IDE环境有三种,前两种VS的方案我都用过各有优缺点,个人还是喜欢RD,随便说一下如何切换UE5关联的IDE,在编辑器偏好设置中->通用-源代码,在源代码编辑器中选择Rider选项,重启即可

步骤2. 创建Material_Actor类继承Actor

UE5的C++文件夹中右键新建C++类,父类选择Actor,下一步,输入名称,创建类

步骤3. 为Actor创建静态网格体

首先在Material_Actor.h头文件中定义创建静态网格体的函数,并且为网格体指定给RootComponent,由于材质编辑器可以多个静态网格体切换,所以需要创建常见网格体都给创建出来,我这边是直接创建了5个,如下图

Material_Actor.h需要添加代码:

public:   // 静态网格   UPROPERTY(EditAnywhere, BlueprintReadWrite)   UStaticMeshComponent* SMC_Box;   UPROPERTY(EditAnywhere, BlueprintReadWrite)   UStaticMeshComponent* SMC_Sphere;   UPROPERTY(EditAnywhere, BlueprintReadWrite)   UStaticMeshComponent* SMC_Cone;      UPROPERTY(EditAnywhere, BlueprintReadWrite)   UStaticMeshComponent* SMC_Cylinder;   //UPROPERTY(VisibleAnywhere)   UPROPERTY(EditAnywhere, BlueprintReadWrite)   UStaticMeshComponent* SMC_Plane;// 创建静态网格体void CreateStaticMesh();UStaticMeshComponent*  CreateStaticMeshAlone(const TCHAR* meshName, const TCHAR* path);

在Material_Actor.cpp中实现CreateStaticMesh()和CreateStaticMeshAlone(),由于要创建多个网格体,于是就又定一个函数CreateStaticMeshAlone用来单独生产,CreateStaticMesh在构造函数AMaterial_Actor中调用。

AMaterial_Actor::AMaterial_Actor(){   // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.   PrimaryActorTick.bCanEverTick = true;   CreateStaticMesh();}
void AMaterial_Actor::CreateStaticMesh(){      SMC_Box = CreateStaticMeshAlone(TEXT("MeshBox"),TEXT("StaticMesh'/Engine/BasicShapes/Cube.Cube'"));   SMC_Sphere = CreateStaticMeshAlone(TEXT("MeshSphere"),TEXT("StaticMesh'/Engine/BasicShapes/Sphere.Sphere'"));   SMC_Cone = CreateStaticMeshAlone(TEXT("MeshCone"),TEXT("StaticMesh'/Engine/BasicShapes/Cone.Cone'"));   SMC_Cylinder = CreateStaticMeshAlone(TEXT("MeshCylinder"),TEXT("StaticMesh'/Engine/BasicShapes/Cylinder.Cylinder'"));   SMC_Plane = CreateStaticMeshAlone(TEXT("MeshPlane"),TEXT("StaticMesh'/Engine/BasicShapes/Plane.Plane'"));}
UStaticMeshComponent* AMaterial_Actor::CreateStaticMeshAlone(const TCHAR* meshName,const TCHAR* path){   // 创建box静态网格体组件   UStaticMeshComponent* meshComponent = CreateDefaultSubobject<UStaticMeshComponent>(meshName);   meshComponent->SetupAttachment(RootComponent);   // 加载内置静态网格   ConstructorHelpers::FObjectFinder<UStaticMesh> VisualAsset(path);   if (VisualAsset.Succeeded())   {      meshComponent->SetStaticMesh(VisualAsset.Object);      meshComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));         }   MeshArr.Add(meshComponent);   return meshComponent;}

注意:创建网格体函数需要放到构造函数中执行!

编译完成后,就应该能看到Material_Actor

步骤4. 创建基于Material_Actor蓝图类

通过右键点击Material_Actor选择创建基于Material_Actor的蓝图类来蓝图类,选择存放路径,命名,我这边命名为BP_Material_Actor,双击打开编辑器,看到如下所示

到目前为止BP_Material_Actor的5个静态网格都创建完成了,但是材质部分使用的是系统默认的材质,那么我们还有三个问题需要解决。

1:使用自定义的材质

2:要在runtime可以动态修改材质参数

3:UI与材质交互

步骤5. 创建自定义材质NewMaterial

新建一个材质,作为我们材质的模板

材质制作不是我们这一节的重点,以后会有专门教程讲解,有兴趣或者不懂的同学建议参看材质蓝图相关资料,在这里就不详细说了, 按照下图所示设置材质如下:

这里需要提到的是,材质蓝图中我定义了2个参数,一个是faxian法线参数,一定是Saturation饱和度

步骤6. 创建动态材质实例

可以使用C++也可以使用蓝图创建创建动态材质实例,采用C++的代码如下:

void AMaterial_Actor::CreateMaterialInstaceDynamic(){      static ConstructorHelpers::FObjectFinder<UMaterial> ColorMaterial_Finder(TEXT("Material'/Game/Materials/NewMaterial.NewMaterial'"));   if (ColorMaterial_Finder.Object)   {      ColorMaterial = (UMaterial*)ColorMaterial_Finder.Object;   }   ColorMaterial_Inst = UMaterialInstanceDynamic::Create(ColorMaterial,SMC_Box);   //设置材质参数   //ColorMaterial_Inst->SetVectorParameterValue(FName(TEXT("ccd")),FLinearColor(0.0,0.0,0.0,1.0);   ColorMaterial_Inst->SetScalarParameterValue(FName(TEXT("ccd")),1);      //继续使用World持有动态材质实例,但是把动态材质实例AddToRoot,避免动态材质实例被回收   ColorMaterial_Inst->AddToRoot();      //为静态网格设置材质   SMC_Box->SetMaterial(0, ColorMaterial_Inst);   }

CreateMaterialInstaceDynamic函数也需要在构造函数中实现,值得注意的是ColorMaterial_Inst容易被销毁导致UE5崩溃,所以ColorMaterial_Inst->AddToRoot();确保不被销毁。代码的方式虽然灵活但是细节没有考虑到容易引起崩溃的情况不好调试,解决方案可以参考:

UE4 填坑系列之动态材质实例设置参数崩溃 - 知乎

【UE4 C++】动态修改材质参数

UE4 C++ 记录几个有关材质的知识点_北极熊的奋斗史的博客-CSDN博客

在C++中通过代码给材质中参数设置数据:

//  给一个float类型变量设置值,第一个参数是变量的名称pMat->SetScalarParameterValue(FName("FloatValue"), 1); // 给一个向量类型变量设置值,第一个参数是变量的名称FColor cLineColor = FColor(255, 255, 0, 255);pMat->SetVectorParameterValue(FName("VectorValue"), FLinearColor(cLineColor));       // 给一个类型变量设置值,第一个参数是变量的名称UTexture2D* colorTableTexture;pMat->SetTextureParameterValue(FName("TextureValue"), colorTableTexture);     

后面考虑到动态材质实例是动态创建出来的不方便调试,我这边采用的是蓝图创建。首先函数CreateMaterialToActor用来单独生成动态材质实例,定义如下:

重要修改说明

加下来,在BP_Material_Actor构造函数中为每一个静态网格体调用,如图:

同样的方式,定义函数SetMaterialSaturation:

同样的方式,定义函数SetMaterialSaturation:

步骤7. 制作主界面UI

我这边命名的是:BP_MainUI,双击打开,使用UMG制作UI不是这一节的重点,所以忽略,不会的同学建议学习再来看,如图所示创建UI:

创建饱和度的OnValueChange事件,这样就可以在滑动的时候根据返回的数值传递给到Saturation参数来调节饱和度

步骤8.UI与Actor的材质交互,设置材质参数

这里有个问题是UI怎么获取Actor那?自然想到的就是在UI中定义一个Actor的变量,数据类型就是BP_MaterialActor,然后通过关卡蓝图传进来

打开关卡蓝图

场景中放入BP_MaterialActor,

在关卡蓝图中,

关卡蓝图的开始事件中创建MainUI

设置饱和度事件响应函数

其中GetCurrentMeshComponent代码为:

UFUNCTION(BlueprintCallable)UStaticMeshComponent* GetCurrentMeshComponent();
UStaticMeshComponent* AMaterial_Actor::GetCurrentMeshComponent(){   if (MeshArr.Contains(MeshArr[MeshIndex]))   {      return MeshArr[MeshIndex];   }   return nullptr;}

同理:法线调整蓝图如下:

步骤8.最后讲一下网格切换按钮

这块功能也是做在C++里面的,现在Material_Actor.h声明用来切换的函数取名:SwitchMesh

UFUNCTION(BlueprintCallable)void SwitchMesh();

然后实现其方法:

void AMaterial_Actor::SwitchMesh(){   MeshArr[MeshIndex]->SetVisibility(false,true);      MeshIndex++;   MeshIndex = MeshIndex%MeshArr.Num();      MeshArr[MeshIndex]->SetVisibility(true,true);   //MeshArr[MeshIndex]->SetRelativeLocation(FVector(0,0,0));}

MeshIndex是用来记录当前是那一个网格显示,MeshArr存储了所有网格体,MeshArr数据是在CreateStaticMeshAlone函数中加入的,这样在使用切换网格和获取当前网格体的时候十分方便!

好了,今天这一节就先到这里,希望对大家有所帮助!最后再放几张如图:

饱和度较低情况,向左滑动降低饱和度

高饱和度+低粗糙度

高饱和度+高粗糙度

标签: #路径编辑器