为什么UE中可以调用其他类的private属性
时间: 2023-06-07 09:07:28 浏览: 83
在C++中,可以通过friend关键字将一个类或函数声明为另一个类的友元,从而使该类或函数能够访问该类的私有成员。在UE中,许多类都采用了友元机制,以便访问其他类的私有成员,从而实现更高效和便捷的编程。同时,UE也提供了一些其他的机制,如成员委托和TWeakObjectPtr等,来实现跨类访问私有成员的功能。总的来说,UE为程序员提供了丰富的工具和机制,帮助开发者更加灵活高效地进行开发。
相关问题
UE4 C++ 用SaveGame类写一个异步加载关卡
首先,你需要创建一个继承自`USaveGame`的保存游戏数据的类,并在其中定义需要保存的数据成员。接下来,你需要在异步加载关卡时加载这些数据。
以下是一个简单的示例:
```c++
// MySaveGame.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/SaveGame.h"
#include "MySaveGame.generated.h"
UCLASS()
class UMySaveGame : public USaveGame
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite)
FString LevelName;
};
// MyLevelLoader.h
#pragma once
#include "CoreMinimal.h"
#include "Engine/LevelStreamingDynamic.h"
#include "MySaveGame.h"
#include "MyLevelLoader.generated.h"
UCLASS()
class AMyLevelLoader : public AActor
{
GENERATED_BODY()
public:
AMyLevelLoader();
UFUNCTION(BlueprintCallable)
void LoadLevelAsync(const FString& LevelName);
void LoadLevelAsync_Internal(const FString& LevelName);
UFUNCTION()
void OnLevelLoaded();
private:
UPROPERTY()
ULevelStreamingDynamic* StreamingLevel;
UPROPERTY()
UMySaveGame* SaveGame;
};
// MyLevelLoader.cpp
#include "MyLevelLoader.h"
#include "Kismet/GameplayStatics.h"
#include "Engine/World.h"
AMyLevelLoader::AMyLevelLoader()
{
PrimaryActorTick.bCanEverTick = false;
StreamingLevel = NewObject<ULevelStreamingDynamic>(this, ULevelStreamingDynamic::StaticClass());
StreamingLevel->bShouldBeLoaded = false;
StreamingLevel->bShouldBeVisible = false;
}
void AMyLevelLoader::LoadLevelAsync(const FString& LevelName)
{
SaveGame = Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass()));
if (SaveGame != nullptr)
{
SaveGame->LevelName = LevelName;
SaveGame->SaveAsync(0);
}
FStreamableManager& Streamable = UAssetManager::GetStreamableManager();
Streamable.RequestLevel(StreamingLevel->GetWorldAssetPackageFName(LevelName), FStreamableDelegate::CreateUObject(this, &AMyLevelLoader::LoadLevelAsync_Internal, LevelName));
}
void AMyLevelLoader::LoadLevelAsync_Internal(const FString& LevelName)
{
StreamingLevel->SetWorldAssetByPackageName(LevelName);
StreamingLevel->bShouldBeLoaded = true;
UWorld* World = GetWorld();
if (World != nullptr)
{
StreamingLevel->LevelColor = FColor::MakeRandomColor();
StreamingLevel->LevelTransform = FTransform(FRotator::ZeroRotator, FVector(0.f, 0.f, 0.f), FVector(1.f, 1.f, 1.f));
World->AddLevelStreamingActor(StreamingLevel, GetActorTransform());
}
}
void AMyLevelLoader::OnLevelLoaded()
{
if (SaveGame != nullptr)
{
FString LevelName = SaveGame->LevelName;
SaveGame->Delete();
SaveGame = nullptr;
// Do something with the loaded level...
}
}
```
在上面的示例中,`UMySaveGame`保存了需要在异步加载关卡时加载的数据成员。`AMyLevelLoader`是一个继承自`AActor`的类,它有一个`LoadLevelAsync`函数,它会异步加载指定名称的关卡,并在加载完成后调用`OnLevelLoaded`函数。在`LoadLevelAsync_Internal`函数中,我们使用`ULevelStreamingDynamic`类来加载关卡,并在加载完成后将其添加到世界中。在`OnLevelLoaded`函数中,我们可以获取保存在`UMySaveGame`对象中的数据成员,并进行后续操作。
请注意,以上示例仅用于演示目的,实际使用时可能需要进行更多的错误处理和数据验证。
uE中事件分发器的作用以及具体的使用方法
uE中的事件分发器可以帮助用户在程序中管理和处理事件。使用事件分发器可以将事件从一个对象传递到另一个对象,实现对象之间的解耦。在uE中,事件分发器使用了观察者模式,当一个事件发生时,事件分发器会通知已注册的监听器并执行相应的操作。
使用uE事件分发器的方法如下:
1. 创建一个事件分发器对象。
2. 注册监听器对象,可以是任何实现了监听器接口的对象。
3. 在需要触发事件的地方,调用事件分发器的方法并传递事件对象作为参数。
4. 事件分发器会自动通知已注册的监听器对象,并执行相应的操作。
示例代码如下:
```c++
// 定义一个事件类型
class MyEvent {
public:
int data;
};
// 定义一个监听器接口
class MyListener {
public:
virtual void onEvent(MyEvent event) = 0;
};
// 定义一个事件分发器
class MyEventDispatcher {
private:
std::vector<MyListener*> listeners;
public:
void registerListener(MyListener* listener) {
listeners.push_back(listener);
}
void dispatchEvent(MyEvent event) {
for (auto listener : listeners) {
listener->onEvent(event);
}
}
};
// 实现一个监听器
class MyEventListener : public MyListener {
public:
void onEvent(MyEvent event) override {
std::cout << "Event data: " << event.data << std::endl;
}
};
// 使用事件分发器
int main() {
MyEventDispatcher dispatcher;
MyEventListener listener;
dispatcher.registerListener(&listener);
MyEvent event;
event.data = 123;
dispatcher.dispatchEvent(event);
return 0;
}
```
在上面的示例代码中,我们创建了一个名为`MyEventDispatcher`的事件分发器,并实现了一个名为`MyEventListener`的监听器。我们使用`registerListener`方法将`MyEventListener`对象注册到事件分发器中,并使用`dispatchEvent`方法触发事件,并将`MyEvent`对象作为参数传递给事件分发器。当事件被触发时,事件分发器会自动通知已注册的监听器对象,并执行相应的操作。在上面的示例代码中,我们实现了`MyEventListener`监听器的`onEvent`方法,当事件被触发时,会输出事件的数据到控制台上。