void UMeshComponent::SetMaterial(int32 ElementIndex, UMaterialInterface* Material)
{
if (ElementIndex >= 0)
{
if (OverrideMaterials.IsValidIndex(ElementIndex) && (OverrideMaterials[ElementIndex] == Material))
{
// Do nothing, the material is already set
}
else
{
// Grow the array if the new index is too large
if (OverrideMaterials.Num() <= ElementIndex)
{
OverrideMaterials.AddZeroed(ElementIndex + 1 - OverrideMaterials.Num());
}
// Check if we are setting a dynamic instance of the original material, or replacing a nullptr material (if not we should dirty the material parameter name cache)
if (Material != nullptr)
{
UMaterialInstanceDynamic* DynamicMaterial = Cast<UMaterialInstanceDynamic>(Material);
if (!((DynamicMaterial != nullptr && DynamicMaterial->Parent == OverrideMaterials[ElementIndex]) || OverrideMaterials[ElementIndex] == nullptr))
{
// Mark cached material parameter names dirty
MarkCachedMaterialParameterNameIndicesDirty();
}
}
// Set the material and invalidate things
OverrideMaterials[ElementIndex] = Material;
MarkRenderStateDirty();
if (Material)
{
Material->AddToCluster(this, true);
}
FBodyInstance* BodyInst = GetBodyInstance();
if (BodyInst && BodyInst->IsValidBodyInstance())
{
BodyInst->UpdatePhysicalMaterials();
}
#if WITH_EDITOR
// Static Lighting is updated when compilation finishes
if (!IsCompiling())
{
FStaticLightingSystemInterface::OnPrimitiveComponentUnregistered.Broadcast(this);
if (HasValidSettingsForStaticLighting(false))
{
FStaticLightingSystemInterface::OnPrimitiveComponentRegistered.Broadcast(this);
}
}
#endif
}
}
}
set材质调用的是父亲的setmaterial方法 你会发现set的材质会保存在一个叫OverrideMaterials[ElementIndex] = Material;
数组中。
UMaterialInterface* UStaticMeshComponent::GetMaterial(int32 MaterialIndex) const
{
// If we have a base materials array, use that
if(OverrideMaterials.IsValidIndex(MaterialIndex) && OverrideMaterials[MaterialIndex])
{
return OverrideMaterials[MaterialIndex];
}
// Otherwise get from static mesh
else
{
return GetStaticMesh() ? GetStaticMesh()->GetMaterial(MaterialIndex) : nullptr;
}
}
get的时候 先从OverrideMaterials中拿 没有的话 再从mesh中拿
总结 所以存取都会从OverrideMaterials中拿
但是要想获得材质的数量 就 跟OverrideMaterials 没关系了
int32 UStaticMeshComponent::GetNumMaterials() const
{
// @note : you don't have to consider Materials.Num()
// that only counts if overridden and it can't be more than GetStaticMesh()->Materials.
if(GetStaticMesh())
{
return GetStaticMesh()->GetStaticMaterials().Num();
}
else
{
return 0;
}
}
获得材质的数量是直接从mesh上拿的
如果 你 通过数量然后遍历
int32 num = GetNumMaterials();
for(num)
{
GetMaterial(i);
}
这样是错误的;
所以要用到这个方法
int32 UMeshComponent::GetNumOverrideMaterials() const
{
return OverrideMaterials.Num();
}
这样得到的数量就正确了
所以 UStaticMeshComponent的set get 和 它里面的staticmesh 的材质 是 独立的两套。