79 lines
4.0 KiB
Markdown
Raw Normal View History

2024-10-12 17:19:46 +08:00
# AnimGetter
- **功能描述:** 指定UAnimInstance及子类的该函数成为一个AnimGetter函数。
- **使用位置:** UFUNCTION
- **引擎模块:** AnimationGraph
- **元数据类型:** bool
- **限制类型:** UAnimInstance及子类的函数
- **关联项:** [GetterContext](../GetterContext/GetterContext.md)
- **常用程度:** ★★★
指定UAnimInstance及子类的该函数成为一个AnimGetter函数。
- 在一些情况下会继承UAnimInstance创建自己的动画蓝图子类然后里面可以自己做一些优化或者添加一些自己的功能函数。
- 所谓的AnimGetter其实就是会被UK2Node_AnimGetter识别并包装成该蓝图节点的函数。识别的范围是在UAnimInstance及子类就是动画蓝图的C++函数。
- AnimGetter还有两个额外功能一是会自动根据当前上下文填充函数里的AssetPlayerIndexMachineIndexStateIndexTransitionIndex和参数。二是会根据GetterContext把该函数限定只能在某些蓝图里调用。普通的蓝图函数不具有这些便利的功能和检查用起来就不够智能。
- 要成为AnimGetter还必须具有
- AnimGetter自然不必说
- BlueprintThreadSafe才能在动画蓝图里调用多线程安全
- BlueprintPure成为一个存获取值的函数
- BlueprintInternalUseOnly = "true”避免再生成一个默认的蓝图节点只用UK2Node_AnimGetter包装而成的那个。
## 测试代码:
```cpp
UCLASS(BlueprintType)
class INSIDER_API UMyAnimInstance :public UAnimInstance
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintPure, Category = "Animation|Insider", meta = (BlueprintInternalUseOnly = "true", AnimGetter, BlueprintThreadSafe))
float MyGetAnimationLength_AnimGetter(int32 AssetPlayerIndex);
UFUNCTION(BlueprintPure, Category = "Animation|Insider", meta = (BlueprintThreadSafe))
float MyGetAnimationLength(int32 AssetPlayerIndex);
public:
UFUNCTION(BlueprintPure, Category = "Animation|Insider", meta = (BlueprintInternalUseOnly = "true", AnimGetter, BlueprintThreadSafe))
float MyGetStateWeight_AnimGetter(int32 MachineIndex, int32 StateIndex);
UFUNCTION(BlueprintPure, Category = "Animation|Insider", meta = (BlueprintThreadSafe))
float MyGetStateWeight(int32 MachineIndex, int32 StateIndex);
public:
UFUNCTION(BlueprintPure, Category = "Animation|Insider", meta = (BlueprintInternalUseOnly = "true", AnimGetter, BlueprintThreadSafe))
float MyGetTransitionTimeElapsed_AnimGetter(int32 MachineIndex, int32 TransitionIndex);
UFUNCTION(BlueprintPure, Category = "Animation|Insider", meta = (BlueprintThreadSafe))
float MyGetTransitionTimeElapsed(int32 MachineIndex, int32 TransitionIndex);
};
```
## 测试效果:
分别定义使用了AssetPlayerIndexMachineIndexStateIndexTransitionIndex的AnimGetter函数以及普通蓝图函数作为对比。分别查看在动画蓝图里几个作用域里的用法。
- 可见在不管什么作用域普通蓝图函数都可以调用毕竟没有做Context的检查。另外AssetPlayerIndex等参数都没有被自动填充这几乎是没法用的因为用户其实并不太懂如何去手填这些Index最好是交给编译器来填充。
- 图里高亮的是可以调用的AnimGetter函数。细看的话可以分析发现规则是只有能正确填充AssetPlayerIndex等参数的才能调用。因此在Transition里能调用的最多因为这个时候最叶子节点有动画又有状态机和Transition节点。
![Untitled](Untitled.png)
## 原理:
分析函数上的AnimGetter标记并且生成蓝图节点的功能基本都在UK2Node_AnimGetter这个类里。大家可自行查看。
```cpp
void UK2Node_AnimGetter::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
TArray<UFunction*> AnimGetters;
for(TFieldIterator<UFunction> FuncIter(BPClass) ; FuncIter ; ++FuncIter)
{
UFunction* Func = *FuncIter;
if(Func->HasMetaData(TEXT("AnimGetter")) && Func->HasAnyFunctionFlags(FUNC_Native))
{
AnimGetters.Add(Func);
}
}
}
```