You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UE5中从原始网格数据创建静态Mesh时SetStaticMesh崩溃的解决方法

UE5运行时从原始网格数据创建静态Mesh崩溃问题解决

问题描述

此前通过StaticLoadObject加载/Engine/BasicShapes/Sphere球体Mesh并分配材质可成功执行,但自行生成顶点和索引数据创建静态Mesh时,在Mesh->SetStaticMesh(StaticMesh);处崩溃,断言错误:

Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:D:\build++UE5\Sync\Engine\Source\Runtime\Core\Public\Containers\Array.h] [Line: 752] Array index out of bounds: 0 from an array of size 0

即使移除FRawMesh相关代码,崩溃现象依然存在。

原代码

UStaticMeshComponent* AMyActor::CreateMesh(AActor* ActorOwner, FLinearColor Color)
{
    FRawMesh RawMesh;
    RawMesh.VertexPositions.Emplace(FVector(0.f, 0.f, 0.f));
    RawMesh.VertexPositions.Emplace(FVector(100.f, 0.f, 0.f));
    RawMesh.VertexPositions.Emplace(FVector(100.f, 100.f, 0.f));
    RawMesh.VertexPositions.Emplace(FVector(0.f, 100.f, 0.f));

    RawMesh.WedgeIndices.Emplace(0);
    RawMesh.WedgeIndices.Emplace(1);
    RawMesh.WedgeIndices.Emplace(2);

    RawMesh.WedgeIndices.Emplace(0);
    RawMesh.WedgeIndices.Emplace(2);
    RawMesh.WedgeIndices.Emplace(3);

    RawMesh.WedgeIndices.Emplace(1);
    RawMesh.WedgeIndices.Emplace(0);
    RawMesh.WedgeIndices.Emplace(3);

    RawMesh.WedgeIndices.Emplace(1);
    RawMesh.WedgeIndices.Emplace(3);
    RawMesh.WedgeIndices.Emplace(2);

    // Create a static mesh from the FRawMesh
    UStaticMesh* StaticMesh = NewObject<UStaticMesh>();
    StaticMesh->AddSourceModel();
    FStaticMeshSourceModel& SourceModel = StaticMesh->GetSourceModel(0);
    SourceModel.RawMeshBulkData->SaveRawMesh(RawMesh);

    StaticMesh->Build(false);

    UStaticMeshComponent* Mesh = NewObject<UStaticMeshComponent>(ActorOwner);
    UE_LOG(LogTemp, Warning, TEXT("Calling Mesh->SetStaticMesh(%x)..."), (void*)StaticMesh);
    // crashes here:
    Mesh->SetStaticMesh(StaticMesh);
    Mesh->SetMaterial(0, CreateMaterial(Color));
    Mesh->SetCollisionProfileName(TEXT("Pawn"));
    Mesh->SetHiddenInGame(false);
    Mesh->RegisterComponent();
    return Mesh;
}

UMaterialInstanceDynamic* AMyActor::CreateMaterial(FLinearColor Color)
{
    FStringAssetReference MaterialRef(TEXT("/Game/SimBlank/Materials/GlossyRedMaterial"));
    UMaterialInterface* LoadedMaterial = Cast<UMaterialInterface>(StaticLoadObject(UMaterialInterface::StaticClass(), nullptr, *MaterialRef.ToString()));
    UMaterialInstanceDynamic* NewMaterial = UMaterialInstanceDynamic::Create(LoadedMaterial, this);
    NewMaterial->SetVectorParameterValue("BaseColor", Color);
    return NewMaterial;
}

调用代码:

MeshActor = World->SpawnActor<AActor>();
MeshActor->SetRootComponent(CreateMesh(MeshActor, FLinearColor::Gray));
MeshActor->SetActorLocation(GetActorLocation() + FVector(100.0f, 0.0f, 40.0f));

错误原因及修正方案

崩溃核心是UStaticMesh初始化不完整,缺少必要的LOD配置、材质插槽定义,以及创建UStaticMesh时的参数不规范。以下是正确实现步骤:

1. 完善FRawMesh数据

UE静态Mesh除顶点和索引外,还需要UV坐标、法线等基础数据(即使是平面也需填充默认值),否则Build后的Mesh会缺失关键数据导致访问越界。

2. 规范UStaticMesh创建参数

创建UStaticMesh时必须指定Outer(通常为ActorOwner)和正确的ObjectFlags,确保Mesh被正确注册和管理。

3. 配置SourceModel的Build设置

启用法线/切线重计算,同时指定材质插槽数量,避免后续设置材质时索引越界。

4. 正确执行StaticMesh.Build

调用Build(true)确保Mesh完全构建完成,生成有效的LOD数据。

修正后的完整代码

UStaticMeshComponent* AMyActor::CreateMesh(AActor* ActorOwner, FLinearColor Color)
{
    FRawMesh RawMesh;

    // 1. 添加顶点位置
    RawMesh.VertexPositions.Emplace(FVector(0.f, 0.f, 0.f));
    RawMesh.VertexPositions.Emplace(FVector(100.f, 0.f, 0.f));
    RawMesh.VertexPositions.Emplace(FVector(100.f, 100.f, 0.f));
    RawMesh.VertexPositions.Emplace(FVector(0.f, 100.f, 0.f));

    // 2. 添加UV坐标(必须,否则Build失败)
    const FVector2D UV0(0.f, 0.f);
    const FVector2D UV1(1.f, 0.f);
    const FVector2D UV2(1.f, 1.f);
    const FVector2D UV3(0.f, 1.f);
    RawMesh.WedgeTexCoords[0].Emplace(UV0);
    RawMesh.WedgeTexCoords[0].Emplace(UV1);
    RawMesh.WedgeTexCoords[0].Emplace(UV2);
    RawMesh.WedgeTexCoords[0].Emplace(UV3);

    // 3. 添加法线(后续Build会重计算,先填充默认值)
    const FVector Normal(0.f, 0.f, 1.f);
    RawMesh.WedgeNormals.Emplace(Normal);
    RawMesh.WedgeNormals.Emplace(Normal);
    RawMesh.WedgeNormals.Emplace(Normal);
    RawMesh.WedgeNormals.Emplace(Normal);

    // 4. 添加索引(三角形列表)
    RawMesh.WedgeIndices.Append({0, 1, 2, 0, 2, 3});

    // 5. 创建UStaticMesh,指定Outer和ObjectFlags
    UStaticMesh* StaticMesh = NewObject<UStaticMesh>(ActorOwner, NAME_None, RF_Public | RF_Standalone);
    StaticMesh->AddSourceModel();
    FStaticMeshSourceModel& SourceModel = StaticMesh->GetSourceModel(0);
    
    // 6. 配置Build设置:启用法线重计算,设置材质插槽数
    SourceModel.BuildSettings.bRecomputeNormals = true;
    SourceModel.BuildSettings.bRecomputeTangents = true;
    StaticMesh->StaticMaterials.SetNum(1); // 设置1个材质插槽

    // 7. 保存RawMesh并构建
    SourceModel.RawMeshBulkData->SaveRawMesh(RawMesh);
    StaticMesh->Build(true); // 传true确保完全构建

    // 8. 创建并配置StaticMeshComponent
    UStaticMeshComponent* MeshComponent = NewObject<UStaticMeshComponent>(ActorOwner, TEXT("GeneratedMesh"));
    MeshComponent->SetStaticMesh(StaticMesh);
    MeshComponent->SetMaterial(0, CreateMaterial(Color));
    MeshComponent->SetCollisionProfileName(TEXT("Pawn"));
    MeshComponent->SetHiddenInGame(false);
    MeshComponent->RegisterComponent();

    return MeshComponent;
}

UMaterialInstanceDynamic* AMyActor::CreateMaterial(FLinearColor Color)
{
    FStringAssetReference MaterialRef(TEXT("/Game/SimBlank/Materials/GlossyRedMaterial"));
    UMaterialInterface* LoadedMaterial = Cast<UMaterialInterface>(StaticLoadObject(UMaterialInterface::StaticClass(), nullptr, *MaterialRef.ToString()));
    if (!LoadedMaterial)
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to load base material!"));
        return nullptr;
    }
    UMaterialInstanceDynamic* NewMaterial = UMaterialInstanceDynamic::Create(LoadedMaterial, this);
    NewMaterial->SetVectorParameterValue("BaseColor", Color);
    return NewMaterial;
}

额外注意事项

  • 调用SpawnActor时建议指定Spawn参数(如位置、旋转),避免默认位置可能引发的问题。
  • 若需创建复杂网格,需填充所有必要的RawMesh数据(如切线、顶点颜色等)。
  • 运行时创建的静态Mesh不会自动保存到内容浏览器,如需持久化需额外调用保存逻辑。

内容的提问来源于stack exchange,提问作者fferri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 16:22:21