虚幻引擎基础入门(C++) — 【资源加载 08】

前言

在虚幻中我们需要处理的资源分为:类资源和非类资源。

资源/资产加载到内存中,我们操作需要通过引用来完成,引用分两类:

  • 直接属性引用(硬性引用):直接引用
  • 间接属性引用(软性引用):通过间接机制(如字符串形式的对象路径)来引用

加载方式分为:

同步加载(资源过大会导致游戏程序卡顿)
  • 在加载运行线程中,阻塞线程的流程执行,将线程停止在当前加载逻辑中,加载完成后继续线程的执行逻辑操作
  • 对于加载小资源可以保证资源的不为空,但是加载大资源将导致调用线程卡顿
异步加载
  • 在加载线程中,不阻塞当前线程逻辑加载资源,加载器本身具备线程进行资源加载
  • 比同步加载更加灵活,但维护成本较高,资源加载成功后需要进行回调通知,以完成整个加载流程

一、直接属性引用

编辑器直接加载

        通过使用属性 UPROPERTY 宏标记,将资产对象指针暴露到编辑器面板,从而直接从编辑器面板拾取资产

TSubClassOf

        是提供UClass的安全模板类,可以快速构建某种类型对象数据
        但只能选取模版类型或继承自模版类型的类 / 蓝图

	//1.引用类资源
    //① UClass类:暴露到蓝图中,直接拾取任意类资源(用指针)
    UPROPERTY(EditAnyWhere, BlueprintReadWrite)
    UClass* CharacterClass;
 

    //② TSubclassOf:只能用来拾取 AMyActor 类或其子类(用<>包裹)(记得加头文件)
    UPROPERTY(EditAnyWhere, BlueprintReadWrite)
    TSubclassOf<AMyActor> MyActor;
    MyActor.GetClass();  //获取UClass指针
//2.引用非类资源
	 UPROPERTY(EditAnyWhere, BlueprintReadWrite)
    USoundBase* Sound;  //拾取音频资源
    //拾取音频还可以用:USoundCue(加头文件#include<Sound/USoundCue.h>)

    UPROPERTY(EditAnyWhere, BlueprintReadWrite)
    UStaticMesh* Mesh;  //拾取静态网格体

    UPROPERTY(EditAnyWhere, BlueprintReadWrite)
    UStaticMeshComponent* Mesh;  //静态网格体组件(装载资产的组件)

    UPROPERTY(EditAnyWhere, BlueprintReadWrite)
    USkeletalMesh* SMesh;  //拾取骨骼网格体
 //3.加载类资源和非类资源
	 //UObject类
    UPROPERTY(EditAnyWhere, BlueprintReadWrite)
    UObject* Object;

 构造函数加载

        - 借助构造函数资产加载类进行资源引用

        - ConstructorHelpers可以进行类引用,源资源引用

        - ConstructorHelpers 只能在构造函数中使用,GameInstance中是 Init 函数(需要重载)

常用的资源加载分类:

        FClassFinder:加载创建后的蓝图对象

ConstructorHelpers::FClassFinder<APawn>(TEXT("/Game/Flappybird/Blueprints/BP_Bird")).Class;//返回数据类型是TSubClassof

//使用路径拾取蓝图对象(要加_C)
ConstructorHelpers::FClassFinder<AActor> UnitSelector(TEXT(“Blueprint‘/Game/Blueprints/MyBlueprint.MyBlueprint_C’”));//下划线C必须要加

        FObjectFinder:加载各种资源(如音频,图片,材质,静态网格)

ConstructorHelpers::FObjectFinder<UTexture2D> BarFillObj(TEXT("/Game/UI/HUD/BarFill"));
BarFillTexture = BarFillObj.Object;  //将获取的数据内容指针保存
查找加载

        在只知道目标资源路径的基础上,进行运行时态的资源加载

        资源加载可能会失败或是无效,所以需要对操作的结果进行判定

  • LoadClass:加载类资产,可放在任何地方加装 , 返回UClass指针,可用TSubclassOf来接
TSubclassOf Player1 = LoadClass(NULL, TEXT(“Blueprint’/Game/BP/BP_Actor.BP_Actor_C’”));
  • LoadObject:加载类资源 + 非类资产,返回该类的指针
AMyActor* Player2 = LoadObject(NULL, TEXT(“Blueprint’/Game/BP/BP_Actor.BP_Actor_C’”));
查找加载

此处的 “文件路径” 是复制绝对路径

二、间接属性引用

//(在.h文件中)
//间接属性引用

//1.FSoftClassPath,用于拾取类资源的链接
    UPROPERTY(EditAnywhere)
    FSoftClassPath CharacterPath;


    //2.FSoftObjectPath:(类资源 + 非类资源)暴露到蓝图中拾取的是一个链接,不会进行资源加载
    UPROPERTY(EditAnyWhere)
    FSoftObjectPath SoundPath;

FSoftObjectPath

        是一个简单的结构体,使用一个字符串包含资源的完整名称

        可以在编辑器中拾取资源(与直接属性引用相同),但没有把资源加载到内存(资源的加载需要通过额外的代码编写完成)

        对于资源的拾取并没有特定的要求,所有能够被序列化的资源均能被拾取(类资源,非类资源)

FSoftClassPath

        仅拾取类资源链接

//(在.h文件中)
//间接属性引用

//1.FSoftClassPath,用于拾取类资源的链接
    UPROPERTY(EditAnywhere)
    FSoftClassPath CharacterPath;


    //2.FSoftObjectPath:(类资源 + 非类资源)暴露到蓝图中拾取的是一个链接,不会进行资源加载
    UPROPERTY(EditAnyWhere)
    FSoftObjectPath SoundPath;

三、同步加载和异步加载

  1. 同步加载(加载大资源将导致调用线程卡顿)
  2. 异步加载(资源加载成功后需要进行回调通知)

        FSreamableManager 构建异步处理逻辑,创建在全局游戏的单例对象中,结合FSoftObjectPath进行加载

//(在UECCharacter.h文件中)

#include <Engine/StreamableManager.h>  //资源加载器头文件引入

UCLASS(config=Game)
class AUECCharacter : public ACharacter
{
public:
    //1.同步加载
    //加载播放音效资源
    void LoadPlaySound();
    //2.异步加载
    //① 声明资源加载器(构建为栈对象,需引入头文件,不要构建为堆对象)
    FStreamableManager LoadStream;

    //② 回调通知函数
    void LoadCallBack();
};
/(在UECCharacter.cpp文件中)

#include <Kismet/GameplayStatics.h>  //播放音频头文件引入

void AUECCharacter::LoadPlaySound()
{
    if (!SoundPath.IsValid())  //判断资产链接是否有效
    {
        //如果资产链接无效,则直接设置资产路径(可以用来替代细节面板中的引用)
        SoundPath.SetPath(TEXT("SoundCue'/Game/StarterContent/Audio/Collapse_Cue.Collapse_Cue'"));
    }

    //尝试加载资源
    UObject*Source = SoundPath.TryLoad();
    //1.同步加载(会阻塞线程)
    UObject* Source = LoadStream.LoadSynchronous(SoundPath);
    //2.异步加载
    //① 请求加载,并绑定回调函数(资源,单播)
    LoadStream.RequestAsyncLoad(SoundPath,FStreamableDelegate::CreateUObject(this,&AUECCharacter::LoadCallBack));

}
//② 回调函数调用(表明异步加载完成)
void AUECCharacter::LoadCallBack()
{
    //类型转换Cast
    //SoundPath.ResolveObject():获取异步加载好的资源引用
    USoundBase* Sound = Cast<USoundBase>(SoundPath.ResolveObject());

    if (Sound)
    {
        //播放音效
        UGameplayStatics::PlaySound2D(GetWorld(), Sound);
    }
}

四、同步加载和异步加载

TSoftObjectPtr和TSoftClassPtr

  • TSoftObjectPtr和TSoftClassPtr也分为同步加载与异步加载
UPROPERTY(EditAnywhere)
TSoftObjectPtr<class UStaticMesh> SoftMesh;
UPROPERTY(EditAnywhere)
TSoftClassPtr<class ATestActor> SoftTestActor;
  • TSoftObjectPtr

        同步加载

//(.h 文件)

UPROPERTY(EditAnywhere)
TSoftObjectPtr<class UStaticMesh> SoftMesh;
// 构建为栈对象,需要引入头文件,不要构建为堆对象
// #include "Engine/StreamableManager.h"
FStreamableManager m_Streamable;

//(.cpp文件)

// 可以转换为FSoftObjectPath对象
SoftMesh.ToSoftObjectPath();

// 同步加载
UObject* Source = m_Streamable.LoadSynchronous(SoftMesh);
UStaticMesh* Mesh = Cast<UStaticMesh>(Source);
if (Mesh) 
{
    UKismetSystemLibrary::PrintString(this, TEXT("加载成功!"));
}

异步加载

//(.h文件)

// 异步加载回调函数
void LoadSourceCallback();
//(.cpp文件)

// 异步加载
//需要在初始化函数中绑定回调函数,然后实现回调函数
m_Streamable.RequestAsyncLoad(SoftMesh.ToSoftObjectPath(), FStreamableDelegate::CreateUObject(this, &UTestGameInstance::LoadSourceCallback));
  • TSoftClassPtr
//(.h文件)
    
UPROPERTY(EditAnywhere)
TSoftObjectPtr<class UStaticMesh> SoftMesh;
// 构建为栈对象,需要引入头文件,不要构建为堆对象
// #include "Engine/StreamableManager.h"
FStreamableManager m_Streamable;

//(.cpp文件)

// 同步加载
TSubclassOf<ATestActor> TestActorClass = m_Streamable.LoadSynchronous(SoftTestActor);
if (TestActorClass) 
{
    GetWorld()->SpawnActor<ATestActor>(TestActorClass);
}

//(.cpp文件)

// 异步加载
m_Streamable.RequestAsyncLoad(SoftTestActor.ToSoftObjectPath(), FStreamableDelegate::CreateUObject(this, &UTestGameInstance::LoadSourceCallback));

//回调函数实现
void UTestGameInstance::LoadSourceCallback() {
// 此函数调用,则表明异步加载完成
UClass* TestActorClass = SoftTestActor.Get();
    if (TestActorClass) 
    {
        GetWorld()->SpawnActor<ATestActor>(TestActorClass);
    }
}

总结

以上就是今天要讲的内容,本文仅仅简单介绍了虚幻引擎中资源加载的使用。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值