Download

Copying structures in the Engine

Consider the two structs


struct FActorComponentTickFunction PrimaryComponentTick, SecondaryComponentTick;

where FActorComponentTickFunctionis defined in EngineBaseTypes.h.

I was wondering what is the Engine solution to duplicate the those objects. Clearly


PrimaryComponentTick = SecondaryComponentTick

is *not safe *(not to mention scary as per UT code!) because of the snippet


// It is unsafe to copy FTickFunctions and any subclasses of FTickFunction should specify the type trait WithCopy = false
    FTickFunction& operator=(const FTickFunction&) = delete;

easily found in EngineBaseTypes.h.

Probably there is no reason to duplicate TickFunction in UE4. Since the address of TickFunction would be registered into TickTaskManager, duplication may cause single TickFunction be called multiple times. To using the pointer of your TickFunction may suit for your case.

Ok, I will have to update the UT code accordingly then. Thanks.
Just so if anyone is curious enough the code is present in UnrealTournament.cpp


UMeshComponent* CreateCustomDepthOutlineMesh(UMeshComponent* Archetype, AActor* Owner)
{
    UMeshComponent* CustomDepthMesh = DuplicateObject<UMeshComponent>(Archetype, Owner);
    CustomDepthMesh->DetachFromComponent(FDetachmentTransformRules::KeepRelativeTransform);
    if (Cast<USkeletalMeshComponent>(CustomDepthMesh) != nullptr)
    {
        // TODO: scary that these get copied, need an engine solution and/or safe way to duplicate objects during gameplay
        ((USkeletalMeshComponent*)CustomDepthMesh)->PrimaryComponentTick = CustomDepthMesh->GetClass()->GetDefaultObject<USkeletalMeshComponent>()->PrimaryComponentTick);// = CustomDepthMesh->GetClass()->GetDefaultObject<USkeletalMeshComponent>()->PrimaryComponentTick;
        ((USkeletalMeshComponent*)CustomDepthMesh)->PostPhysicsComponentTick = CustomDepthMesh->GetClass()->GetDefaultObject<USkeletalMeshComponent>()->PostPhysicsComponentTick;
    }
    CustomDepthMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision); // make sure because could be in ragdoll
    CustomDepthMesh->SetSimulatePhysics(false);
    CustomDepthMesh->SetCastShadow(false);
    if (Cast<USkinnedMeshComponent>(CustomDepthMesh) != nullptr)
    {
        ((USkinnedMeshComponent*)CustomDepthMesh)->SetMasterPoseComponent((USkinnedMeshComponent*)Archetype);
    }
    for (int32 i = 0; i < CustomDepthMesh->GetNumMaterials(); i++)
    {
        CustomDepthMesh->SetMaterial(i, UMaterial::GetDefaultMaterial(MD_Surface));
    }
    CustomDepthMesh->BoundsScale = 15000.f;
    CustomDepthMesh->bVisible = true;
    CustomDepthMesh->bHiddenInGame = false;
    CustomDepthMesh->bRenderInMainPass = false;
    CustomDepthMesh->bRenderCustomDepth = true;
    CustomDepthMesh->AttachToComponent(Archetype, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
    CustomDepthMesh->RelativeLocation = FVector::ZeroVector;
    CustomDepthMesh->RelativeRotation = FRotator::ZeroRotator;
    CustomDepthMesh->RelativeScale3D = FVector(1.0f, 1.0f, 1.0f);
    return CustomDepthMesh;
}