【目标】

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 中添加实现宏,及函数实现

  1. IMPLEMENT_CLASS(UGameSkelCtrl_CCD_IK_Recoil);
 
  1. /*-----------------------------------------------------------------------------
  2. UGameSkelCtrl_CCD_IK_Recoil
  3. -----------------------------------------------------------------------------*/
  4. FVector2DUGameSkelCtrl_CCD_IK_Recoil::GetAim(USkeletalMeshComponent*InSkelComponent)
  5. {
  6. returnAim;
  7. }
  8. /** Is skeleton currently mirrored */
  9. UBOOL UGameSkelCtrl_CCD_IK_Recoil::IsMirrored(USkeletalMeshComponent*InSkelComponent)
  10. {
  11. return FALSE;
  12. }
  13. // USkelControlBase interface
  14. voidUGameSkelCtrl_CCD_IK_Recoil::TickSkelControl(FLOAT DeltaSeconds,USkeletalMeshComponent*SkelComp)
  15. {
  16. bApplyControl = FALSE;
  17. if(ControlStrength> ZERO_ANIMWEIGHT_THRESH )
  18. {
  19. // if willing to play recoil, reset its state
  20. if( bPlayRecoil != bOldPlayRecoil )
  21. {
  22. bPlayRecoil = bOldPlayRecoil;
  23. Recoil.TimeToGo=Recoil.TimeDuration;
  24. // ERS_Random == Start at random position along sine wave,
  25. // ERS_Zero == Start at 0
  26. const FLOAT TWO_PI =2.f*(FLOAT)PI;
  27. Recoil.RotSinOffset.X =Recoil.RotParams.X == ERS_Random ? appFrand()* TWO_PI :0.f;
  28. Recoil.RotSinOffset.Y =Recoil.RotParams.Y == ERS_Random ? appFrand()* TWO_PI :0.f;
  29. Recoil.RotSinOffset.Z =Recoil.RotParams.Z == ERS_Random ? appFrand()* TWO_PI :0.f;
  30. Recoil.LocSinOffset.X =Recoil.LocParams.X == ERS_Random ? appFrand()* TWO_PI :0.f;
  31. Recoil.LocSinOffset.Y =Recoil.LocParams.Y == ERS_Random ? appFrand()* TWO_PI :0.f;
  32. Recoil.LocSinOffset.Z =Recoil.LocParams.Z == ERS_Random ? appFrand()* TWO_PI :0.f;
  33. Recoil.RotOffset=FRotator(0,0,0);
  34. Recoil.LocOffset=FVector(0.f);
  35. }
  36. if(Recoil.TimeToGo>DeltaSeconds)
  37. {
  38. Recoil.TimeToGo-=DeltaSeconds;
  39. if(Recoil.TimeToGo>0.f)
  40. {
  41. bApplyControl = TRUE;
  42. // Smooth fade out
  43. const FLOAT TimePct=Clamp<FLOAT>(Recoil.TimeToGo/Recoil.TimeDuration,0.f,1.f);
  44. const FLOAT Alpha=TimePct*TimePct*(3.f-2.f*TimePct);
  45. const FLOAT AlphaTimesDelta=Alpha*DeltaSeconds;
  46. // Recoil Bone Rotation, compute sin wave value for each component
  47. if(!Recoil.RotAmplitude.IsZero())
  48. {
  49. if(Recoil.RotAmplitude.X !=0.f)
  50. {
  51. Recoil.RotSinOffset.X +=AlphaTimesDelta*Recoil.RotFrequency.X;
  52. Recoil.RotOffset.Pitch= appTrunc(Alpha*Recoil.RotAmplitude.X * appSin(Recoil.RotSinOffset.X));
  53. }
  54. if(Recoil.RotAmplitude.Y !=0.f)
  55. {
  56. Recoil.RotSinOffset.Y +=AlphaTimesDelta*Recoil.RotFrequency.Y;
  57. Recoil.RotOffset.Yaw= appTrunc(Alpha*Recoil.RotAmplitude.Y * appSin(Recoil.RotSinOffset.Y));
  58. }
  59. if(Recoil.RotAmplitude.Z !=0.f)
  60. {
  61. Recoil.RotSinOffset.Z +=AlphaTimesDelta*Recoil.RotFrequency.Z;
  62. Recoil.RotOffset.Roll= appTrunc(Alpha*Recoil.RotAmplitude.Z * appSin(Recoil.RotSinOffset.Z));
  63. }
  64. }
  65. // Recoil Bone Location, compute sin wave value for each component
  66. if(!Recoil.LocAmplitude.IsZero())
  67. {
  68. if(Recoil.LocAmplitude.X !=0.f)
  69. {
  70. Recoil.LocSinOffset.X +=AlphaTimesDelta*Recoil.LocFrequency.X;
  71. Recoil.LocOffset.X =Alpha*Recoil.LocAmplitude.X * appSin(Recoil.LocSinOffset.X);
  72. }
  73. if(Recoil.LocAmplitude.Y !=0.f)
  74. {
  75. Recoil.LocSinOffset.Y +=AlphaTimesDelta*Recoil.LocFrequency.Y;
  76. Recoil.LocOffset.Y =Alpha*Recoil.LocAmplitude.Y * appSin(Recoil.LocSinOffset.Y);
  77. }
  78. if(Recoil.LocAmplitude.Z !=0.f)
  79. {
  80. Recoil.LocSinOffset.Z +=AlphaTimesDelta*Recoil.LocFrequency.Z;
  81. Recoil.LocOffset.Z =Alpha*Recoil.LocAmplitude.Z * appSin(Recoil.LocSinOffset.Z);
  82. }
  83. }
  84. }
  85. }
  86. }
  87. Super::TickSkelControl(DeltaSeconds,SkelComp);
  88. }
  89. voidUGameSkelCtrl_CCD_IK_Recoil::GetAffectedBones(INT BoneIndex,USkeletalMeshComponent*SkelComp,TArray<INT>&OutBoneIndices)
  90. {
  91. check(OutBoneIndices.Num()==0);
  92. // Only process bone if there is something to do
  93. if( bApplyControl )
  94. Super::GetAffectedBones(BoneIndex,SkelComp,OutBoneIndices);
  95. }
  96. voidUGameSkelCtrl_CCD_IK_Recoil::CalculateNewBoneTransforms(INT BoneIndex,USkeletalMeshComponent*SkelComp,TArray<FBoneAtom>&OutBoneTransforms)
  97. {
  98. check(OutBoneTransforms.Num()==0);
  99. // Current bone transform matrix in component space
  100. FBoneAtomNewBoneTM=SkelComp->SpaceBases(BoneIndex);
  101. if(bBoneSpaceRecoil)
  102. {
  103. if(!Recoil.LocOffset.IsZero()||!Recoil.RotOffset.IsZero())
  104. {
  105. FBoneAtomRecoilTM(Recoil.RotOffset,Recoil.LocOffset);
  106. NewBoneTM=RecoilTM*NewBoneTM;
  107. OutBoneTransforms.AddItem(NewBoneTM);
  108. }
  109. return;
  110. }
  111. // Extract Aim
  112. Aim=GetAim(SkelComp);
  113. // Actor to Aim transform matrix
  114. constFRotatorAimRotOffset( appTrunc(Aim.Y*16384), appTrunc(Aim.X*16384),0);
  115. FBoneAtomActorToAim(AimRotOffset,FVector::ZeroVector);
  116. ActorToAim.RemoveScaling();
  117. ActorToAim.SetOrigin(FVector(0.f));
  118. constFBoneAtomAimToActor=ActorToAim.Inverse();
  119. // Component to Actor transform matrix
  120. FBoneAtomComponentToActor=SkelComp->CalcComponentToFrameMatrix(BoneIndex, BCS_ActorSpace, NAME_None);
  121. ComponentToActor.RemoveScaling();
  122. ComponentToActor.SetOrigin(FVector(0.f));
  123. constFBoneAtomActorToComponent=ComponentToActor.InverseSafe();
  124. // Add rotation offset in component space
  125. if(!Recoil.RotOffset.IsZero())
  126. {
  127. FRotatorRotOffset=Recoil.RotOffset;
  128. // Handle mirroring
  129. if(IsMirrored(SkelComp))
  130. {
  131. RotOffset.Yaw=-RotOffset.Yaw;
  132. }
  133. FBoneAtomNewRotTM=NewBoneTM*(ComponentToActor*(AimToActor*FBoneAtom(RotOffset,FVector::ZeroVector)*ActorToAim)*ActorToComponent);
  134. NewRotTM.SetOrigin(NewBoneTM.GetOrigin());
  135. NewBoneTM=NewRotTM;
  136. }
  137. // Add location offset in component space
  138. if(!Recoil.LocOffset.IsZero())
  139. {
  140. FVectorLocOffset=Recoil.LocOffset;
  141. // Handle mirroring
  142. if(IsMirrored(SkelComp))
  143. {
  144. LocOffset.Y =-LocOffset.Y;
  145. }
  146. constFVectorTransInWorld=ActorToAim.TransformNormal(LocOffset);
  147. constFVectorTransInComp=ActorToComponent.TransformNormal(TransInWorld);
  148. constFVectorNewOrigin=NewBoneTM.GetOrigin()+TransInComp;
  149. NewBoneTM.SetOrigin(NewOrigin);
  150. }
  151. // OutBoneTransforms.AddItem(NewBoneTM);
  152. EffectorLocation=NewBoneTM.GetOrigin();
  153. EffectorLocationSpace= BCS_WorldSpace;
  154. Super::CalculateNewBoneTransforms(BoneIndex,SkelComp,OutBoneTransforms);
  155. }
 

5 运行

如果单独一根骨骼的Recoil

 
 

6

14073102(CCDIKRecoil)的更多相关文章

  1. Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求

    上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...

  2. Angular2学习笔记(1)

    Angular2学习笔记(1) 1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之 ...

  3. ASP.NET Core 之 Identity 入门(一)

    前言 在 ASP.NET Core 中,仍然沿用了 ASP.NET里面的 Identity 组件库,负责对用户的身份进行认证,总体来说的话,没有MVC 5 里面那么复杂,因为在MVC 5里面引入了OW ...

  4. ABP入门系列(1)——学习Abp框架之实操演练

    作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...

  5. Online Judge(OJ)搭建(第一版)

    搭建 OJ 需要的知识(重要性排序): Java SE(Basic Knowledge, String, FileWriter, JavaCompiler, URLClassLoader, Secur ...

  6. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  7. 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成

    阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...

  8. 【.net 深呼吸】细说CodeDom(5):类型成员

    前文中,老周已经厚着脸皮介绍了类型的声明,类型里面包含的自然就是类型成员了,故,顺着这个思路,今天咱们就了解一下如何向类型添加成员. 咱们都知道,常见的类型成员,比如字段.属性.方法.事件.表示代码成 ...

  9. 【.net 深呼吸】细说CodeDom(4):类型定义

    上一篇文章中说了命名空间,你猜猜接下来该说啥.是了,命名空间下面就是类型,知道了如何生成命名空间的定义代码,之后就该学会如何声明类型了. CLR的类型通常有这么几种:类.接口.结构.枚举.委托.是这么 ...

随机推荐

  1. 传感器介绍之DHT11

    一.DHT11介绍 DHT11 数字温湿度传感器,如图所示,是一款含有已校准数字信号输出的温湿度复合传感器.它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性.传 ...

  2. 进军Linux

    大二的时候学习Java,学完Java SE之后就放弃了这条道路,踏上了嵌入式之路.那时候约定好,选择了DSP,从C2000开始学起,基础仅仅是会C51,有C语言和Java的基础.这几年随着项目的需求变 ...

  3. ssh远程执行命令

    ssh -p $port $user@$p 'cmd' $port : ssh连接端口号 $user: ssh连接用户名 $ip:ssh连接的ip地址 cmd:远程服务器需要执行的操作 ssh -p ...

  4. PHP基础结业感想与总结!

    之前来传智是我认真调查和思考后得出的结论,我做程序员的第一目标是赚钱和学习技术,有一句话"艺多不压身".相信班上所有人的目标都是,这一点都不会庸俗,但是各个人的目的就未必一样了.我 ...

  5. mysql导入乱码问题,centOS

    CREATE DATABASE db_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;mysql -uroot -p --default ...

  6. Upload Files To FTP in Oracle Forms D2k

    Upload Files To FTP in Oracle Forms D2k Use following procedure to upload files to Ftp.   PROCEDURE ...

  7. Sprint第三阶段(第四天12.12)

  8. layer弹出层全屏及关闭

    一.首先引用JS文件 <script src="../../js/common/layer/layer.js"></script> 二.全屏调用以下代码 v ...

  9. HTML5部分新标签属性及DOM扩展元素

    HTML5定义了一系列新元素,如新语义标签.智能表单.多媒体标签等. 我们日常讨论的H5其实是一个泛称,它指的是由HTML5 + CSS3 + Javascript等技术组合而成的一个应用开发平台. ...

  10. 写日志 log 到文件夹

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...