Skip to content

Commit

Permalink
fixbug
Browse files Browse the repository at this point in the history
  • Loading branch information
RenderTool committed Jan 7, 2025
1 parent 0b60bf7 commit 27d9efc
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 103 deletions.
Binary file added src/unreal/assets/testactor2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 10 additions & 10 deletions src/unreal/core[核心]/1-Gameplay.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ Game State 就是指游戏状态。它管理了所有已连接的客户端,并

<chatmessage avatar="../../assets/emoji/kclr.png" :avatarWidth="40">

记不住根本记不住!这里BABA推荐我看<a href="./exp_经验_/1-Blueprint2CPP.html">蓝图节点对应CPP的探索与解析</a>
记不住根本记不住!

</chatmessage>

Expand Down Expand Up @@ -320,7 +320,7 @@ Baba我不知道什么叫宏耶!


`宏(英语:Macro),是一种批量处理的称谓。 计算机科学里的宏是一种抽象(Abstraction),它根据一系列预定义的规则替换一定的文本模式。
解释器或编译器在遇到宏时会自动进行这一模式替换。——wiki` 具体的宏标记请[阅读我的](./doc_文档_/macro.html)
解释器或编译器在遇到宏时会自动进行这一模式替换。——wiki`

### UHT|Unreal Header Tool(虚幻头文件工具)

Expand Down Expand Up @@ -541,12 +541,12 @@ void UTEST::TESTFUNC()
|---------------------------|
| **[ 知乎大钊](https://www.zhihu.com/people/fjz13)**|

| 课程名 | 类型 | 链接 |
|-----------------------------------|-------|----------------------------------------------------------------------------------------|
| 2023最新版C++ | C++基础 | [链接](https://www.bilibili.com/video/BV1eL41187JS/?spm_id_from=333.999.0.0&vd_source=fc61eb54bf3245afbff2be6b8c1ebfc2) |
| 【Cherno C++】 | C++基础 | [链接](https://www.bilibili.com/video/BV1fP4y1w7iE/?spm_id_from=333.999.0.0) |
| 为游戏编程学习C++ | C++基础 | [链接](https://www.bilibili.com/video/BV1Dd4y1R7VS/?spm_id_from=333.999.0.0) |
| 黑马程序员匠心之作|C++教程 | [链接](https://www.bilibili.com/video/BV1et411b73Z?t=94.0&p=95 ) |
| 字节跳动最新打造的C++教程 | C++基础 | [链接](https://www.bilibili.com/video/BV1ps4y1k7d7/?spm_id_from=333.999.0.0) |
| Udemy宝藏数据结构与算法课 | C++算法 | [链接](https://www.bilibili.com/video/BV1Ba411Y71K/?spm_id_from=333.337.top_right_bar_window_custom_collection.content.click) |
| 课程名 | 类型 | 链接 |
|-----------------|-------|-----------------------------------------------------------------------------------------------------------------------------|
| 2023最新版C++ | C++基础 | [链接](https://www.bilibili.com/video/BV1eL41187JS/?spm_id_from=333.999.0.0&vd_source=fc61eb54bf3245afbff2be6b8c1ebfc2) |
| 【Cherno C++】 | C++基础 | [链接](https://www.bilibili.com/video/BV1fP4y1w7iE/?spm_id_from=333.999.0.0) |
| 为游戏编程学习C++ | C++基础 | [链接](https://www.bilibili.com/video/BV1Dd4y1R7VS/?spm_id_from=333.999.0.0) |
| 黑马程序员匠心之作 | C++教程 | [链接](https://www.bilibili.com/video/BV1et411b73Z?t=94.0&p=95 ) |
| 字节跳动最新打造的C++教程 | C++基础 | [链接](https://www.bilibili.com/video/BV1ps4y1k7d7/?spm_id_from=333.999.0.0) |
| Udemy宝藏数据结构与算法课 | C++算法 | [链接](https://www.bilibili.com/video/BV1Ba411Y71K/?spm_id_from=333.337.top_right_bar_window_custom_collection.content.click) |

96 changes: 3 additions & 93 deletions src/unreal/function[函数]/11-Getactorofclass.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,105 +184,15 @@ void UGameplayStatics::GetAllActorsOfClass(const UObject* WorldContextObject, TS
### 问题
<chatmessage avatar="../../assets/emoji/hh.png" :avatarWidth="50">
为什么一开始就清空了数组,我也没见到节点有传入数组啊?<br>
DeterminesOutputType和DynamicOutputParam作用是啥?
</chatmessage>
<chatmessage avatar="../../assets/emoji/new4.png" :avatarWidth="50" alignLeft>
你注意UFUNCTION宏meta(元数据)的描述了吗?
</chatmessage>
`DeterminesOutputType` 和 `DynamicOutputParam` 是 UFUNCTION 宏的元数据,用于在蓝图中更好地处理输出参数的类型。
1. **`DeterminesOutputType`:**
- 当指定了 `DeterminesOutputType` 元数据时,它表示函数的输出参数类型是由函数的实现决定的,而不是由函数声明时指定的。这对于一些动态生成输出类型的函数非常有用。
2. **`DynamicOutputParam`:**
- 当指定了 `DynamicOutputParam` 元数据时,它表示函数的输出参数是动态生成的,而不是静态指定的。在函数签名中,你可以看到这个参数被标记为 `&OutActors`,这就是动态输出参数的示例。
<chatmessage avatar="../../assets/emoji/hh.png" :avatarWidth="50">
那么这个节点会强制变成输出节点吗?比如我加了const修饰。
</chatmessage>
<chatmessage avatar="../../assets/emoji/new7.png" :avatarWidth="50" alignLeft>
测试一下不就行了!
</chatmessage>
```cpp
//没用const限定
UFUNCTION(BlueprintCallable, Category="Actor", meta=( DynamicOutputParam="OutActors"))
static void TestFun(TArray<AActor*>& OutActors);
void UTEST::TestFun(TArray<AActor*>& OutActors)
{
//测试使用,实际开发别用哦
AActor* Actor2 = nullptr;
OutActors.Add(Actor2);
OutActors.Add(Actor2);
int Num = OutActors.Num();
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::White, FString::FromInt(Num), true, FVector2D(1, 1));
}
//const限定
UFUNCTION(BlueprintCallable, Category="Actor" ,meta=(DynamicOutputParam="OutActors"))
static void TestFun2(const TArray<AActor*>& OutActors);
void UTEST::TestFun2( const TArray<AActor*>& OutActors)
{
int Num = OutActors.Num();
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::White, FString::FromInt(Num), true, FVector2D(1, 1));
}
```

![](..%2Fassets%2Fconstwithoutconst.png)

<chatmessage avatar="../../assets/emoji/new8.png" :avatarWidth="50">
测试结果看来const修饰后会将数组变成输入节点。
</chatmessage>

<chatmessage avatar="../../assets/emoji/dsyj.png" :avatarWidth="40" alignLeft>
没错,而且我们测试代码中给2个空指针到这个指针数组中,测试结果也是打印2.
</chatmessage>

![](..%2Fassets%2Fwss.png)

<chatmessage avatar="../../assets/emoji/dsyj.png" :avatarWidth="40" alignLeft>
const修饰后数组变成只读,需要我们自己传入数据。
</chatmessage>

![](..%2Fassets%2Fxd.png)

<chatmessage avatar="../../assets/emoji/new8.png" :avatarWidth="50">
const强制变成只读这没毛病,但动态生成我还是抱有怀疑态度,如果我们去掉DynamicOutputParam呢?还会打印2吗?
</chatmessage>

```cpp
//没有meta
UFUNCTION(BlueprintCallable, Category="Actor")
static void TestFun3(TArray<AActor*>& OutActors);

void UTEST::TestFun3(TArray<AActor*>& OutActors)
{
//测试使用,实际开发别用哦
AActor* Actor2 = nullptr;
OutActors.Add(Actor2);
OutActors.Add(Actor2);
int Num = OutActors.Num();
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::White, FString::FromInt(Num), true, FVector2D(1, 1));
}
```
<chatmessage avatar="../../assets/emoji/new1.png" :avatarWidth="50" alignLeft>
![](..%2Fassets%2Fyjsc.png)
具体跳转到 [UPROPERTY宏标记](../function_函数_/5-UPROPERTY.html#DeterminesOutputType) 里面有具体的介绍
<chatmessage avatar="../../assets/emoji/new3.png" :avatarWidth="50" alignLeft>
居然还是可以!看来系统自动帮我们初始化了一个指针数组。
</chatmessage>
结论:
1. const 限定优先级更高。
2. DynamicOutputParam 确实帮我们动态生成了一个对象,但即使不加也会主动尝试生成。
## 其他问题
### `getactorofclass`vs`Cast`
Expand Down
96 changes: 96 additions & 0 deletions src/unreal/function[函数]/5-UPROPERTY.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,100 @@ public:
int32 EditDefaultsOnlyNumber;
```
## DeterminesOutputType
>动态输出类型
<chatmessage avatar="../../assets/emoji/new5.png" :avatarWidth="40" alignLeft>
你有没有注意过一个细节:官方的GetActorOfClass节点给输入一个ActorClass,能返回对应的Actor对象,但这个Actor不是Actor*而是对应的派生类?
就比如下图的角色类。
</chatmessage>
![](..%2Fassets%2Ftestactor2.png)
```cpp
UFUNCTION(BlueprintCallable, Category="Actor", meta=(WorldContext="WorldContextObject", DeterminesOutputType="ActorClass"))
static ENGINE_API class AActor* GetActorOfClass(const UObject* WorldContextObject, TSubclassOf<AActor> ActorClass);
AActor* UGameplayStatics::GetActorOfClass(const UObject* WorldContextObject, TSubclassOf<AActor> ActorClass)
{
QUICK_SCOPE_CYCLE_COUNTER(UGameplayStatics_GetActorOfClass);
// We do nothing if no is class provided
if (ActorClass)
{
if (UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull))
{
for (TActorIterator<AActor> It(World, ActorClass); It; ++It)
{
AActor* Actor = *It;
return Actor;
}
}
}
return nullptr;
}
```

<chatmessage avatar="../../assets/emoji/new1.png" :avatarWidth="40" >
我靠!我有一个维护各种策略的子系统。实际使用中往往需要输出对应的策略派生类。虽然C++可以使用模板,但用了模板后蓝图里就没法玩了。
</chatmessage>

```cpp
UDataStrategyBase* UUserDataSubsystem::FindDataStrategy(FName StrategyName)
{
UDataStrategyBase* StrategyInstance = RegisteredStrategies.FindRef(StrategyName);
return StrategyInstance;
}
```
<chatmessage avatar="../../assets/emoji/new5.png" :avatarWidth="40" alignLeft>
是的,我们虽然可以用模板来应对C++开发者,但蓝图中显得不够智能了,每次都要手动Cast,因此才需要我们今天的主角` DeterminesOutputType`
</chatmessage>
> 首先当然是C++的T模板
```cpp
template <typename T>
T* UUserDataSubsystem::FindDataStrategyAs(FName StrategyName)
{
UDataStrategyBase* BaseInstance = FindDataStrategy(StrategyName);
return Cast<T>(BaseInstance); // 直接通过Cast返回派生类指针
}
```
> 其次是蓝图节点的改造,通过`DeterminesOutputType`
```cpp

public:

UFUNCTION(BlueprintCallable, Category="DataStrategy", meta = (DeterminesOutputType = "StrategyClass"))
UDataStrategyBase* FindDataStrategyByClass(FName StrategyName, TSubclassOf<UDataStrategyBase> StrategyClass)
{
UDataStrategyBase* StrategyInstance = FindDataStrategy(StrategyName);

if (StrategyInstance && StrategyInstance->IsA(StrategyClass))
{
return StrategyInstance;
}

return nullptr;
}

//将UDataStrategyBase* FindDataStrategy(FName StrategyName);移到私有

private:
UDataStrategyBase* FindDataStrategy(FName StrategyName);

```
## Category
Expand Down Expand Up @@ -245,6 +339,8 @@ UPROPERTY(EditAnywhere, meta=(EditCondition="bCanFly", Units="s"))
![](..%2Fassets%2FInlineEditConditionToggle.png)
### 更多参考
- [官方文档](https://docs.unrealengine.com/5.2/zh-CN/unreal-engine-uproperties/)
Expand Down

0 comments on commit 27d9efc

Please sign in to comment.