【问题标题】:Unreal Engine: Load static mesh from file path虚幻引擎:从文件路径加载静态网格物体
【发布时间】:2016-10-26 19:08:05
【问题描述】:

美好的一天!我刚开始学习虚幻引擎 4.12 一个星期。由您自行决定 - 我对 C++ 编程知之甚少。 (虽然我使用 PHP 进行编码,所以我在一定程度上理解 OOP)——而且,我只是对可视化脚本(蓝图)有点熟悉。

我想要做的是通过加载一个新的静态网格物体来改变玩家的武器,这个静态网格物体将来自一个文件路径。目前没有蓝图节点可以做到这一点,很多文章/论坛都建议构建自己的蓝图节点。

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

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

此致,

克里斯

【问题讨论】:

    标签: unreal-engine4 unreal-blueprint


    【解决方案1】:

    静态负载只是帮手。只有通过 UFUNCTION(...) 宏标记该函数的标头,才能调用 C++ 函数。请参阅this 链接。

    所以你可以创建你的函数并在它的实现中调用那个助手。例如:

    // 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 的覆盖位置(这是由于动态创建 widget)我有:

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

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

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

    • 创建 WeaponManager 作为 ActorComponent
    • 创建 Weapon 作为 SceneComponent(这样您就可以将它附加到骨架插槽上)
    • 每个武器都会有基于相同接口的自己的实现(可能会覆盖共同祖先中定义的某些功能?)
    • 您可以拥有多个子子项(能量武器、射击武器等),因此您可以正确继承并避免多次实现同一事物。
    • 每个 Weapon 都会定义它的网格和属性 - 同样,如果您硬编码网格路径(没关系,因为它是实现),您可以使用该列表末尾的代码)或者您如果您想在蓝图中编写代码,可以在原型上设置它。
    • 然后在 WeaponManager 中定义所有武器(例如 TArray&lt;TSubclassOf&lt;UWeapon&gt;&gt;
    • 每个武器都应该定义 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);
    }
    

    【讨论】:

    • 我的天哪,太广泛了。我非常感谢您为我提出这个答案。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-17
    • 1970-01-01
    • 2019-12-20
    • 2018-11-19
    • 2021-10-11
    • 2017-06-11
    相关资源
    最近更新 更多