--- title: Mass扩展笔记 date: 2024-09-12 15:32:15 excerpt: tags: rating: ⭐ --- # 1. 创建 UMassEntityTraitBase (UMassVisualizationTrait) 2. 相关的渲染设置逻辑位于UMassVisualizationComponent。 # UMassVisualizationComponent ```c++ void UMassVisualizationComponent::ConstructStaticMeshComponents() { AActor* ActorOwner = GetOwner(); check(ActorOwner); UE_MT_SCOPED_WRITE_ACCESS(InstancedStaticMeshInfosDetector); for (FMassInstancedStaticMeshInfo& Info : InstancedStaticMeshInfos) { // Check if it is already created if (!Info.InstancedStaticMeshComponents.IsEmpty()) { continue; } // Check if there are any specified meshes for this visual type if(Info.Desc.Meshes.Num() == 0) { UE_LOG(LogMassRepresentation, Error, TEXT("No associated meshes for this intanced static mesh type")); continue; } for (const FStaticMeshInstanceVisualizationMeshDesc& MeshDesc : Info.Desc.Meshes) { FISMCSharedData* SharedData = ISMCSharedData.Find(MeshDesc); UInstancedStaticMeshComponent* ISMC = SharedData ? SharedData->ISMC : nullptr; if (SharedData) { SharedData->RefCount += 1; } else { ISMC = NewObject(ActorOwner); ISMC->SetStaticMesh(MeshDesc.Mesh); for (int32 ElementIndex = 0; ElementIndex < MeshDesc.MaterialOverrides.Num(); ++ElementIndex) { if (UMaterialInterface* MaterialOverride = MeshDesc.MaterialOverrides[ElementIndex]) { ISMC->SetMaterial(ElementIndex, MaterialOverride); } } ISMC->SetCullDistances(0, 1000000); // @todo: Need to figure out what to do here, either LOD or cull distances. ISMC->SetupAttachment(ActorOwner->GetRootComponent()); ISMC->SetCanEverAffectNavigation(false); ISMC->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName); ISMC->SetCastShadow(MeshDesc.bCastShadows); ISMC->Mobility = MeshDesc.Mobility; ISMC->SetReceivesDecals(false); ISMC->RegisterComponent(); ISMCSharedData.Emplace(MeshDesc, FISMCSharedData(ISMC)); } Info.InstancedStaticMeshComponents.Add(ISMC); } // Build the LOD significance ranges TArray AllLODSignificances; auto UniqueInsertOrdered = [&AllLODSignificances](const float Significance) { int i = 0; for (; i < AllLODSignificances.Num(); ++i) { // I did not use epsilon check here on purpose, because it will make it hard later meshes inside. if (Significance == AllLODSignificances[i]) { return; } if (AllLODSignificances[i] > Significance) { break; } } AllLODSignificances.Insert(Significance, i); }; for (const FStaticMeshInstanceVisualizationMeshDesc& MeshDesc : Info.Desc.Meshes) { UniqueInsertOrdered(MeshDesc.MinLODSignificance); UniqueInsertOrdered(MeshDesc.MaxLODSignificance); } Info.LODSignificanceRanges.SetNum(AllLODSignificances.Num() - 1); for (int i = 0; i < Info.LODSignificanceRanges.Num(); ++i) { FMassLODSignificanceRange& Range = Info.LODSignificanceRanges[i]; Range.MinSignificance = AllLODSignificances[i]; Range.MaxSignificance = AllLODSignificances[i+1]; Range.ISMCSharedDataPtr = &ISMCSharedData; for (int j = 0; j < Info.Desc.Meshes.Num(); ++j) { const FStaticMeshInstanceVisualizationMeshDesc& MeshDesc = Info.Desc.Meshes[j]; const bool bAddMeshInRange = (Range.MinSignificance >= MeshDesc.MinLODSignificance && Range.MinSignificance < MeshDesc.MaxLODSignificance); if (bAddMeshInRange) { Range.StaticMeshRefs.Add(MeshDesc); } } } } } ``` 设置灯光通道: ```c++ void UPrimitiveComponent::SetLightingChannels(bool bChannel0, bool bChannel1, bool bChannel2) { if (bChannel0 != LightingChannels.bChannel0 || bChannel1 != LightingChannels.bChannel1 || bChannel2 != LightingChannels.bChannel2) { LightingChannels.bChannel0 = bChannel0; LightingChannels.bChannel1 = bChannel1; LightingChannels.bChannel2 = bChannel2; if (SceneProxy) { SceneProxy->SetLightingChannels_GameThread(LightingChannels); } MarkRenderStateDirty(); } } ```