【目标】
CCDIKRecoil
【思路】
1 CCDIK和Recoil的结合
2 Recoil的回弹机制,逐渐回到原来位置
3 添加一个Recoil基类
【步骤】
1 将\Src\GameFramework\Classes\GameSkelCtrl_Recoil.uc复制到\Src\Engine\Classes\SkelControlRecoilBase.uc
修改一下名称 作为基类
2 其他相关类继承于SkelControlRecoilBase, \Engine\Classes\SkelControlLimbRecoil.uc
make一下
编译不通过
原因是USkeletalControlRecoilBase是在后面声明的
方案:
采取将派生类放GameFrameWork工程中
编译后发现
这里有语法错误
最后还是没有用继承方式,脚本目前很难使用双基类
所以目前还是重复写相同代码
3 添加一个继承类GameSkelCtrl_CCD_IK_Recoil_CCD_IK_Recoil.uc,放到GameFramework中,否则又牵扯到那些结构体声明的先后顺序问题
4 在GameSkelControls.cpp 中添加实现宏,及函数实现
IMPLEMENT_CLASS(UGameSkelCtrl_CCD_IK_Recoil);
/*-----------------------------------------------------------------------------UGameSkelCtrl_CCD_IK_Recoil-----------------------------------------------------------------------------*/FVector2DUGameSkelCtrl_CCD_IK_Recoil::GetAim(USkeletalMeshComponent*InSkelComponent){returnAim;}/** Is skeleton currently mirrored */UBOOL UGameSkelCtrl_CCD_IK_Recoil::IsMirrored(USkeletalMeshComponent*InSkelComponent){return FALSE;}// USkelControlBase interfacevoidUGameSkelCtrl_CCD_IK_Recoil::TickSkelControl(FLOAT DeltaSeconds,USkeletalMeshComponent*SkelComp){bApplyControl = FALSE;if(ControlStrength> ZERO_ANIMWEIGHT_THRESH ){// if willing to play recoil, reset its stateif( bPlayRecoil != bOldPlayRecoil ){bPlayRecoil = bOldPlayRecoil;Recoil.TimeToGo=Recoil.TimeDuration;// ERS_Random == Start at random position along sine wave,// ERS_Zero == Start at 0const 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 outconst 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 componentif(!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 componentif(!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);}voidUGameSkelCtrl_CCD_IK_Recoil::GetAffectedBones(INT BoneIndex,USkeletalMeshComponent*SkelComp,TArray<INT>&OutBoneIndices){check(OutBoneIndices.Num()==0);// Only process bone if there is something to doif( bApplyControl )Super::GetAffectedBones(BoneIndex,SkelComp,OutBoneIndices);}voidUGameSkelCtrl_CCD_IK_Recoil::CalculateNewBoneTransforms(INT BoneIndex,USkeletalMeshComponent*SkelComp,TArray<FBoneAtom>&OutBoneTransforms){check(OutBoneTransforms.Num()==0);// Current bone transform matrix in component spaceFBoneAtomNewBoneTM=SkelComp->SpaceBases(BoneIndex);if(bBoneSpaceRecoil){if(!Recoil.LocOffset.IsZero()||!Recoil.RotOffset.IsZero()){FBoneAtomRecoilTM(Recoil.RotOffset,Recoil.LocOffset);NewBoneTM=RecoilTM*NewBoneTM;OutBoneTransforms.AddItem(NewBoneTM);}return;}// Extract AimAim=GetAim(SkelComp);// Actor to Aim transform matrixconstFRotatorAimRotOffset( appTrunc(Aim.Y*16384), appTrunc(Aim.X*16384),0);FBoneAtomActorToAim(AimRotOffset,FVector::ZeroVector);ActorToAim.RemoveScaling();ActorToAim.SetOrigin(FVector(0.f));constFBoneAtomAimToActor=ActorToAim.Inverse();// Component to Actor transform matrixFBoneAtomComponentToActor=SkelComp->CalcComponentToFrameMatrix(BoneIndex, BCS_ActorSpace, NAME_None);ComponentToActor.RemoveScaling();ComponentToActor.SetOrigin(FVector(0.f));constFBoneAtomActorToComponent=ComponentToActor.InverseSafe();// Add rotation offset in component spaceif(!Recoil.RotOffset.IsZero()){FRotatorRotOffset=Recoil.RotOffset;// Handle mirroringif(IsMirrored(SkelComp)){RotOffset.Yaw=-RotOffset.Yaw;}FBoneAtomNewRotTM=NewBoneTM*(ComponentToActor*(AimToActor*FBoneAtom(RotOffset,FVector::ZeroVector)*ActorToAim)*ActorToComponent);NewRotTM.SetOrigin(NewBoneTM.GetOrigin());NewBoneTM=NewRotTM;}// Add location offset in component spaceif(!Recoil.LocOffset.IsZero()){FVectorLocOffset=Recoil.LocOffset;// Handle mirroringif(IsMirrored(SkelComp)){LocOffset.Y =-LocOffset.Y;}constFVectorTransInWorld=ActorToAim.TransformNormal(LocOffset);constFVectorTransInComp=ActorToComponent.TransformNormal(TransInWorld);constFVectorNewOrigin=NewBoneTM.GetOrigin()+TransInComp;NewBoneTM.SetOrigin(NewOrigin);}// OutBoneTransforms.AddItem(NewBoneTM);EffectorLocation=NewBoneTM.GetOrigin();EffectorLocationSpace= BCS_WorldSpace;Super::CalculateNewBoneTransforms(BoneIndex,SkelComp,OutBoneTransforms);}
5 运行

如果单独一根骨骼的Recoil

6
浙公网安备 33010602011771号