【目标】
带IK的Recoil
【思路】
1 继承于USkelControlLimb和UGameSkelCtrl_Recoil
2 效果对比
以这个骨骼为例
Recoil
Limb
可见,Recoil只影响一根骨骼
如果两个结合就是,Recoil产生的冲击位移作为Limb的控制点,由控制点带动三根骨骼的移动
【步骤】
1 在\ue3\Development\Src\Engine\Classes中新建SkelControlLimbRecoil.uc
先复制\ue3\Development\Src\GameFramework\Classes\GameSkelCtrl_Recoil.uc的内容
make 后 编译代码会出现结构体 枚举 重命名
需要将\GameSkelCtrl_Recoil.uc的结构体 枚举注释掉
2 在UnSkelControl.cpp 添加类实现
IMPLEMENT_CLASS(USkelControlLimbRecoil)
...
/*-----------------------------------------------------------------------------
USkelControlLimbRecoil
-----------------------------------------------------------------------------*/
FVector2D USkelControlLimbRecoil::GetAim(USkeletalMeshComponent* InSkelComponent)
{
return Aim;
}
/** Is skeleton currently mirrored */
UBOOL USkelControlLimbRecoil::IsMirrored(USkeletalMeshComponent* InSkelComponent)
{
return FALSE;
}
// USkelControlBase interface
void USkelControlLimbRecoil::TickSkelControl(FLOAT DeltaSeconds, USkeletalMeshComponent* SkelComp)
{
bApplyControl = FALSE;
if( ControlStrength > ZERO_ANIMWEIGHT_THRESH )
{
// if willing to play recoil, reset its state
if( bPlayRecoil != bOldPlayRecoil )
{
bPlayRecoil = bOldPlayRecoil;
Recoil.TimeToGo = Recoil.TimeDuration;
// ERS_Random == Start at random position along sine wave,
// ERS_Zero == Start at 0
const FLOAT TWO_PI = 2.f * (FLOAT)PI;
Recoil.RotSinOffset.X = Recoil.RotParams.X == ERS_Random ? appFrand() * TWO_PI : 0.f;
Recoil.RotSinOffset.Y = Recoil.RotParams.Y == ERS_Random ? appFrand() * TWO_PI : 0.f;
Recoil.RotSinOffset.Z = Recoil.RotParams.Z == ERS_Random ? appFrand() * TWO_PI : 0.f;
Recoil.LocSinOffset.X = Recoil.LocParams.X == ERS_Random ? appFrand() * TWO_PI : 0.f;
Recoil.LocSinOffset.Y = Recoil.LocParams.Y == ERS_Random ? appFrand() * TWO_PI : 0.f;
Recoil.LocSinOffset.Z = Recoil.LocParams.Z == ERS_Random ? appFrand() * TWO_PI : 0.f;
Recoil.RotOffset = FRotator(0,0,0);
Recoil.LocOffset = FVector(0.f);
}
if( Recoil.TimeToGo > DeltaSeconds )
{
Recoil.TimeToGo -= DeltaSeconds;
if( Recoil.TimeToGo > 0.f )
{
bApplyControl = TRUE;
// Smooth fade out
const FLOAT TimePct = Clamp<FLOAT>(Recoil.TimeToGo / Recoil.TimeDuration, 0.f, 1.f);
const FLOAT Alpha = TimePct*TimePct*(3.f - 2.f*TimePct);
const FLOAT AlphaTimesDelta = Alpha * DeltaSeconds;
// Recoil Bone Rotation, compute sin wave value for each component
if( !Recoil.RotAmplitude.IsZero() )
{
if( Recoil.RotAmplitude.X != 0.f )
{
Recoil.RotSinOffset.X += AlphaTimesDelta * Recoil.RotFrequency.X;
Recoil.RotOffset.Pitch = appTrunc(Alpha * Recoil.RotAmplitude.X * appSin(Recoil.RotSinOffset.X));
}
if( Recoil.RotAmplitude.Y != 0.f )
{
Recoil.RotSinOffset.Y += AlphaTimesDelta * Recoil.RotFrequency.Y;
Recoil.RotOffset.Yaw = appTrunc(Alpha * Recoil.RotAmplitude.Y * appSin(Recoil.RotSinOffset.Y));
}
if( Recoil.RotAmplitude.Z != 0.f )
{
Recoil.RotSinOffset.Z += AlphaTimesDelta * Recoil.RotFrequency.Z;
Recoil.RotOffset.Roll = appTrunc(Alpha * Recoil.RotAmplitude.Z * appSin(Recoil.RotSinOffset.Z));
}
}
// Recoil Bone Location, compute sin wave value for each component
if( !Recoil.LocAmplitude.IsZero() )
{
if( Recoil.LocAmplitude.X != 0.f )
{
Recoil.LocSinOffset.X += AlphaTimesDelta * Recoil.LocFrequency.X;
Recoil.LocOffset.X = Alpha * Recoil.LocAmplitude.X * appSin(Recoil.LocSinOffset.X);
}
if( Recoil.LocAmplitude.Y != 0.f )
{
Recoil.LocSinOffset.Y += AlphaTimesDelta * Recoil.LocFrequency.Y;
Recoil.LocOffset.Y = Alpha * Recoil.LocAmplitude.Y * appSin(Recoil.LocSinOffset.Y);
}
if( Recoil.LocAmplitude.Z != 0.f )
{
Recoil.LocSinOffset.Z += AlphaTimesDelta * Recoil.LocFrequency.Z;
Recoil.LocOffset.Z = Alpha * Recoil.LocAmplitude.Z * appSin(Recoil.LocSinOffset.Z);
}
}
}
}
}
Super::TickSkelControl(DeltaSeconds, SkelComp);
}
void USkelControlLimbRecoil::CalculateNewBoneTransforms(INT BoneIndex, USkeletalMeshComponent* SkelComp, TArray<FBoneAtom>& OutBoneTransforms)
{
Super::CalculateNewBoneTransforms(BoneIndex, SkelComp, OutBoneTransforms);
}
现在需要将USkelControlLimb.EffectorLocation 设置为Recoil影响的骨骼的更新的位置
3
4
时间: 2024-10-13 14:04:49