TAssetPtr
因为在wiki上已经有介绍TAssetPtr的内容了,所以我就直接翻译了,并且在末尾给予一定的补充。以下是翻译自wiki的内容:
一般情况下,我们无需将这个场景中所有Asset都加载了再进入游戏,我们可以先加载必要Asset,在进入场景后,异步加载剩余的非必要资源。而TAssetPtr可以解决这个问题。TAssetPtr类似于标准指针,其区别在于TAssetPtr指向的资产可能已经加载,也可能还没有加载,如果资产没有加载,则它包含加载该资产所需的信息。(TAssetPtr属于弱指针)
一个简单的引用Asset的方法就是创建带有UProperty标记的TAssetPtr成员变量,并且在编辑器中指定想要加载的Asset。本质上是TSoftClassPtr,包含了FSoftObjectPtr对象。可以通过FSoftObjectPath构造,并用其监视Asset的状态。
类型
变量 | 描述 |
---|---|
TAssetPtr |
指向尚未加载但可以根据请求加载的资产的指针 |
TAssetSubclassOf |
指向已定义的基类的子类的指针,该子类尚未加载,但可以根据请求加载。用于指向蓝图而不是基本component。(大概是因为蓝图是Asset) |
关键功能
.h
/** 定义Asset指针. 别忘记添加UPROPERTY标记 */
UPROPERTY(EditAnywhere)
TAssetPtr<MyClass> MyAssetPointer;
/** 定义子类版本. */
UPROPERTY(EditAnywhere)
TAssetSubclassOf<MyBaseClass> MyAssetSubclassOfPointer;
.cpp
// 调用IsValid()去测试这个AssetPtr是不是指向一个有效的UObject
MyAssetPointer.IsValid();
//调用Get()来返回其指向的UObject(在UObject存在的情况下)
MyAssetPointer.Get();
/** 特别注意TAssetSubclassOf的Get(),它返回的是UClass的指针!! */
MyAssetSubclassOfPointer.Get()
/** 要正确使用UClass指针,必须使用GetDefaultObject<T>()来获得指向UObject或派生类的指针 */
MyAssetSubclassOfPointer.Get()->GetDefaultObject<MyBaseClass>()
// 调用ToStringReference()返回希望加载的Asset的FStringAssetReference
MyAssetPointer.ToStringReference();
如何使用
变量 | 描述 |
---|---|
FStreamableManager | 运行时的Asset流控制管理器,这是用户定义的对象,应该被定义在类似GameInstance之类的方便访问的对象中。 |
FStringAssetReference | 一个包含Asset应用字符串的结构体,能对Asset进行弱引用。 |
Asset载入器
FStreamableManager是异步资源加载器,最好定义在类似GameInstance之类持久性对象中,原因有下:
- 访问方便,这使得在需要时加载资产变得很容易。
- 具备持久性,因为你永远不想在加载对象时丢失或销毁对FStreamableManager的引用。
使用方法
简单异步载入
允许您加载单个资产并获得它的强引用。这意味着在您使用unload手动卸载它之前,它永远不会被垃圾回收。(这个 方法已经被废弃,请使用RequestAsyncLoad,并设置bManageActiveHandle为true)
// the .h
TAssetPtr<ABaseItem> MyItem;
// the .cpp
FStringAssetReference AssetToLoad
AssetToLoad = MyItem.ToStringReference();
AssetLoader.SimpleAsyncLoad(AssetToLoad);
请求式异步载入
//the .h
TArray< TAssetPtr<ABaseItem> > MyItems;
// the .cpp
TArray<FStringAssetReference> AssetsToLoad
for(TAssetPtr<ABaseItem>& AssetPtr : MyItems) // C++11 ranged loop
{
AssetsToLoad.AddUnique(AssetPtr.ToStringReference());
}
AssetLoader.RequestAsyncLoad(AssetsToLoad, FStreamableDelegate::CreateUObject(this, &MyClass::MyFunctionToBeCalledAfterAssetsAreLoaded));
PS.实际看过代码之后发现这个RequestAsyncLoad还有一个回调版本的。
/**
* This is the primary streamable operation. Requests streaming of one or more target objects. When complete, a delegate function is called. Returns a Streamable Handle.
*
* @param TargetsToStream Assets to load off disk
* @param DelegateToCall Delegate to call when load finishes. Will be called on the next tick if asset is already loaded, or many seconds later
* @param Priority Priority to pass to the streaming system, higher priority will be loaded first
* @param bManageActiveHandle If true, the manager will keep the streamable handle active until explicitly released
* @param bStartStalled If true, the handle will start in a stalled state and will not attempt to actually async load until StartStalledHandle is called on it
* @param DebugName Name of this handle, will be reported in debug tools
*/
TSharedPtr<FStreamableHandle> RequestAsyncLoad(const TArray<FSoftObjectPath>& TargetsToStream, FStreamableDelegate DelegateToCall = FStreamableDelegate(), TAsyncLoadPriority Priority = DefaultAsyncLoadPriority, bool bManageActiveHandle = false, bool bStartStalled = false, const FString& DebugName = TEXT("RequestAsyncLoad ArrayDelegate"));
TSharedPtr<FStreamableHandle> RequestAsyncLoad(const FSoftObjectPath& TargetToStream, FStreamableDelegate DelegateToCall = FStreamableDelegate(), TAsyncLoadPriority Priority = DefaultAsyncLoadPriority, bool bManageActiveHandle = false, bool bStartStalled = false, const FString& DebugName = TEXT("RequestAsyncLoad SingleDelegate"));
/** Lambda Wrappers. Be aware that Callback may go off multiple seconds in the future. */
TSharedPtr<FStreamableHandle> RequestAsyncLoad(const TArray<FSoftObjectPath>& TargetsToStream, TFunction<void()>&& Callback, TAsyncLoadPriority Priority = DefaultAsyncLoadPriority, bool bManageActiveHandle = false, bool bStartStalled = false, const FString& DebugName = TEXT("RequestAsyncLoad ArrayLambda"));
TSharedPtr<FStreamableHandle> RequestAsyncLoad(const FSoftObjectPath& TargetToStream, TFunction<void()>&& Callback, TAsyncLoadPriority Priority = DefaultAsyncLoadPriority, bool bManageActiveHandle = false, bool bStartStalled = false, const FString& DebugName = TEXT("RequestAsyncLoad SingleLambda"));
使用Asset
当你的Asset加载完成,别忘记调用Get()来取得它。
MyItem.Get(); // returns a pointer to the LIVE UObject
本人额外添加的内容(一些有用的东西)
FStreamableManager
/**
* 同步版本的载入函数,用于载入多个(一组)资源,返回一个handle。
*
* @param TargetsToStream Assets to load off disk
* @param bManageActiveHandle If true, the manager will keep the streamable handle active until explicitly released
* @param DebugName Name of this handle, will be reported in debug tools
*/
TSharedPtr<FStreamableHandle> RequestSyncLoad(const TArray<FSoftObjectPath>& TargetsToStream, bool bManageActiveHandle = false, const FString& DebugName = TEXT("RequestSyncLoad Array"));
TSharedPtr<FStreamableHandle> RequestSyncLoad(const FSoftObjectPath& TargetToStream, bool bManageActiveHandle = false, const FString& DebugName = TEXT("RequestSyncLoad Single"));
/**
* 同步版本的载入函数,用于载入单个资源,返回UObject的指针。如果没有找到则返回空指针。
*
* @param Target Specific asset to load off disk
* @param bManageActiveHandle If true, the manager will keep the streamable handle active until explicitly released
* @param RequestHandlePointer If non-null, this will set the handle to the handle used to make this request. This useful for later releasing the handle
*/
UObject* LoadSynchronous(const FSoftObjectPath& Target, bool bManageActiveHandle = false, TSharedPtr<FStreamableHandle>* RequestHandlePointer = nullptr);
FStreamableHandle
同步或者异步加载的句柄,只要句柄处于激活状态,那么Asset就不会被回收。你可以句柄来控制Asset,以及绑定相应的委托。
/** Bind delegate that is called when load completes, only works if loading is in progress. This will overwrite any already bound delegate! */
bool BindCompleteDelegate(FStreamableDelegate NewDelegate);
/** Bind delegate that is called if handle is canceled, only works if loading is in progress. This will overwrite any already bound delegate! */
bool BindCancelDelegate(FStreamableDelegate NewDelegate);
/** Bind delegate that is called periodically as delegate updates, only works if loading is in progress. This will overwrite any already bound delegate! */
bool BindUpdateDelegate(FStreamableUpdateDelegate NewDelegate);
/**
* Blocks until the requested assets have loaded. This pushes the requested asset to the top of the priority list,
* but does not flush all async loading, usually resulting in faster completion than a LoadObject call
*
* @param Timeout Maximum time to wait, if this is 0 it will wait forever
* @param StartStalledHandles If true it will force all handles waiting on external resources to try and load right now
*/
EAsyncPackageState::Type WaitUntilComplete(float Timeout = 0.0f, bool bStartStalledHandles = true);
/** Gets list of assets references this load was started with. This will be the paths before redirectors, and not all of these are guaranteed to be loaded */
void GetRequestedAssets(TArray<FSoftObjectPath>& AssetList) const;
/** Adds all loaded assets if load has succeeded. Some entries will be null if loading failed */
void GetLoadedAssets(TArray<UObject *>& LoadedAssets) const;
/** Returns first asset in requested asset list, if it's been successfully loaded. This will fail if the asset failed to load */
UObject* GetLoadedAsset() const;
/** Returns number of assets that have completed loading out of initial list, failed loads will count as loaded */
void GetLoadedCount(int32& LoadedCount, int32& RequestedCount) const;
/** Returns progress as a value between 0.0 and 1.0. */
float GetProgress() const;
FSoftObjectPath
一个包含对象的引用字符串的结构体。它可以对按需加载的资产进行弱引用。可以使用UProperties进行标记,使得它可以在编辑器中显示并且可以指定资源。
可以使用TryLoad进行Asset载入,返回UObject指针,为空则表示载入失败。