Unreal Engine: 从文件路径加载静态网格物体

Unreal Engine: Load static mesh from file path

美好的一天!我刚开始学习 Unreal Engine 4.12 一周。供您自行决定-我对 C++ 编程知之甚少。 (尽管我使用 PHP 进行编码,所以我在某种程度上理解了 OOP)- 而且,我只是对可视化脚本(蓝图)有点熟悉。

我想要做的是通过加载一个新的静态网格物体来改变玩家的武器,该静态网格物体将来自文件路径.目前没有执行此操作的蓝图节点,许多 articles/forums 建议构建我自己的蓝图节点。

我做了一些研究,发现了这个:Dynamic Load Object C++ - 它非常有前途 - 但是,我不知道如何实施它。我尝试打开 MyProject.h 并将其粘贴到那里,但我不确定下一步该怎么做 - 它会变成一个函数吗?还是蓝图节点?

我愿意接受关于如何实现我想要的目标的其他建议(或方向)。如果还有其他方法可以实现这一点,请分享和教育我。非常感谢!

此致,

克里斯

静态负载只是帮手。只有用 UFUNCTION(...) 宏标记该函数的 header 才能调用 C++ 函数。参见 this link。

所以您可以创建您的函数并在它的实现中调用该帮助程序。例如:

// Helpers.h
static FORCEINLINE UTexture2D* GetTexture2DByName(const FName& name) {
    return LoadObjFromPath<UTexture2D>(name);
}

UFUNCTION(BlueprintCallable, Category = TCF2Helpers)
    static UTexture2D* GetTexture2DForBlock(UBuildableBlockInfo* blockInfo);


// Helpers.cpp
UTexture2D* UHelpers::GetTexture2DForBlock(UBuildableBlockInfo* blockInfo)
{
    if (!blockInfo)
        return nullptr;

    const FString baseFolder = TEXT("Texture2D'/Game/Textures/HUD/%s");

    if (blockInfo->IsEmptyHand)
        return GetTexture2DByName(*FString::Printf(*baseFolder, TEXT("EmptyHand.EmptyHand'")));

    // another lines of implementation
}

但是您需要问问自己,是否真的需要对其进行硬编码。您可以指定类似

的内容
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Widgets")
    TSubclassOf<class UObjectWidget> wInGameMenu;

UPROPERTY(BlueprintReadOnly, Category = "Widgets")
    UObjectWidget* InGameMenu;

在覆盖函数 BeginPlay 的地方(这是由于动态创建 小部件 )我有:

if (wInGameMenu)
{
    InGameMenu = CreateWidget<UObjectWidget>(this, wInGameMenu);
}

UObjectWidgetUUserWidget 的继任者,我的小部件(在编辑器中创建)被重新设置为将该小部件作为继承基础。我定义了应该在我的 object 的 archetype 上创建哪个小部件。

我会这样实现它:(如果有人告诉我更好的方法,这可能会改变)

  • 创建 WeaponManager 作为 ActorComponent
  • 创建 Weapon 作为 SceneComponent(这样你就可以将它附加到骨架插座上)
  • 每个 Weapon 都会有它自己的基于相同接口的实现(可能覆盖共同祖先中定义的一些函数?)
  • 您可以拥有多个 sub-childs(能量武器、射击武器等),这样您就有了正确的继承并且避免了同一事物的多次实现。
  • 每个 Weapon 都会定义它的网格和属性 - 同样,如果你硬编码网格路径(没关系,因为它是实现),你可以在最后使用这样的代码那个列表)或者你可以在原型上设置它,如果你想在蓝图中编码一些东西。
  • 然后在WeaponManager中定义所有武器(例如TArray<TSubclassOf<UWeapon>>
  • 每个武器都应该定义 EWeaponType - 枚举游戏中的所有武器,这样我就可以将定义的武器与其在 TMap 中的类型匹配,然后根据需要简单地使用它(显示,隐藏、更换武器等)该类型应该硬编码到武器的所有实现中。

在构造函数中加载网格:

//TerminalObject.h
UCLASS()
class TAUCETIF2_API ATerminalObject : public AStaticMeshActor
{
    GENERATED_UCLASS_BODY()
};

// TerminalObject.cpp
ATerminalObject::ATerminalObject(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{

    static ConstructorHelpers::FObjectFinder<UStaticMesh> mesh(TEXT("StaticMesh'/Game/BuildingObjects/Meshes/terminal.terminal'"));

    checkf(mesh.Succeeded(), TEXT("Failed to find mesh"));

    auto mc = GetStaticMeshComponent();
    checkf(mc, TEXT("Failed to find mesh component"));

    mc->SetStaticMesh(mesh.Object);
}