Kinect with Unity3D游戏开发的一点思路总结(体感赛车游戏)

Unity3D是一个非常成熟的3D引擎;Kinect可以理解为一个输入设备(像鼠标键盘一样)所以这里技术上的关键点是:将输入信号与3D图形控制结合起来

设计上的关键点是:构造正常人会在2—3平方米的面积内通常可以做的事情(比如让普通人在这个范围内挥动手臂切水果、罚点球、垫排球等等)

这些是笔者这几天接触Kinect with Unity3D以来的最大感受吧。(为什么使用Unity3D呢;因为它含有丰富的例程和已开发资源,所以初期适宜用来移植合适的游戏到Kinect上)

对于第二点,我想也是每一个Kinect人都在探索和寻找创意的;

而第一点,笔者刚玩这俩东西,稍稍分享一些思路。在Unity3D当中,笔者主要是利用了KinectPointController.cs这个官方提供的脚本。

这个脚本实现了识别全身各个关键部位,那么理论上我们只要将这些量通过某种转化关系之后,用来控制Unity3D已有的各个元素,就完成了任务。笔者因此进行了这方面的尝试,得益于Unity3D非常丰富的Sample,笔者选取官方的Car Tutorial进行改造。我们要做的就是根据识别部位的结果,将动作映射到汽车控制的指令,而后进行不断的测试和优化用户体验,即可。

笔者将KinectPointController.cs所挂的PointMan这个包挂在Car上,这样他们就可以一起移动,而后笔者目前只用到左右手、头和脚这几点,因此在unity中不显示PointMan的其他几点mesh。

在unity中通过KinectPointController.cs识别PointMan各点相对Car中心的坐标值,而后进行分析,笔者选取了若干个姿势,包括转方向盘,前倾踩油门和后倾踩刹车及挂倒档,通过试验正确识别后,下面剩下的就是模拟键盘鼠标控制Car的结果了。

在Car tutorial这个示例中,车子的油门和方向盘主要通过Car.js这个脚本中的throttle和steer来进行控制,而KinectPointController.cs是C#脚本,这就涉及C#对js中变量值的操作。Unity支持这样的操作。

笔者先将Car.js移到"Pro Standard Assets”目录下,然后修改上面两个变量为全局变量,而后直接可以在C#中调用Car.js的全局变量。为什么这样做可以参考官方文档:
http://docs.unity3d.com/Documentation/ScriptReference/index.Script_compilation_28Advanced29.html

因此再辅以对Unity3D图形界面下的若干设置和操作,就完成了目前的体感赛车demo,而剩下的就是根据用户体验对操控方式进行优化。

最后附上目前使用的修改后的KinectPointController.cs脚本,其中含有笔者目前对Car.js脚本中变量的操作方式

  1. /*
  2. * KinectModelController.cs - Moves every 'bone' given to match
  3. * the position of the corresponding bone given by
  4. * the kinect. Useful for viewing the point tracking
  5. * in 3D.

  6. * Developed by Peter Kinney -- 6/30/2011

  7. * ____________________________________________
  8. *
  9. * Modified By Chen Zhehuai@Dian -- 11/2/2012
  10. */

  11. using UnityEngine;
  12. using System;
  13. using System.Collections;

  14. public class KinectPointController : MonoBehaviour 
  15. {

  16. //Assignments for a bitmask to control which bones to look at and which to ignore
  17. public enum BoneMask
  18. {
  19. None = 0x0,
  20. Hip_Center = 0x1,
  21. Spine = 0x2,
  22. Shoulder_Center = 0x4,
  23. Head = 0x8,
  24. Shoulder_Left = 0x10,
  25. Elbow_Left = 0x20,
  26. Wrist_Left = 0x40,
  27. Hand_Left = 0x80,
  28. Shoulder_Right = 0x100,
  29. Elbow_Right = 0x200,
  30. Wrist_Right = 0x400,
  31. Hand_Right = 0x800,
  32. Hip_Left = 0x1000,
  33. Knee_Left = 0x2000,
  34. Ankle_Left = 0x4000,
  35. Foot_Left = 0x8000,
  36. Hip_Right = 0x10000,
  37. Knee_Right = 0x20000,
  38. Ankle_Right = 0x40000,
  39. Foot_Right = 0x80000,
  40. All = 0xFFFFF,
  41. Torso = 0x10000F, //the leading bit is used to force the ordering in the editor
  42. Left_Arm = 0x1000F0,
  43. Right_Arm = 0x100F00,
  44. Left_Leg = 0x10F000,
  45. Right_Leg = 0x1F0000,
  46. R_Arm_Chest = Right_Arm | Spine,
  47. No_Feet = All & ~(Foot_Left | Foot_Right)
  48. }

  49. public SkeletonWrapper sw;

  50. public GameObject Hip_Center;
  51. public GameObject Spine;
  52. public GameObject Shoulder_Center;
  53. public GameObject Head;
  54. public GameObject Shoulder_Left;
  55. public GameObject Elbow_Left;
  56. public GameObject Wrist_Left;
  57. public GameObject Hand_Left;
  58. public GameObject Shoulder_Right;
  59. public GameObject Elbow_Right;
  60. public GameObject Wrist_Right;
  61. public GameObject Hand_Right;
  62. public GameObject Hip_Left;
  63. public GameObject Knee_Left;
  64. public GameObject Ankle_Left;
  65. public GameObject Foot_Left;
  66. public GameObject Hip_Right;
  67. public GameObject Knee_Right;
  68. public GameObject Ankle_Right;
  69. public GameObject Foot_Right;

  70. private GameObject[] _bones; //internal handle for the bones of the model
  71. //private Vector4[] _bonePos; //internal handle for the bone positions from the kinect

  72. public int player;
  73. public BoneMask Mask = BoneMask.All;

  74. // Use this for initialization
  75. void Start () {
  76. //store bones in a list for easier access
  77. _bones = new GameObject[(int)Kinect.NuiSkeletonPositionIndex.Count] {Hip_Center, Spine, Shoulder_Center, Head,
  78. Shoulder_Left, Elbow_Left, Wrist_Left, Hand_Left,
  79. Shoulder_Right, Elbow_Right, Wrist_Right, Hand_Right,
  80. Hip_Left, Knee_Left, Ankle_Left, Foot_Left,
  81. Hip_Right, Knee_Right, Ankle_Right, Foot_Right};
  82. //_bonePos = new Vector4[(int)BoneIndex.Num_Bones];




  83. }

  84. // Update is called once per frame
  85. void Update () {
  86. Vector3 leftHand = new Vector3(0,0,0);
  87. Vector3 rightHand = new Vector3(0,0,0);
  88. Vector3 HipCenter = new Vector3(0,0,0);
  89. Vector3 HeadCenter = new Vector3(0,0,0);
  90. Vector3 FootLeft = new Vector3(0,0,0);
  91. Vector3 FootRight = new Vector3(0,0,0);

  92. //update all of the bones positions
  93. if (sw.pollSkeleton())
  94. {
  95. Debug.Log("Has Track\n");
  96. for( int ii = 0; ii < (int)Kinect.NuiSkeletonPositionIndex.Count; ii++) 
  97. {
  98. //_bonePos[ii] = sw.getBonePos(ii);
  99. if( ((uint)Mask & (uint)(1 << ii) ) > 0 ){
  100. _bones[ii].transform.localPosition = sw.bonePos[player,ii];
  101. }
  102. //hip center
  103. if(ii == 0)
  104. {
  105. HipCenter = _bones[ii].transform.localPosition;
  106. // Debug.Log("Hip: x " + _bones[ii].transform.localPosition.x.ToString() + " y " + 
  107. // _bones[ii].transform.localPosition.y.ToString() + " z " +_bones[ii].transform.localPosition.z.ToString()); 

  108. }
  109. //head center
  110. if(ii == 3)
  111. {
  112. HeadCenter = _bones[ii].transform.localPosition;
  113. // Debug.Log("Head: x " + _bones[ii].transform.localPosition.x.ToString() + " y " + 
  114. // _bones[ii].transform.localPosition.y.ToString() + " z " +_bones[ii].transform.localPosition.z.ToString()); 
  115. }
  116. //foot left
  117. if(ii == 15)
  118. {
  119. FootLeft = _bones[ii].transform.localPosition;
  120. // Debug.Log("LeftFoot: x " + _bones[ii].transform.localPosition.x.ToString() + " y " + 
  121. // _bones[ii].transform.localPosition.y.ToString() + " z " +_bones[ii].transform.localPosition.z.ToString()); 
  122. }
  123. if(ii == 19)
  124. {
  125. FootRight = _bones[ii].transform.localPosition;
  126. // Debug.Log("RightFoot: x " + _bones[ii].transform.localPosition.x.ToString() + " y " + 
  127. // _bones[ii].transform.localPosition.y.ToString() + " z " +_bones[ii].transform.localPosition.z.ToString()); 
  128. }
  129. //Right hand
  130. if(ii == 11)
  131. {
  132. rightHand = _bones[ii].transform.localPosition;
  133. // Debug.Log("RightHand: x " + _bones[ii].transform.localPosition.x.ToString() + " y " + 
  134. // _bones[ii].transform.localPosition.y.ToString() + " z " +_bones[ii].transform.localPosition.z.ToString()); 
  135. }
  136. //left hand
  137. if(ii == 7)
  138. {
  139. leftHand = _bones[ii].transform.localPosition;
  140. // Debug.Log("LeftHand: x " + _bones[ii].transform.localPosition.x.ToString() + " y " + 
  141. // _bones[ii].transform.localPosition.y.ToString() + " z " +_bones[ii].transform.localPosition.z.ToString());

  142. }

  143. }


  144. //Event.KeyboardEvent("w");

  145. //Car.throttle = 0.5f;

  146. //Car.throttle = 0;
  147. //Car.steer = 0;

  148. //left hand y+z >2 ;right hand y+z <2 右转
  149. if ((leftHand.y + leftHand.z > 2) && (rightHand.y + leftHand.z < 2))
  150. {
  151. //右转
  152. Car.steer = 1f;
  153. //Car.throttle = 0.5f;
  154. Debug.Log("Right Turn\n");
  155. }
  156. if ((leftHand.y + leftHand.z < 2) && (rightHand.y + leftHand.z > 2))
  157. {
  158. //左转
  159. Car.steer = -1f;
  160. //Car.throttle = 0.5f;
  161. Debug.Log("Left Turn\n");
  162. }
  163. /* 倒车-》后倾;油门-》前倾 */
  164. if ((HeadCenter.x > HipCenter.x + 0.06))
  165. {
  166. Debug.Log("UPUP\n");
  167. Car.throttle = Car.throttle + 0.015f;
  168. if (Car.throttle > 1)
  169. Car.throttle = 1;
  170. }
  171. if ((HeadCenter.x < HipCenter.x) && (FootRight.x < HipCenter.x))
  172. {
  173. Debug.Log("DOWNdown\n");
  174. Car.throttle = Car.throttle - 0.015f;
  175. if (Car.throttle < -1)
  176. Car.throttle = -1;
  177. }

  178. Debug.Log("CS-thro " + Car.throttle); 
  179. Debug.Log("CS-stee " + Car.steer); 

  180. }
  181. else
  182. {
  183. Car.throttle = 0f;
  184. Debug.Log("Not Track--Down\n");
  185. }
  186. }
  187. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值