【学习笔记】UE4——TSoftClassPtr<T> ptr/TSoftObjectPtr<T> ptr

前言

本文章仅作为个人学习笔记,本章中包含错误、过时、遗漏知识点等问题,因此请读者发现上述问题请谅解并且欢迎指正。本文更新时间:2020-8-6

引用

虚幻4官方中文文档:
TSoftClassPtr:

https://docs.unrealengine.com/en-US/API/Runtime/CoreUObject/UObject/TSoftClassPtr/index.html

TSoftObjectPtr

https://docs.unrealengine.com/en-US/API/Runtime/CoreUObject/UObject/TSoftObjectPtr/index.html

异步资源加载

https://docs.unrealengine.com/zh-CN/Programming/Assets/AsyncLoading/index.html

个人解读

原理

软指针中存放两个重要变量,其一为指针类型,其二为String(存放路径用)。在生成实例化之前,UE4引擎会在后台自动生成一个默认模板的对象并且不可修改。当使用软指针时,会先寻找内存中的指针对象,如果没有则根据路径去硬盘中寻找。因此多半情况是在对象未正式实例化时,提前引用其模板对象。本文章主要通过以下代码,获得软指针,并允许其在笔者创建的组件上,方便赋值。

    UPROPERTY(EditAnywhere)
	TSoftClassPtr<UUserWidget> ResourcesWidgetClassPtr;
	UPROPERTY(EditAnywhere)
	TMap<TSubclassOf<ABaseResources>, int> CharacterResourcesNumber;

目的

FSoftObjectPaths和TSoftObjectPtr
让美术或设计师引用资源的最简单方法是创建硬指针的UProperty并为它指定一个类别。在UE4中,如果有一个硬UObject指针属性引用了一个资源,则加载包含这个属性的对象(放在贴图中,或者从gameinfo等引用)时,就会加载这个资源。如果处理不当,就会在游戏开始时加载全部资源。如果您希望美术/设计师能够使用同一个UI作为硬指针来引用特定资源,而不必总是加载被引用资源,可以使用FSoftObjectPathTSoftObjectPtr

FSoftObjectPath是一个简单的结构体,其中有一个字符串包含资源的完整名称。如果您在类中添加这个类型的属性,它就会像UObject *属性一样显示在编辑器中。它还会正确处理烘焙和重定向,因此如果您使用SoftObjectPath,就一定能在设备上正确工作。TSoftObjectPtr基本上是包含了FSoftObjectPathTWeakObjectPtr,将用于设置特定类的模板,这样就可以限制编辑器UI仅允许选择特定类。如果被引用资源存在于内存中,则TSoftObjectPtr.Get()将返回这个资源。如果不存在,可以调用ToSoftObjectPath()来找出它引用的资源,使用下述方法加载这个资源,然后再次调用TSoftObjectPtr.Get()来取消引用。

如果美术或设计师要手动设置引用,则TSoftObjectPtrs和Soft Object Paths十分有用,但如果想要通过查询等功能来查找符合特定要求的资源,而不加载所有资源,则可以使用资源注册表和对象库。

案例

在这里插入图片描述
//注:TSubclassof<T>作用原理与TSoftClassPtr<T>近似
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这段代码存在多个问题。 首先,在主函数中,`SmartPtr<int> ptr1 = new int(0);` 会创建一个 `SmartPtr` 对象,并将一个 `int` 指针赋值给它。然而,这个指针没有通过 `new` 运算符分配内存,应该使用 `SmartPtr<int> ptr1(new int(0));` 来分配内存并创建 `SmartPtr` 对象。 其次,在 `SmartPtr` 类中,拷贝构造函数 `SmartPtr(SmartPtr<T> & rhs)` 和赋值运算符 `operator=` 都没有考虑到资源所有权的问题。当使用 `SmartPtr<int> ptr2(ptr1);` 进行拷贝构造时,`ptr2` 和 `ptr1` 将拥有相同的指针,当其中一个 `SmartPtr` 对象被销毁时,它将删除指针,导致另一个 `SmartPtr` 对象持有一个无效的指针。同样的问题也存在于 `ptr3=ptr2;` 的赋值操作中。为了解决这个问题,应该实现深拷贝和移动语义。 最后,在 `SmartPtr` 类中,`pointee` 应该是一个指针类型,而不是一个对象类型。因为在析构函数中使用了 `delete` 运算符,它只能删除指针类型的资源,而无法删除对象类型的资源。 下面是修正后的代码: ```c++ template <class T> class SmartPtr { public: SmartPtr(T* p = nullptr) : pointee(p) {} ~SmartPtr() { delete pointee; } SmartPtr(const SmartPtr& rhs) : pointee(rhs.pointee ? new T(*rhs.pointee) : nullptr) {} SmartPtr(SmartPtr&& rhs) : pointee(rhs.pointee) { rhs.pointee = nullptr; } SmartPtr& operator=(SmartPtr rhs) { std::swap(pointee, rhs.pointee); return *this; } private: T* pointee; }; int main() { SmartPtr<int> ptr1(new int(0)); SmartPtr<int> ptr2(ptr1); SmartPtr<int> ptr3; ptr3 = ptr2; return 0; } ``` 在修改后的代码中,使用了深拷贝和移动语义,修复了资源所有权的问题。同时,在 `SmartPtr` 类中,`pointee` 被定义为指针类型,可以正确地释放资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值