基本思路
1,拷贝一个和人物一样的骨骼模型
2,将该骨骼模型的颜色改为黑色
3,模型沿法线方向外扩
4,根据法线方向只渲染模型的背面
5,模型实时同步主模型的位置和姿态
材质部分
1,创建一个无光照的表面材质
2,混合模型改为已遮罩
2,材质中双面属性设置为true,否则背面会被剔除
3,根据顶点法线和该点到相机的方向的点积判断该点是否是模型正面
4,将正面的点的不透明蒙版设置成0
5,将顶点向法线方向进行外扩
C++部分
1,新建一个AActor的派生类
2,类中添加USkeletalMeshComponent成员
3,构造函数中给该成员分配与玩家角色一致的骨骼模型
4,加载描边的材质,将骨骼模型中的所有材质都设置为描边材质
5,在Tick函数中查找玩家角色的骨骼模型,并将玩家角色的骨骼模型的位置和姿态同步到该类对象的骨骼模型上
// 构造函数
if (mesh == nullptr) {
mesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("mesh"));
mesh->SetupAttachment(RootComponent);
static ConstructorHelpers::FObjectFinder<USkeletalMesh> locMesh(TEXT("SkeletalMesh'/YourSkeletalMesh'"));
if (locMesh.Succeeded()) {
mesh->SetSkeletalMesh(locMesh.Object, false);
}
static ConstructorHelpers::FObjectFinder<UMaterialInstance> MaterialObj(TEXT("MaterialInstanceConstant'/YourMaterialInst'"));
if (MaterialObj.Succeeded()) {
int matNum = mesh->GetNumMaterials();
for (int i = 0; i < matNum; i++) {
mesh->SetMaterial(i, MaterialObj.Object);
}
}
}
//Tick
USkeletalMeshComponent* source = nullptr;
for (TActorIterator<UYourCharacter> itr(GetWorld()); itr; ++itr)
{
ADEMOUSECharacter* master = *itr;
master->GetTransform();
source = itr->FindComponentByClass<USkeletalMeshComponent>();
break;
}
if (source)
{
// 同步位置和朝向
this->SetActorTransform(source->GetComponentTransform());
// 同步骨骼模型姿态
mesh->SetMasterPoseComponent(source);
}
效果展示