zoukankan      html  css  js  c++  java
  • Unity3D 游戏引擎之FBX模型的载入与人物行走动画的播放【转】

    http://blog.csdn.net/xys289187120/article/details/6961080

           3D 世界中自定义模型的使用恐怕是重中之重,因为系统自身提供的模型肯定是无法满足GD对游戏的策划,所以为了让游戏更加绚丽,我们须要调用美术制作的精品模型与动画,本章MOMO将带领盆友们学习Unity3D中模型的载入与动画的播放,哇咔咔~~

     

     

           由于MOMO手头上没有现成的模型,所以我将在Unity3D 官网中下载官方提供的游戏DEMO 中的模型来使用。另外官方提供了很多Unity3D 游戏DEMO,与详细的文档。可以帮助我们学习Unity.有兴趣的盆友可以去看看哈。

    下载页面:http://unity3d.com/support/resources/  

     

     

    本章博文的目的是利用上一章介绍的游戏摇杆来控制人物模型的移动,与行走动画的播放。

     

     


     
     
     
     

    如上图所示Create中的文件夹male中存放着模型动画与贴图等,这个应该是美术提供给我们的。然后将整个male用鼠标拖动到左侧3D世界中,通过移动,旋转,缩放将人物模型放置在一个理想的位置。右侧红框内设置模型动画的属性。

     

    Animation  

            idle1  该模型默认动画名称为idle1

    Animations 

            size   该模型动画的数量

            Element 该模型的动画名称

    Play Automatically 是否自动播放

    Animation Physics 是否设置该模型物理碰撞

    Animation Only if Visable 是否设置该模型仅自己显示

     

     

    给该模型绑定一个脚本Controller.cs 用来接收摇杆返回的信息更新模型动画。

     

    Controller.cs

    [csharp] view plaincopy
    1. using UnityEngine;  
    2. using System.Collections;  
    3.   
    4.   
    5.   
    6. public class Controller : MonoBehaviour {  
    7.       
    8.     //人物的行走方向状态  
    9.     public const int HERO_UP= 0;  
    10.     public const int HERO_RIGHT= 1;  
    11.     public const int HERO_DOWN= 2;  
    12.     public const int HERO_LEFT= 3;  
    13.       
    14.     //人物当前行走方向状态  
    15.     public int state = 0;  
    16.       
    17.     //备份上一次人物当前行走方向状态  
    18.     //这里暂时没有用到  
    19.     public int backState = 0;  
    20.       
    21.     //游戏摇杆对象  
    22.     public MPJoystick moveJoystick;    
    23.       
    24.     //这个方法只调用一次,在Start方法之前调用  
    25.     public void Awake() {  
    26.           
    27.     }  
    28.       
    29.     //这个方法只调用一次,在Awake方法之后调用  
    30.     void Start () {  
    31.         state = HERO_DOWN;  
    32.     }  
    33.       
    34.       
    35.     void Update () {  
    36.       
    37.     //获取摇杆控制的方向数据 上一章有详细介绍    
    38.     float touchKey_x =  moveJoystick.position.x;    
    39.     float touchKey_y =  moveJoystick.position.y;    
    40.           
    41.         
    42.        
    43.     if(touchKey_x == -1){    
    44.        setHeroState(HERO_LEFT);  
    45.             
    46.     }else if(touchKey_x == 1){    
    47.        setHeroState(HERO_RIGHT);  
    48.             
    49.     }    
    50.        
    51.     if(touchKey_y == -1){    
    52.         setHeroState(HERO_DOWN);  
    53.    
    54.     }else if(touchKey_y == 1){    
    55.         setHeroState(HERO_UP);           
    56.     }    
    57.       
    58.     if(touchKey_x == 0 && touchKey_y ==0){  
    59.         //松开摇杆后播放默认动画,  
    60.         //不穿参数为播放默认动画。  
    61.         animation.Play();  
    62.     }  
    63.       
    64.           
    65.     }  
    66.       
    67.     public void setHeroState(int newState)  
    68.     {  
    69.           
    70.         //根据当前人物方向 与上一次备份方向计算出模型旋转的角度  
    71.         int rotateValue = (newState - state) * 90;  
    72.         Vector3 transformValue = new Vector3();  
    73.           
    74.         //播放行走动画  
    75.         animation.Play("walk");  
    76.           
    77.         //模型移动的位移的数值  
    78.         switch(newState){  
    79.             case HERO_UP:  
    80.                 transformValue = Vector3.forward * Time.deltaTime;  
    81.             break;    
    82.             case HERO_DOWN:  
    83.                 transformValue = -Vector3.forward * Time.deltaTime;  
    84.             break;    
    85.             case HERO_LEFT:  
    86.                 transformValue = Vector3.left * Time.deltaTime;  
    87.                   
    88.             break;    
    89.             case HERO_RIGHT:  
    90.                 transformValue = -Vector3.left * Time.deltaTime;  
    91.             break;                
    92.         }  
    93.           
    94.           
    95.         //模型旋转  
    96.         transform.Rotate(Vector3.up, rotateValue);  
    97.           
    98.         //模型移动  
    99.         transform.Translate(transformValue, Space.World);  
    100.           
    101.         backState = state;  
    102.         state = newState;  
    103.           
    104.     }  
    105.       
    106. }  


     

     

    上一章介绍了javaScript脚本使用游戏摇杆的方法,本章MOMO告诉大家使用C#脚本来使用游戏摇杆,上面我用 Controller.cs  C#脚本来接收系统提供的Joystick.js是肯定无法使用的,须要修改成.cs文件,我在国外的一个网站上看到了一个老外帮我们已经修改了,那么我将他修改后的代码贴出来方便大家学习,有兴趣的朋友可以研究研究。哇咔咔~

     

    MPJoystick.cs

     

    [csharp] view plaincopy
    1. using UnityEngine;   
    2.   
    3. /** 
    4.  
    5.  * File: MPJoystick.cs 
    6.  
    7.  * Author: Chris Danielson of (monkeyprism.com) 
    8.  
    9.  *  
    10.  
    11. // USED TO BE: Joystick.js taken from Penelope iPhone Tutorial 
    12.  
    13. // 
    14.  
    15. // Joystick creates a movable joystick (via GUITexture) that  
    16.  
    17. // handles touch input, taps, and phases. Dead zones can control 
    18.  
    19. // where the joystick input gets picked up and can be normalized. 
    20.  
    21. // 
    22.  
    23. // Optionally, you can enable the touchPad property from the editor 
    24.  
    25. // to treat this Joystick as a TouchPad. A TouchPad allows the finger 
    26.  
    27. // to touch down at any point and it tracks the movement relatively  
    28.  
    29. // without moving the graphic 
    30.  
    31. */  
    32. [RequireComponent(typeof(GUITexture))]  
    33.   
    34. public class MPJoystick : MonoBehaviour  
    35.   
    36. {  
    37.   
    38. class Boundary {  
    39.   
    40. public Vector2 min = Vector2.zero;  
    41.   
    42. public Vector2 max = Vector2.zero;  
    43.   
    44. }  
    45. private static MPJoystick[] joysticks;   // A static collection of all joysticks  
    46.   
    47. private static bool enumeratedJoysticks = false;  
    48.   
    49. private static float tapTimeDelta = 0.3f;    // Time allowed between taps  
    50. public bool touchPad;  
    51.   
    52. public Vector2 position = Vector2.zero;  
    53.   
    54. public Rect touchZone;  
    55.   
    56. public Vector2 deadZone = Vector2.zero;  // Control when position is output  
    57.   
    58. public bool normalize = false// Normalize output after the dead-zone?  
    59.   
    60. public int tapCount;       
    61.   
    62. private int lastFingerId = -1;   // Finger last used for this joystick  
    63.   
    64. private float tapTimeWindow;     // How much time there is left for a tap to occur  
    65.   
    66. private Vector2 fingerDownPos;  
    67.   
    68. //private float fingerDownTime;  
    69.   
    70. //private float firstDeltaTime = 0.5f;  
    71. private GUITexture gui;  
    72.   
    73. private Rect defaultRect;    // Default position / extents of the joystick graphic  
    74.   
    75. private Boundary guiBoundary = new Boundary();   // Boundary for joystick graphic  
    76.   
    77. private Vector2 guiTouchOffset;  // Offset to apply to touch input  
    78.   
    79. private Vector2 guiCenter;   // Center of joystick  
    80. void Start() {  
    81.   
    82. gui = (GUITexture)GetComponent(typeof(GUITexture));  
    83. defaultRect = gui.pixelInset;  
    84.   
    85. defaultRect.x += transform.position.x * Screen.width;// + gui.pixelInset.x; // -  Screen.width * 0.5;  
    86.   
    87.         defaultRect.y += transform.position.y * Screen.height;// - Screen.height * 0.5;  
    88. transform.position = Vector3.zero;  
    89. if (touchPad) {  
    90.   
    91. // If a texture has been assigned, then use the rect ferom the gui as our touchZone  
    92.   
    93. if ( gui.texture )  
    94.   
    95. touchZone = defaultRect;  
    96.   
    97. else {  
    98.   
    99. guiTouchOffset.x = defaultRect.width * 0.5f;  
    100.   
    101. guiTouchOffset.y = defaultRect.height * 0.5f;  
    102. // Cache the center of the GUI, since it doesn't change  
    103.   
    104. guiCenter.x = defaultRect.x + guiTouchOffset.x;  
    105.   
    106. guiCenter.y = defaultRect.y + guiTouchOffset.y;  
    107. // Let's build the GUI boundary, so we can clamp joystick movement  
    108.   
    109. guiBoundary.min.x = defaultRect.x - guiTouchOffset.x;  
    110.   
    111. guiBoundary.max.x = defaultRect.x + guiTouchOffset.x;  
    112.   
    113. guiBoundary.min.y = defaultRect.y - guiTouchOffset.y;  
    114.   
    115. guiBoundary.max.y = defaultRect.y + guiTouchOffset.y;  
    116.   
    117. }  
    118.   
    119. }  
    120. public Vector2 getGUICenter() {  
    121.   
    122. return guiCenter;  
    123.   
    124. }  
    125. void Disable() {  
    126.   
    127. gameObject.active = false;  
    128.   
    129. //enumeratedJoysticks = false;  
    130.   
    131. }  
    132. private void ResetJoystick() {  
    133.   
    134. gui.pixelInset = defaultRect;  
    135.   
    136. lastFingerId = -1;  
    137.   
    138. position = Vector2.zero;  
    139.   
    140. fingerDownPos = Vector2.zero;  
    141.   
    142. }  
    143. private bool IsFingerDown() {  
    144.   
    145. return (lastFingerId != -1);  
    146.   
    147. }  
    148. public void LatchedFinger(int fingerId) {  
    149.   
    150. // If another joystick has latched this finger, then we must release it  
    151.   
    152. if ( lastFingerId == fingerId )  
    153.   
    154. ResetJoystick();  
    155.   
    156. }  
    157. void Update() {  
    158.   
    159. if (!enumeratedJoysticks) {  
    160.   
    161. // Collect all joysticks in the game, so we can relay finger latching messages  
    162.   
    163. joysticks = (MPJoystick[])FindObjectsOfType(typeof(MPJoystick));  
    164.   
    165. enumeratedJoysticks = true;  
    166.   
    167. }  
    168. int count = Input.touchCount;  
    169. if ( tapTimeWindow > 0 )  
    170.   
    171. tapTimeWindow -= Time.deltaTime;  
    172.   
    173. else  
    174.   
    175. tapCount = 0;  
    176. if ( count == 0 )  
    177.   
    178. ResetJoystick();  
    179.   
    180. else  
    181.   
    182. {  
    183.   
    184. for(int i = 0; i < count; i++) {  
    185.   
    186. Touch touch = Input.GetTouch(i);  
    187.   
    188. Vector2 guiTouchPos = touch.position - guiTouchOffset;  
    189. bool shouldLatchFinger = false;  
    190.   
    191. if (touchPad) {  
    192.   
    193. if (touchZone.Contains(touch.position))  
    194.   
    195. shouldLatchFinger = true;  
    196.   
    197. }  
    198.   
    199. else if (gui.HitTest(touch.position)) {  
    200.   
    201. shouldLatchFinger = true;  
    202.   
    203. }  
    204. // Latch the finger if this is a new touch  
    205.   
    206. if (shouldLatchFinger && (lastFingerId == -1 || lastFingerId != touch.fingerId )) {  
    207. if (touchPad) {  
    208.   
    209. //gui.color.a = 0.15;  
    210.   
    211. lastFingerId = touch.fingerId;  
    212.   
    213. //fingerDownPos = touch.position;  
    214.   
    215. //fingerDownTime = Time.time;  
    216.   
    217. }  
    218. lastFingerId = touch.fingerId;  
    219.   
    220.    
    221.   
    222. // Accumulate taps if it is within the time window  
    223.   
    224. if ( tapTimeWindow > 0 )  
    225.   
    226. tapCount++;  
    227.   
    228. else {  
    229.   
    230. tapCount = 1;  
    231.   
    232. tapTimeWindow = tapTimeDelta;  
    233.   
    234. }  
    235. // Tell other joysticks we've latched this finger  
    236.   
    237. //for (  j : Joystick in joysticks )  
    238.   
    239. foreach (MPJoystick j in joysticks) {  
    240.   
    241. if (j != this)   
    242.   
    243. j.LatchedFinger( touch.fingerId );  
    244.   
    245. }  
    246.   
    247. }     
    248. if ( lastFingerId == touch.fingerId ) {  
    249.   
    250. // Override the tap count with what the iPhone SDK reports if it is greater  
    251.   
    252. // This is a workaround, since the iPhone SDK does not currently track taps  
    253.   
    254. // for multiple touches  
    255.   
    256. if ( touch.tapCount > tapCount )  
    257.   
    258. tapCount = touch.tapCount;  
    259. if ( touchPad ) {  
    260.   
    261. // For a touchpad, let's just set the position directly based on distance from initial touchdown  
    262.   
    263. position.x = Mathf.Clamp( ( touch.position.x - fingerDownPos.x ) / ( touchZone.width / 2 ), -1, 1 );  
    264.   
    265. position.y = Mathf.Clamp( ( touch.position.y - fingerDownPos.y ) / ( touchZone.height / 2 ), -1, 1 );  
    266.   
    267. else {  
    268.   
    269. // Change the location of the joystick graphic to match where the touch is  
    270.   
    271. Rect r = gui.pixelInset;  
    272.   
    273. r.x =  Mathf.Clamp( guiTouchPos.x, guiBoundary.min.x, guiBoundary.max.x );  
    274.   
    275. r.y =  Mathf.Clamp( guiTouchPos.y, guiBoundary.min.y, guiBoundary.max.y );  
    276.   
    277. gui.pixelInset = r;  
    278.   
    279. }  
    280. if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)  
    281.   
    282. ResetJoystick();  
    283.   
    284. }  
    285.   
    286. }  
    287.   
    288. }  
    289. if (!touchPad) {  
    290.   
    291. // Get a value between -1 and 1 based on the joystick graphic location  
    292.   
    293. position.x = ( gui.pixelInset.x + guiTouchOffset.x - guiCenter.x ) / guiTouchOffset.x;  
    294.   
    295. position.y = ( gui.pixelInset.y + guiTouchOffset.y - guiCenter.y ) / guiTouchOffset.y;  
    296.   
    297. }  
    298. // Adjust for dead zone  
    299.   
    300. var absoluteX = Mathf.Abs( position.x );  
    301.   
    302. var absoluteY = Mathf.Abs( position.y );  
    303.   
    304.    
    305.   
    306. if (absoluteX < deadZone.x) {  
    307.   
    308. // Report the joystick as being at the center if it is within the dead zone  
    309.   
    310. position.x = 0;  
    311.   
    312. }  
    313.   
    314. else if (normalize) {  
    315.   
    316. // Rescale the output after taking the dead zone into account  
    317.   
    318. position.x = Mathf.Sign( position.x ) * ( absoluteX - deadZone.x ) / ( 1 - deadZone.x );  
    319.   
    320. }  
    321. if (absoluteY < deadZone.y) {  
    322.   
    323. // Report the joystick as being at the center if it is within the dead zone  
    324.   
    325. position.y = 0;  
    326.   
    327. }  
    328.   
    329. else if (normalize) {  
    330.   
    331. // Rescale the output after taking the dead zone into account  
    332.   
    333. position.y = Mathf.Sign( position.y ) * ( absoluteY - deadZone.y ) / ( 1 - deadZone.y );  
    334.   
    335. }  
    336. }  
    337. }  

     


    导出 build and run  看看在iPhone 上的效果,通过触摸游戏摇杆可以控制人物的上,下,左,右 ,左上,右上,左下,右下 8个方向的移动啦,不错吧,哇咔咔~~


     

     


     

     

     

     


     

     

    最后欢迎各位盆友可以和MOMO一起讨论Unity3D游戏开发,本来昨天就想发表这篇文章,结果晚上去打高尔夫球连挥N杆,打的回家后浑身酸痛,回家就睡觉啦~希望大家在学习的同时别忘了多运动。哇咔咔~~~ 附上Unity3D工程的下载地址,Xcode项目我就不上传了,须要的自己导出。

     

  • 相关阅读:
    信件分析实战(五)——数据可视化
    信件分析实战(四)——数据分析以及部分可视化
    剑指offer15题
    剑指offer14题
    剑指offer11题
    剑指offer第9题
    剑指offer第8题--动态规划最简单讲解
    剑指offer第7题
    剑指offer第6题
    剑指offer第5题
  • 原文地址:https://www.cnblogs.com/songtzu/p/3009551.html
Copyright © 2011-2022 走看看