1、通过MeshDescription在运行时构建StaticMesh并设置碰撞、修改材质
1、MyActor.h
(图片来源网络,侵删)
//MyActor.h #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "MyActor.generated.h" UCLASS() class CONTROLLER_API AMyActor : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties AMyActor(); UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Polygon") TObjectPtr PolygonComponent; FPolygonGroupID GroupId; UPROPERTY(EditAnywhere, Category = "Polygon") TArray Coodinates; TObjectPtr Polygon; UPROPERTY(EditAnywhere, Category = "Polygon") UMaterialInterface* Material; protected: // Called when the game starts or when spawned virtual void BeginPlay() override; virtual void OnConstruction(const FTransform& Transform) override; public: // Called every frame virtual void Tick(float DeltaTime) override; TObjectPtr BuildPolygon(TArray InPositions); };
2、MyActor.cpp
//MyActor.cpp #include "MyActor.h" #include "StaticMeshAttributes.h" #include "CompGeom/PolygonTriangulation.h" #include #include // Sets default values AMyActor::AMyActor() { // 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; PolygonComponent = CreateDefaultSubobject(TEXT("PolygonComponent"), false); SetRootComponent(PolygonComponent); } // Called when the game starts or when spawned void AMyActor::BeginPlay() { Super::BeginPlay(); if(Coodinates.Num()) { Material = LoadObject(this, TEXT("/Engine/BasicShapes/BasicShapeMaterial.BasicShapeMaterial")); PolygonComponent->SetStaticMesh(BuildPolygon(Coodinates)); PolygonComponent->SetMaterial(0,Material); //PolygonComponent->SetForcedLodModel(1); } } void AMyActor::OnConstruction(const FTransform& Transform) { if (!IsTemplate()) { if (Coodinates.Num()) { //加载虚幻引擎自带的材质 Material = LoadObject(this, TEXT("/Engine/BasicShapes/BasicShapeMaterial.BasicShapeMaterial")); //将生成的StaticMesh挂载到StaticMeshComponent上 BuildPolygon(Coodinates); PolygonComponent->SetStaticMesh(Polygon); //在StaticMeshComponent上设置材质,坑1:StaticMesh也有一个SetMaterial方法,但是它是仅在编辑器状态下可用的,调用了这个方法打包时会报错,打包就失败了,而StaticMeshComponent的SetMaterial方法没有这个问题,且材质能够成功应用到StaticMesh上 PolygonComponent->SetMaterial(0, Material); } } } // Called every frame void AMyActor::Tick(float DeltaTime) { Super::Tick(DeltaTime); } FBox2D computeMinRectangle(TArray InPositions) { FBox2D result; uint8 num = InPositions.Num(); if (num currentPoint.X ? maxX : currentPoint.X; maxY = maxY > currentPoint.Y ? maxY : currentPoint.Y; minX = minX GetStaticMaterials().Add(FStaticMaterial()); FMeshDescription meshDesc; FStaticMeshAttributes attributes(meshDesc); //注册默认的静态模型属性 attributes.Register(); //FMeshDescriptionBuilder用于设置顶点、法线、UV坐标等信息 FMeshDescriptionBuilder meshDescBuilder; meshDescBuilder.SetMeshDescription(&meshDesc); //允许使用多边形组 meshDescBuilder.EnablePolyGroups(); //设置UV坐标的级数为1 meshDescBuilder.SetNumUVLayers(1); TArray vertexIDs; const int count = InPositions.Num(); vertexIDs.SetNum(count); TArray Positions2D; for (int32 i = 0; i BuildFromMeshDescriptions(meshDescPtrs, mdParams); //坑3:如果要给StaticMeshComponent绑定鼠标的click、hover等时间的话,需要调用下面这段代码以启用复杂碰撞,因为click等事件也是基于射线检测进行判断的,但是它检测的是复杂碰撞(TraceComplex参数值为true),因此如果不调用下面这段代码,click等事件是不会生效的。注意:这里不要创建BodySetup,在前面的BuildFromMeshDescriptions方法的函数实现里面已经为StaticMesh创建了一个BodySetup,并为其赋予了一些值。 if (UBodySetup* bodySetup = Polygon->GetBodySetup()) { bodySetup->DefaultInstance.SetCollisionProfileName(UCollisionProfile::BlockAll_ProfileName); bodySetup->CollisionTraceFlag = CTF_UseSimpleAsComplex; bodySetup->bGenerateMirroredCollision = false; } return Polygon; }
3、总结
1)运行时修改StaticMesh的材质要调用StaticMeshComponent的SetMaterial方法而不是StaticMesh的SetMaterial方法,因为StaticMesh的SetMaterial方法仅在编辑器状态下可用,会导致你打包失败;
2)想要在运行时修改StaticMesh的材质,首先要确保StaticMesh有材质插槽,为StaticMesh增加材质插槽的方法如上,一定不能使用StaticMesh的AddMaterial方法,运行时状态下无效;
3)想要给StaticMesh绑定click、hover等事件,需要为其启用复杂碰撞,代码如上,但是不使用那段代码也有碰撞,只是click、hover等事件不生效。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。