UE5多人MOBA+GAS 39、制作角色上半身UI
文章目录
- 创建渲染Acotr和显示ActorUI的基类
- 继承基类完善头像渲染功能
创建渲染Acotr和显示ActorUI的基类
RenderActor
#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "RenderActor.generated.h"/*** 渲染专用Actor类,用于场景捕获和渲染到纹理* * 主要功能:* - 创建一个离屏渲染场景* - 捕获指定目标的高质量图像* - 将渲染结果输出到RenderTarget纹理*/
UCLASS()
class CRUNCH_API ARenderActor : public AActor
{GENERATED_BODY()public:// Sets default values for this actor's propertiesARenderActor();/*** 设置渲染目标纹理* @param RenderTarget 要渲染到的目标纹理*/void SetRenderTarget(class UTextureRenderTarget2D* RenderTarget);/*** 执行场景捕获操作* 调用后会将当前场景渲染到预设的RenderTarget*/void UpdateRender();// 获取场景捕获组件(用于进一步配置)FORCEINLINE class USceneCaptureComponent2D* GetCaptureComponent() const { return CaptureComponent; }
protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;private:/** 根组件,用于组织场景层次 */UPROPERTY(VisibleDefaultsOnly, Category = "Render Actor")class USceneComponent* RootComp;/*** 场景捕获组件,核心渲染功能* 将3D场景渲染为2D纹理*/UPROPERTY(VisibleDefaultsOnly, Category = "Render Actor")class USceneCaptureComponent2D* CaptureComponent;
};
#include "RenderActor.h"#include "Components/SceneCaptureComponent2D.h"// Sets default values
ARenderActor::ARenderActor()
{PrimaryActorTick.bCanEverTick = true;// 创建场景锚点作为根组件RootComp = CreateDefaultSubobject<USceneComponent>("Root Comp");SetRootComponent(RootComp);// 创建场景捕获组件并添加到根组件CaptureComponent = CreateDefaultSubobject<USceneCaptureComponent2D>("Capture Component");CaptureComponent->SetupAttachment(RootComp);// 配置捕获参数CaptureComponent->bCaptureEveryFrame = false; // 禁用自动捕获,手动控制CaptureComponent->FOVAngle = 30.f; // 窄视角适合头部特写
}void ARenderActor::SetRenderTarget(UTextureRenderTarget2D* RenderTarget)
{CaptureComponent->TextureTarget = RenderTarget;
}void ARenderActor::UpdateRender()
{if (CaptureComponent){// 捕获场景CaptureComponent->CaptureScene();}
}// Called when the game starts or when spawned
void ARenderActor::BeginPlay()
{Super::BeginPlay();// 只显示当前Actor的组件到捕获画面CaptureComponent->ShowOnlyActorComponents(this);// 将Actor移动到远离主场景的位置,避免干扰SetActorLocation(FVector{0.f, 0.f, 100000.f});
}
继承基类完善头像渲染功能
RenderActorWidget
创建渲染Acotr的UI
PURE_VIRTUAL
跟在纯虚函数后面写一个=0差不多
#pragma once#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "RenderActorWidget.generated.h"class ARenderActor;
class USizeBox;
class UImage;
/*** */
UCLASS()
class CRUNCH_API URenderActorWidget : public UUserWidget
{GENERATED_BODY()
protected:// 构建前回调(可用于初始化参数)virtual void NativePreConstruct() override;// 构建时回调(用于初始化控件、渲染等)virtual void NativeConstruct() override;// 销毁时回调(用于清理资源)virtual void BeginDestroy() override;
private:// 配置渲染Actor(设置渲染目标等)void ConfigureRenderActor();// 派生类实现:生成渲染Actorvirtual void SpawnRenderActor() PURE_VIRTUAL(URenderActorWidget::SpawnRenderActor, ); // 派生类实现:获取渲染Actor实例virtual ARenderActor* GetRenderActor() const PURE_VIRTUAL(URenderActorWidget::GetRenderActor, return nullptr; );// 开始渲染捕获(定时刷新渲染)void BeginRenderCapture();// 更新渲染内容void UpdateRender();// 停止渲染捕获void StopRenderCapture();// 显示渲染结果的图片控件UPROPERTY(meta = (BindWidget))TObjectPtr<UImage> DisplayImage;// 控制渲染区域大小的控件UPROPERTY(meta = (BindWidget))TObjectPtr<USizeBox> RenderSizeBox;// 材质参数名,用于绑定渲染目标纹理UPROPERTY(EditDefaultsOnly, Category = "Render Actor")FName DisplayImageRenderTargetParamName = "RenderTarget";// 渲染区域尺寸UPROPERTY(EditDefaultsOnly, Category = "Render Actor")FVector2D RenderSize;// 渲染帧率UPROPERTY(EditDefaultsOnly, Category = "Render Actor")int32 FrameRate = 24;// 渲染定时器间隔float RenderTickInterval;// 渲染定时器句柄FTimerHandle RenderTimerHandle;// 渲染目标纹理UPROPERTY()TObjectPtr<UTextureRenderTarget2D> RenderTarget;
};
#include "RenderActorWidget.h"#include "RenderActor.h"
#include "Components/Image.h"
#include "Components/SizeBox.h"
#include "Engine/TextureRenderTarget2D.h"void URenderActorWidget::NativePreConstruct()
{Super::NativePreConstruct();// 设置大小RenderSizeBox->SetWidthOverride(RenderSize.X);RenderSizeBox->SetHeightOverride(RenderSize.Y);
}void URenderActorWidget::NativeConstruct()
{Super::NativeConstruct();// 创建特定类型的渲染Actor(由子类实现)SpawnRenderActor();// 配置渲染Actor和渲染目标ConfigureRenderActor();// 启动渲染循环BeginRenderCapture();
}void URenderActorWidget::BeginDestroy()
{// 停止渲染循环(避免内存泄漏)StopRenderCapture();Super::BeginDestroy();
}void URenderActorWidget::ConfigureRenderActor()
{if (!GetRenderActor()){UE_LOG(LogTemp, Error, TEXT("没有渲染Actor,将不会渲染任何内容"));return;}// 创建渲染目标纹理RenderTarget = NewObject<UTextureRenderTarget2D>(this);// 设置格式和尺寸RenderTarget->InitAutoFormat(static_cast<uint32>(RenderSize.X), static_cast<uint32>(RenderSize.Y));RenderTarget->RenderTargetFormat = ETextureRenderTargetFormat::RTF_RGBA8_SRGB; // 使用sRGB格式保证颜色准确// 将渲染目标设置给ActorGetRenderActor()->SetRenderTarget(RenderTarget);// 获取显示图像的动态材质实例UMaterialInstanceDynamic* DisplayImageDynamicMaterial = DisplayImage->GetDynamicMaterial();if (DisplayImageDynamicMaterial){// 绑定渲染目标纹理DisplayImageDynamicMaterial->SetTextureParameterValue(DisplayImageRenderTargetParamName, RenderTarget);}
}void URenderActorWidget::BeginRenderCapture()
{// 计算渲染间隔(秒/帧)RenderTickInterval = 1.f / static_cast<float>(FrameRate);// 获取世界上下文UWorld* World = GetWorld();if (World){// 设置定时器按指定帧率调用渲染更新World->GetTimerManager().SetTimer(RenderTimerHandle, this, &URenderActorWidget::UpdateRender,RenderTickInterval, true // 循环执行);}
}void URenderActorWidget::UpdateRender()
{// 安全检查后执行渲染更新if (GetRenderActor()){GetRenderActor()->UpdateRender();}
}void URenderActorWidget::StopRenderCapture()
{UWorld* World = GetWorld();if (World){// 停止定时器World->GetTimerManager().ClearTimer(RenderTimerHandle);}
}
继承RenderActor
创建SkeletalMeshRenderActor
渲染骨骼网格体
#pragma once#include "CoreMinimal.h"
#include "UI/Common/Rendering/RenderActor.h"
#include "SkeletalMeshRenderActor.generated.h"/*** 用于在UI中渲染骨骼网格体的Actor* 继承自通用渲染Actor,可设置骨骼网格和动画蓝图*/
UCLASS()
class CRUNCH_API ASkeletalMeshRenderActor : public ARenderActor
{GENERATED_BODY()public:// Sets default values for this actor's propertiesASkeletalMeshRenderActor();// 配置骨骼网格和动画蓝图void ConfigureSkeletalMesh(USkeletalMesh* MeshAsset, TSubclassOf<UAnimInstance> AnimBlueprint);protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;private:// 渲染的骨骼网格体组件UPROPERTY(VisibleAnywhere, Category = "Skeletal Mesh Renderer")TObjectPtr<USkeletalMeshComponent> MeshComp;
};
#include "SkeletalMeshRenderActor.h"
#include "Components/SkeletalMeshComponent.h"// Sets default values
ASkeletalMeshRenderActor::ASkeletalMeshRenderActor()
{MeshComp = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Mesh Comp"));MeshComp->SetupAttachment(GetRootComponent());// 禁用碰撞MeshComp->SetCollisionEnabled(ECollisionEnabled::NoCollision);// 设置光照通道,仅使用第二通道(通常用于UI渲染优化)MeshComp->SetLightingChannels(false, true, false);
}void ASkeletalMeshRenderActor::ConfigureSkeletalMesh(USkeletalMesh* MeshAsset, TSubclassOf<UAnimInstance> AnimBlueprint)
{// 设置骨骼网格资源MeshComp->SetSkeletalMeshAsset(MeshAsset);// 设置动画蓝图MeshComp->SetAnimInstanceClass(AnimBlueprint);
}// Called when the game starts or when spawned
void ASkeletalMeshRenderActor::BeginPlay()
{Super::BeginPlay();// 仅在场景捕获时可见(用于UI渲染,不显示在主场景)MeshComp->SetVisibleInSceneCaptureOnly(true);
}
创建其蓝图
设置一下骨骼网格体
调一下位置
不知道这个有啥用
继承RenderActorWidget
创建SkeletalMeshRenderWidget
#pragma once#include "CoreMinimal.h"
#include "UI/Common/Rendering/RenderActorWidget.h"
#include "SkeletalMeshRenderWidget.generated.h"class ASkeletalMeshRenderActor;
/*** 用于在UI中渲染骨骼网格体的Widget* 负责生成和管理骨骼网格渲染Actor*/
UCLASS()
class CRUNCH_API USkeletalMeshRenderWidget : public URenderActorWidget
{GENERATED_BODY()
public:// 构建时回调(初始化控件和渲染Actor)virtual void NativeConstruct() override;private:// 生成骨骼网格渲染Actor实例virtual void SpawnRenderActor() override; // 获取骨骼网格渲染Actor实例virtual ARenderActor* GetRenderActor() const override;// 骨骼网格渲染Actor的类(可在编辑器中指定)UPROPERTY(EditDefaultsOnly, Category = "SKeletal Mesh Render")TSubclassOf<ASkeletalMeshRenderActor> SkeletalMeshRenderActorClass;// 当前生成的骨骼网格渲染Actor实例UPROPERTY()TObjectPtr<ASkeletalMeshRenderActor> SkeletalMeshRenderActor;
};
#include "SkeletalMeshRenderWidget.h"#include "SkeletalMeshRenderActor.h"
#include "GameFramework/Character.h"void USkeletalMeshRenderWidget::NativeConstruct()
{Super::NativeConstruct();// 获取拥有该UI的玩家角色ACharacter* PlayerCharacter = GetOwningPlayerPawn<ACharacter>();if (PlayerCharacter && SkeletalMeshRenderActor){// 配置骨骼网格和动画类SkeletalMeshRenderActor->ConfigureSkeletalMesh(PlayerCharacter->GetMesh()->GetSkeletalMeshAsset(), PlayerCharacter->GetMesh()->GetAnimClass());}}void USkeletalMeshRenderWidget::SpawnRenderActor()
{if (!SkeletalMeshRenderActorClass) return;UWorld* World = GetWorld();if (!World) return;// 设置生成参数FActorSpawnParameters SpawnParams;SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;// 生成渲染ActorSkeletalMeshRenderActor = World->SpawnActor<ASkeletalMeshRenderActor>(SkeletalMeshRenderActorClass, SpawnParams);
}ARenderActor* USkeletalMeshRenderWidget::GetRenderActor() const
{return SkeletalMeshRenderActor;
}
到GameplayWidget
中添加头像UI
// 头像UIUPROPERTY(meta=(BindWidget))TObjectPtr<USkeletalMeshRenderWidget> HeadshotWidget;
创建头像UI
创建一个材质设置为用户界面以及半透明
创建一个材质实例后放到UI的图像中去
最后把这个UI放进GameplayWidget中去
然后就可以渲染出人头了
然后会看到角色的脸色不是很好,可以加点灯泡
加了灯泡后,看起来就亮多了