首页 > 代码库 > 14040802(攻击骨骼控制)

14040802(攻击骨骼控制)

【目标】

攻击时的骨骼控制

【思路】

1 武器骨骼碰撞时要受碰撞面影响

2 参考FootPlaceMent的机制

3 AUDKPawn.DoFootPlacement

4 为

5

问题:

1)如何确定射线方向

作为参数

2)是否需要三个方向的射线(XYZ轴)

方案:

1 每帧Tick检测碰撞的结果,碰撞的结果影响骨骼位置

2

方案2:

1 USkelControlAttack.CalculateNewBoneTransforms中,从当前骨骼上面找两块骨骼,分别为End Mid Start(Start为最上面的)

2 计算最上面Start到End方向上的射线检测,碰撞的点就是当前

技术分享

【问题】骨骼的方向并不一定是武器下落时的方向,一般情况应是骨骼方向的垂直方向

所以在原方向上要有旋转

3 如果用碰撞体?

4 【问题】

如果碰撞到设置骨骼位置,只影响一块骨骼就会出现

技术分享


如何约束骨骼的旋转

可以采用一根骨骼的方法

技术分享



5 【问题】

武器没有AnimTree,需要手动添加上去

USkeletalMeshComponent.Animations 

是配置到USkeletonMesh上,还是在代码中设置?


6 【问题】

如果检测的结果在正面和反面

技术分享


技术分享

就会出现

技术分享


7


【步骤】

1 新建\Development\Src\Engine\Classes\SkelControlHitPlacement.uc

技术分享


class SkelControlHitPlacement extends SkelControlLimb
    hidecategories(Effector)
    native(Anim);
cpptext
{
    // USkelControlBase interface
    virtual void CalculateNewBoneTransforms(INT BoneIndex, USkeletalMeshComponent* SkelComp, TArray<FBoneAtom>& OutBoneTransforms);    
}
defaultproperties
{
}

编译

2 添加USkelControlHitPlacement.CalculateNewBoneTransforms

void USkelControlHitPlacement::CalculateNewBoneTransforms(INT BoneIndex, USkeletalMeshComponent* SkelComp, TArray<FBoneAtom>& OutBoneTransforms)
{
    check(BoneIndex != 0);
    INT LowerLimbIndex = SkelComp->SkeletalMesh->RefSkeleton(BoneIndex).ParentIndex;
    check(LowerLimbIndex != 0);
    INT UpperLimbIndex = SkelComp->SkeletalMesh->RefSkeleton(LowerLimbIndex).ParentIndex;
    
    // Find the root and end position in world space.
    FVector RootPos = SkelComp->SpaceBases(UpperLimbIndex).GetOrigin();
    FVector WorldRootPos = SkelComp->LocalToWorld.TransformFVector(RootPos);
    FVector EndPos = SkelComp->SpaceBases(BoneIndex).GetOrigin();
    FVector WorldEndPos = SkelComp->LocalToWorld.TransformFVector(EndPos);
    FVector LegDelta = WorldEndPos - WorldRootPos;
    FVector LegDir = LegDelta.SafeNormal();
    FMatrix WorldMatrix = SkelComp->SpaceBases(BoneIndex).ToMatrix() * SkelComp->LocalToWorld;
    LegDir = WorldMatrix.TransformNormal(GetAxisDirVector(AXIS_X,false).SafeNormal());
    FVector CheckEndPos = WorldEndPos + (1000.f) * LegDir;
    FVector HitLocation, HitNormal;
    UBOOL bHit = SkelComp->LegLineCheck( WorldRootPos, CheckEndPos, HitLocation, HitNormal);
    
    AActor* Owner = SkelComp->GetOwner();
    
    if(bHit)
    {
        EffectorLocation = HitLocation;
    }
    else
        EffectorLocation = WorldEndPos;
        EffectorLocationSpace = BCS_WorldSpace;
    Super::CalculateNewBoneTransforms(BoneIndex, SkelComp, OutBoneTransforms);
    check(OutBoneTransforms.Num() == 3);
    if( Owner )
    {
        Owner->DrawDebugLine(WorldRootPos,CheckEndPos,255,0,0);
        Owner->DrawDebugPoint(EffectorLocation,10,FLinearColor(255,255,0));
    }
}

技术分享

换色的点是检测到的射线交点

3 调整射线方向 脚骨骼的Z轴方向

技术分享

绿色点为起点 黄色点为检测到的碰撞点


4 添加属性Development\Src\Engine\Classes\SkelControlHitPlacement.uc

var(Hit)        EAxis                    CheckAxis;
var(Hit)        bool                    bInvertCheckAxis;
var(Hit)        float                    CheckLineRadius;

相应的C++


【问题】

目前只有剑尖有检测,调整的是剑尖的骨骼位置

如果需要中部骨骼检测,再调整体的旋转怎么办?

技术分享


【问题】

技术分享


技术分享 技术分享

细红线为射线,方向有可能两边,交点法线方向

所以,用射线和交点法线方向决定不了骨骼是否碰撞了面


方案1:

    减少射线长度,减少误差,

    就会出现很近才能检测到结果,

方案2:

    交点到骨骼的方向和交点法线方向 (还是不能确定)

技术分享  技术分享


方案3

    骨骼A到B的射线检测,如果有交点且红色射线也检测到交点,说明真正有交点

技术分享

A和B如果都在物体中呢,AB的射线长度多少呢?

方案4

    采取A到C的射线检测,和红色射线检测来共同决定


void USkelControlHitPlacement::CalculateNewBoneTransforms(INT BoneIndex, USkeletalMeshComponent* SkelComp, TArray<FBoneAtom>& OutBoneTransforms)
{
    check(BoneIndex != 0);
    INT LowerLimbIndex = SkelComp->SkeletalMesh->RefSkeleton(BoneIndex).ParentIndex;
    check(LowerLimbIndex != 0);
    INT UpperLimbIndex = SkelComp->SkeletalMesh->RefSkeleton(LowerLimbIndex).ParentIndex;
    
    // Find the root and end position in world space.
    FVector RootPos = SkelComp->SpaceBases(UpperLimbIndex).GetOrigin();
    FVector WorldRootPos = SkelComp->LocalToWorld.TransformFVector(RootPos);
    FVector EndPos = SkelComp->SpaceBases(BoneIndex).GetOrigin();
    FVector WorldEndPos = SkelComp->LocalToWorld.TransformFVector(EndPos);
    FVector LegDelta = WorldEndPos - WorldRootPos;
    FVector LegDir = LegDelta.SafeNormal();
    FMatrix WorldMatrix = SkelComp->SpaceBases(BoneIndex).ToMatrix() * SkelComp->LocalToWorld;
    LegDir = WorldMatrix.TransformNormal(GetAxisDirVector(CheckAxis,bInvertCheckAxis).SafeNormal());
    FVector CheckEndPos = WorldEndPos + CheckLineRadius * LegDir;
    FVector CheckStartPos = WorldEndPos - CheckLineRadius * LegDir;
    FVector HitLocation, HitNormal;
    UBOOL bBoneHit = SkelComp->LegLineCheck( CheckStartPos, CheckEndPos, HitLocation, HitNormal);
    FVector HitLocation2, HitNormal2;
    UBOOL bBoneLineHit = SkelComp->LegLineCheck( WorldEndPos, WorldRootPos, HitLocation2, HitNormal2);
    
    AActor* Owner = SkelComp->GetOwner();
    
    if(bBoneHit && bBoneLineHit)
    {
        EffectorLocation = HitLocation;
    }
    else
        EffectorLocation = WorldEndPos;
    EffectorLocationSpace = BCS_WorldSpace;
    Super::CalculateNewBoneTransforms(BoneIndex, SkelComp, OutBoneTransforms);
    check(OutBoneTransforms.Num() == 3);
    if( Owner )
    {
        Owner->DrawDebugLine(CheckStartPos,CheckEndPos,255,0,0);
        Owner->DrawDebugPoint(EffectorLocation,10,FLinearColor(255,255,0));
        Owner->DrawDebugPoint(WorldRootPos,8,FLinearColor(0,0,255));
        Owner->DrawDebugPoint(CheckEndPos,8,FLinearColor(0,255,255));
        Owner->DrawDebugPoint(CheckStartPos,8,FLinearColor(0,255,0));
    }
}


6



来自为知笔记(Wiz)


14040802(攻击骨骼控制)