[图文教程]Unity3D+Kinect由浅入深教程:Unity3D官方赛车游戏简单改造[复制链接]
绅士小徐
新手
入会
升
级
22
%
银子
90
两
金子
两
威望
点
?串
个
门
?加
好
友
?打
招
电梯直达
楼主
发表于 2012-12-17 14:36:19 |只看该作者|倒序浏览
本帖最后由绅士小徐于 2012-12-17 15:16 编辑
前两天刚开始接触Unity3D,看了个简单的教程后,想尝试做点东西,然而却苦于自己不会制作素材,刚接触没几天,也不知道什
么地方的素材比较好用。随便逛了下论坛,突然间发现了
https://www.sodocs.net/doc/4815310394.html,/support/resources/files/CarTutorial.zip官
方的这个资源,觉得素材非常不错,倍感兴奋;不过,个人感觉是开
起来难度非常大~~~~~冬天比较冷,于是想用Kinect连上去试一试,
来锻炼锻炼身体,无论如何,先从最简单的做起,今天顺便做出第一
篇个人的KinectU3D由浅入深教程并且提供自己制作的开发中间件。
大家注意,我是将数据传输到Unity3D的C#脚本内部来处理的,而不
是通过键盘模拟形式,也许有人会问我为啥不用键盘模拟模拟,就这
个游戏而言,的确不会有啥区别。吾曰:我做这个整合不是仅仅为了
这个游戏,例如,以后如果有更加复杂的项目,例如市面上喊得比较
火的试衣镜,那你怎么用键盘模拟?
(https://www.sodocs.net/doc/4815310394.html,/v_show/id_XMjU4MjExNjgw.html )最后,连
接成功,自定义了四种简单的姿势,前倾后仰左倾右倾分别来代替前
后左右的方向控制,并且,注意玩的时候要举起双手到胸前,基本上
就是下面图中的样子(有个镜面问题,看到左上角从kinect传输过来
的RGB流,左右刚好相反)
呼
发
消
息
连玩之后,先说明这么几个问题:
(1)本来是想把Camera镜头放到车里面的驾驶座那儿,这样子会更
加身临其境一些,但是,这辆车里面实在太丑了,于是,就不改变视
角了;
(2)还是那个问题,本身这个游戏键盘控制起来都不算舒服,连上
kinect后开起来的难度会比原来的还大一点~当然,最重要的不是为
了让大家玩好这个游戏,而是希望大家能通过这个例子,自己好好研
究研究,能做出其他更好的kinect、Unity3D游戏;
(3)我的电脑CPU很低,延时大一点,如果电脑不好的话,建立把左
上角的视频呈现(RGB)关掉,等会儿说。
(4)我的kinect还是旧版的kinect xbox 360 ,目前无法开启
near mode,也就是近端模式(坐在电脑前也能使用,但是识别的是
上半身)。
(5)要是试过碰到什么不好的地方请留言提意见;碰到bug的话,更
要及时回复我。
下面就教大家来一步步搞完这个东西:
一、写出一个Unity和Kinect数据通信的中间件,主要是把kinect
端的骨骼点数据(人的20个骨骼点在空间的三维坐标)和RGB流接收
过来,骨骼点数据如下图所示:
https://www.sodocs.net/doc/4815310394.html,/?p=1764。推荐大家使用卡耐基梅隆那个kinectWrapper,上去wiki看看使用法。这玩意儿功能还凑合,但是,没有kinect基础的人很难用得了。如果追求傻瓜式开发法,毕竟在天地会开贴要考虑到大部分只会Unity3D,不懂kinect的朋友,那么,就用我写的东西,等给大家介绍傻瓜式应用法。目前比较简单,只加入了用到的东西,只有彩色数据和骨骼数据(分别对应视频块和20个骨骼三维坐标点),特别是骨骼点数据,千万不要小看他,大部分的动作姿势都是依靠这些点的运动规律再结合计时器来完成的,像KTU 一样绑定一个人体模型需要大家自己去动下脑子,做下坐标换算,目前读取出来的坐标是最原始的kinect坐标,原始的坐标比较容易被理解,也方便于大家自我改造。以下是坐标范围的官方解释:
The skeleton(骨骼) position data ranges are:
Values of x range from approximately -2.2 to +2.2.
//x是平行于kinect的方向,以人正对于kinect摄像头前方而言,正//中间是0,人的左边是-2.2~0,人的右边是0~2.2,单位是米。
Values of y range from approximately -1.6 to +1.6.
//y向上,越上越大
Values of z range from 0.0 to 4.0.
//剩下的一维从摄像头到人的直线方向就是z,离得越远越大。
之后会逐步添加新的功能进去,并且及时发布傻瓜式使用法,只要别太过于心浮气躁就能使用。
二、下面代码加文字说明,我的这个简单的wrapper的大体意思,要
打开EggWrapper.cs,先看最下面,这些方法是最核心的地方,分别对应着KUInteractive.dll中的方法,调用dll的方法,完成对kinect
的操作:
然后依次从上往下看,介绍下主要属性和方法:
VideoWidth 、VideoHeight :Kinect端RGB彩色数据分辨率。UpdateRGB:动态更新RGB数据,为了实时获得最新数据,调用时将该方法置入update函数中,处理后返回值是Color[],像素块数据。updateSkeletons:动态更新骨骼三维数据,为了实时获得最新数据,调用时将该方法置入update函数中
hasSkeleton:判断是否已经识别人体骨骼
getKinectTime:获得时间,单位是毫秒。(用时间来结合骨骼坐标来做人体姿态运算)
GetSkeletonPosition:获取骨骼坐标,传入参数为枚举类型Joints 中的元素,依次对应相应的人体骨骼点。
三、最后,代码加文字加赛车实践说明具体使用法。
(1)无论如何,请先安装kinect sdk1.5(我用的是1.5,暂且不确定就这个玩意儿而言1.6行不行),安装完之后,插上 kinect usb,自动在线安装kinect 驱动,xp系统印象里是不行的。
(2)解压EggWrapper,将文件夹”kinect”复制到Assets
下面
(3)贴上主文件代码解释
https://www.sodocs.net/doc/4815310394.html,ing System;
https://www.sodocs.net/doc/4815310394.html,ing UnityEngine;
https://www.sodocs.net/doc/4815310394.html,ing System.Runtime.InteropServices;
https://www.sodocs.net/doc/4815310394.html,ing System.Collections;
https://www.sodocs.net/doc/4815310394.html,ing System.Text;
https://www.sodocs.net/doc/4815310394.html,ing System.Reflection;
7.public class KinectAction: MonoBehaviour
8.{
9. //需要哪些骨骼点,就定义哪些骨骼点
10. Vector3 hipCenter=new Vector3(0,0,0);
11. Vector3 handRight=new Vector3(0,0,0);
12. Vector3 kneeRight=new Vector3(0,0,0);
13. Vector3 kneeLeft=new Vector3(0,0,0);
14. Vector3 spine=new Vector3(0,0,0);
15. Vector3 shoulderRight=new Vector3(0,0,0);
16. Vector3 shoulderLeft=new Vector3(0,0,0);
17. Vector3 head=new Vector3(0,0,0);
18. Vector3 handLeft=new
Vector3(0,0,0);
19. //是否开启视频流
20. private bool useRGB =true;
21.
22. //定义二维纹理,用以绘制
23. private Texture2D texture;
24.
25. public bool flg;
26. float RSpeed=3;
27. float LSpeed=-3;
28. float FSpeed=10;
29. float BSpeed=-10;
30.
31.
32. float vs;
33. float hs;
34.
35. private void Start()
36. {
37. //启动kinect
38. int
status=EggWrapper.NuiContextInit();
39.
40. if(status!=6){
41. print("kinect init
error.............................");
42. return;
43. }
44. //因为姿势在上半身,稍微提高一下
kinect摄像头的角度
45. EggWrapper.SetCameraAngle(12);
46.
47. if (useRGB) {
48. texture=new
Texture2D(EggWrapper.VideoWidth,EggWrapper.VideoHe
ight);
50.
51.
52. }
53.
54. private void OnApplicationQuit(){
55. EggWrapper.NuiContextUnInit();
56. }
57.
58.
59.
60.
61. private void Update() {
62. //捕捉动作
63. updateSkeleton();
64. //如果开启RGB数据显示,那么会在左
上角有块视频流显示区域
65. if (useRGB) {
66. getVideo();
67. }
68.
69. }
70.
71. //实时接收Color[] 数据块,并且设置texture
72. private void getVideo(){
73. Color32[] cols;
74. cols=EggWrapper.UpdateRGB();
75. texture.SetPixels32(cols);
76. texture.Apply();
77. }
78.
79. //绘制视频流,注意EggWrapper.VideoWidth /
3, EggWrapper.VideoHeight / 3是将640*480的大小缩小3倍
80. private void OnGUI() {
81. if (useRGB ) {
82. GUI.DrawTexture(new Rect(0, 0,
EggWrapper.VideoWidth / 3, EggWrapper.VideoHeight / 3), texture, ScaleMode.ScaleToFit, false);
83. }
84. }
85.
86.
87. private void updateSkeleton()
89. EggWrapper.updateSkeletons();
90. if(EggWrapper.hasSkeleton()){
91. setPositions();
92. //此处缩小下捕捉区域的范
围,大家可以自定义
93. if( hipCenter.x>-0.5 &&
hipCenter.x<0.5){
94. doActions();
95. }
96. }
97.
98. }
99.
100. //获得骨骼点的三维坐标
101. private void setPositions(){
102. hipCenter=EggWrapper.GetSkele tonPosition(EggWrapper.Joints.HIP_CENTER);
103. handRight=EggWrapper.GetSkele tonPosition(EggWrapper.Joints.HAND_RIGHT);
104. handLeft=EggWrapper.GetSkelet onPosition(EggWrapper.Joints.HAND_LEFT);
105. spine=EggWrapper.GetSkeletonP osition(EggWrapper.Joints.SPINE);
106. head=EggWrapper.GetSkeletonPo sition(EggWrapper.Joints.HEAD);
107. }
108.
109. private void doActions(){
110. hs=0;
111. vs=0;
112. //举起双手到胸前
113. if(handLeft.y>spine.y-0.1&&ha ndRight.y>spine.y-0.1){
114. flg=true;
115. }else{
116. flg=false;
117. }
118.
119. //以下定义四个比较简单的肢体动作,分别是左倾右倾前倾后仰
120. if(flg){
121. if(head.x 122. //print("left ............................"); 123. hs=Time.delta Time*LSpeed; 124. } 125. if(head.x>spine.x+0.2 ){ 126. //print("righ t............................"); 127. hs=Time.delta Time*RSpeed; 128. } 129. if(head.z 130. //print("fron t............................"); 131. vs=Time.delta Time*FSpeed; 132. } 133. 134. if(head.z>hipCenter.z +0.1){ 135. //print("back ............................"); 136. vs=Time.delta Time*BSpeed; 137. } 138. } 139. 140. //用下面的方法获得Car.js文件的throttle,steer变量,分别控制纵向和横向 141. Component AComponent = gameObject.GetComponent("Car"); 142. FieldInfo fieldInfo = AComponent.GetType().GetField("throttle"); 143. FieldInfo fieldInfo1 = AComponent.GetType().GetField("steer"); 144. fieldInfo.SetValue(AComponent ,vs); 145. fieldInfo1.SetValue(AComponen t,hs); 146. } 复制代码 (4)将Car.js的以下两个变量改为public public var throttle : float = 0; public var steer : float = 0; 并且,锁定到以下方法,注释掉键盘控制 (5)将KinectAction.cs拖到Car上 态下也没法找到这张多余的图片) 40617481bde01b7c2fa96e6958081071.png(100.83 KB, 下载次数: 1) Kinect.zip 14.1 KB, 下载次数: 56, 下载积分: 银子 -1 两 KinectU3D