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
相关产品推荐
相关产品推荐

