文章目录
创建渲染Acotr和显示ActorUI的基类
RenderActor
cpp
#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 properties
ARenderActor();
/**
* 设置渲染目标纹理
* @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 spawned
virtual void BeginPlay() override;
private:
/** 根组件,用于组织场景层次 */
UPROPERTY(VisibleDefaultsOnly, Category = "Render Actor")
class USceneComponent* RootComp;
/**
* 场景捕获组件,核心渲染功能
* 将3D场景渲染为2D纹理
*/
UPROPERTY(VisibleDefaultsOnly, Category = "Render Actor")
class USceneCaptureComponent2D* CaptureComponent;
};
cpp
#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差不多
cpp
#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();
// 派生类实现:生成渲染Actor
virtual 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;
};
cpp
#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格式保证颜色准确
// 将渲染目标设置给Actor
GetRenderActor()->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
渲染骨骼网格体
cpp
#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 properties
ASkeletalMeshRenderActor();
// 配置骨骼网格和动画蓝图
void ConfigureSkeletalMesh(USkeletalMesh* MeshAsset, TSubclassOf<UAnimInstance> AnimBlueprint);
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
private:
// 渲染的骨骼网格体组件
UPROPERTY(VisibleAnywhere, Category = "Skeletal Mesh Renderer")
TObjectPtr<USkeletalMeshComponent> MeshComp;
};
cpp
#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
cpp
#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;
};
cpp
#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;
// 生成渲染Actor
SkeletalMeshRenderActor = World->SpawnActor<ASkeletalMeshRenderActor>(SkeletalMeshRenderActorClass, SpawnParams);
}
ARenderActor* USkeletalMeshRenderWidget::GetRenderActor() const
{
return SkeletalMeshRenderActor;
}
到GameplayWidget
中添加头像UI
cpp
// 头像UI
UPROPERTY(meta=(BindWidget))
TObjectPtr<USkeletalMeshRenderWidget> HeadshotWidget;
创建头像UI
创建一个材质设置为用户界面以及半透明
创建一个材质实例后放到UI的图像中去

最后把这个UI放进GameplayWidget中去
然后就可以渲染出人头了
然后会看到角色的脸色不是很好,可以加点灯泡
加了灯泡后,看起来就亮多了