Modular Pawn

Overview

Contains code to create a basic modular pawn/character with separate head, body & legs.

NOTE: Created with & tested on UE4 beta. May be slight difference between it and public build.

MyCharacter.h

class AMyCharacter : public AMyCharacter
{
    GENERATED_UCLASS_BODY()
 
    /** 
     *  The skeletal mesh used for the body.
     *  Mesh (inherited from ACharacter) will act as characters head.
     */
    UPROPERTY(Category=Character, VisibleAnywhere, BlueprintReadOnly)
    TSubobjectPtr<class USkeletalMeshComponent> Body;
 
    /**
     *  Name of the BodyComponentName.
     *  Use this name if you want to prevent creation of the component (with PCIP.DoNotCreateDefaultSubobject).
     */
    static FName BodyComponentName;
 
    /** 
     *  The skeletal mesh used for the legs.
     *  Mesh (inherited from ACharacter) will act as characters head.
     */
    UPROPERTY(Category=Character, VisibleAnywhere, BlueprintReadOnly)
    TSubobjectPtr<class USkeletalMeshComponent> Legs;
 
    /**
     *  Name of the BodyComponentName.
     *  Use this name if you want to prevent creation of the component (with PCIP.DoNotCreateDefaultSubobject).
     */
    static FName LegsComponentName;
}

MyCharacter.cpp

FName AMyCharacter::BodyComponentName(TEXT("CharacterBody0"));
FName AMyCharacter::LegsComponentName(TEXT("CharacterLegs0"));
 
AMyCharacter::AMyCharacter(const class FPostConstructInitializeProperties& PCIP)
    : Super(PCIP)
{
    static FName CollisionProfileName(TEXT("IgnoreOnlyPawn"));
 
    Body = PCIP.CreateOptionalDefaultSubobject<USkeletalMeshComponent>(this, AMyCharacter::BodyComponentName);
    if (Body)
    {
        Body->AlwaysLoadOnClient = true;
        Body->AlwaysLoadOnServer = true;
        Body->bOwnerNoSee = false;
        Body->MeshComponentUpdateFlag = EMeshComponentUpdateFlag::AlwaysTickPose;
        Body->bCastDynamicShadow = true;
        Body->PrimaryComponentTick.TickGroup = TG_PrePhysics;
        Body->bChartDistanceFactor = true;
        Body->SetCollisionProfileName(CollisionProfileName);
        Body->bGenerateOverlapEvents = false;
 
        // Mesh acts as the head, as well as the parent for both animation and attachment.
        Body->AttachParent = Mesh;
        Body->SetMasterPoseComponent(Mesh);
 
        Components.Add(Body);
    }
 
    Legs = PCIP.CreateOptionalDefaultSubobject<USkeletalMeshComponent>(this, AMyCharacter::LegsComponentName);
    if (Legs)
    {
        Legs->AlwaysLoadOnClient = true;
        Legs->AlwaysLoadOnServer = true;
        Legs->bOwnerNoSee = false;
        Legs->MeshComponentUpdateFlag = EMeshComponentUpdateFlag::AlwaysTickPose;
        Legs->bCastDynamicShadow = true;
        Legs->PrimaryComponentTick.TickGroup = TG_PrePhysics;
        Legs->bChartDistanceFactor = true;
        Legs->SetCollisionProfileName(CollisionProfileName);
        Legs->bGenerateOverlapEvents = false;
 
        // Mesh acts as the head, as well as the parent for both animation and attachment.
        Legs->AttachParent = Mesh;
        Legs->SetMasterPoseComponent(Mesh);
 
        Components.Add(Legs);
    }
}

Usage

  • Create a blueprint based on this character.
  • Under the components tab, find the body & legs components
  • Set the skeletal meshes the body & legs should use.

Kris