79 lines
4.0 KiB
Markdown
79 lines
4.0 KiB
Markdown
|
# AnimGetter
|
|||
|
|
|||
|
- **功能描述:** 指定UAnimInstance及子类的该函数成为一个AnimGetter函数。
|
|||
|
- **使用位置:** UFUNCTION
|
|||
|
- **引擎模块:** AnimationGraph
|
|||
|
- **元数据类型:** bool
|
|||
|
- **限制类型:** UAnimInstance及子类的函数
|
|||
|
- **关联项:** [GetterContext](../GetterContext/GetterContext.md)
|
|||
|
- **常用程度:** ★★★
|
|||
|
|
|||
|
指定UAnimInstance及子类的该函数成为一个AnimGetter函数。
|
|||
|
|
|||
|
- 在一些情况下会继承UAnimInstance创建自己的动画蓝图子类,然后里面可以自己做一些优化,或者添加一些自己的功能函数。
|
|||
|
- 所谓的AnimGetter,其实就是会被UK2Node_AnimGetter识别并包装成该蓝图节点的函数。识别的范围是在UAnimInstance及子类(就是动画蓝图)的C++函数。
|
|||
|
- AnimGetter还有两个额外功能:一是会自动根据当前上下文填充函数里的AssetPlayerIndex,MachineIndex,StateIndex,TransitionIndex和参数。二是会根据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);
|
|||
|
};
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
## 测试效果:
|
|||
|
|
|||
|
分别定义使用了AssetPlayerIndex,MachineIndex,StateIndex,TransitionIndex的AnimGetter函数以及普通蓝图函数作为对比。分别查看在动画蓝图里几个作用域里的用法。
|
|||
|
|
|||
|
- 可见在不管什么作用域,普通蓝图函数都可以调用(毕竟没有做Context的检查)。另外AssetPlayerIndex等参数都没有被自动填充,这几乎是没法用的,因为用户其实并不太懂如何去手填这些Index,最好是交给编译器来填充。
|
|||
|
- 图里高亮的是可以调用的AnimGetter函数。细看的话,可以分析发现规则是只有能正确填充AssetPlayerIndex等参数的才能调用。因此在Transition里能调用的最多,因为这个时候最叶子节点,有动画,又有状态机和Transition节点。
|
|||
|
|
|||
|

|
|||
|
|
|||
|
## 原理:
|
|||
|
|
|||
|
分析函数上的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);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|