3D 世界中自定义模型的使用恐怕是重中之重,因为系统自身提供的模型肯定是无法满足GD对游戏的策划,所以为了让游戏更加绚丽,我们须要调用美术制作的精品模型与动画,本章将带领大家学习Unity3D中模型的载入与动画的播放。
由于作者手头上没有现成的模型,所以我将在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
[代码]c#/cpp/oc代码:
002 |
using System.Collections; |
006 |
public class Controller : MonoBehaviour { |
009 |
public const int HERO_UP= 0; |
010 |
public const int HERO_RIGHT= 1; |
011 |
public const int HERO_DOWN= 2; |
012 |
public const int HERO_LEFT= 3; |
015 |
public int state = 0; |
019 |
public int backState = 0; |
022 |
public MPJoystick moveJoystick; |
024 |
//这个方法只调用一次,在Start方法之前调用 |
025 |
public void Awake() { |
029 |
//这个方法只调用一次,在Awake方法之后调用 |
037 |
//获取摇杆控制的方向数据 上一章有详细介绍 |
038 |
float touchKey_x = moveJoystick.position.x; |
039 |
float touchKey_y = moveJoystick.position.y; |
043 |
if(touchKey_x == -1){ |
044 |
setHeroState(HERO_LEFT); |
046 |
}else if(touchKey_x == 1){ |
047 |
setHeroState(HERO_RIGHT); |
051 |
if(touchKey_y == -1){ |
052 |
setHeroState(HERO_DOWN); |
054 |
}else if(touchKey_y == 1){ |
055 |
setHeroState(HERO_UP); |
058 |
if(touchKey_x == 0 && touchKey_y ==0){ |
067 |
public void setHeroState(int newState) |
070 |
//根据当前人物方向 与上一次备份方向计算出模型旋转的角度 |
071 |
int rotateValue = (newState - state) * 90; |
072 |
Vector3 transformValue = new Vector3(); |
075 |
animation.Play("walk"); |
080 |
transformValue = Vector3.forward * Time.deltaTime; |
083 |
transformValue = -Vector3.forward * Time.deltaTime; |
086 |
transformValue = Vector3.left * Time.deltaTime; |
090 |
transformValue = -Vector3.left * Time.deltaTime; |
096 |
transform.Rotate(Vector3.up, rotateValue); |
099 |
transform.Translate(transformValue, Space.World); |
上一章介绍了javaScript脚本使用游戏摇杆的方法,本章MOMO告诉大家使用C#脚本来使用游戏摇杆,上面我用 Controller.cs C#脚本来接收系统提供的Joystick.js是肯定无法使用的,须要修改成.cs文件,我在国外的一个网站上看到了一个老外帮我们已经修改了,那么我将他修改后的代码贴出来方便大家学习,有兴趣的朋友可以研究研究。
MPJoystick.cs
[代码]c#/cpp/oc代码:
005 |
* File: MPJoystick.cs |
007 |
* Author: Chris Danielson of (monkeyprism.com) |
011 |
// USED TO BE: Joystick.js taken from Penelope iPhone Tutorial |
015 |
// Joystick creates a movable joystick (via GUITexture) that |
017 |
// handles touch input, taps, and phases. Dead zones can control |
019 |
// where the joystick input gets picked up and can be normalized. |
023 |
// Optionally, you can enable the touchPad property from the editor |
025 |
// to treat this Joystick as a TouchPad. A TouchPad allows the finger |
027 |
// to touch down at any point and it tracks the movement relatively |
029 |
// without moving the graphic |
032 |
[RequireComponent(typeof(GUITexture))] |
034 |
public class MPJoystick : MonoBehaviour |
040 |
public Vector2 min = Vector2.zero; |
042 |
public Vector2 max = Vector2.zero; |
045 |
private static MPJoystick[] joysticks; // A static collection of all joysticks |
047 |
private static bool enumeratedJoysticks = false; |
049 |
private static float tapTimeDelta = 0.3f; // Time allowed between taps |
050 |
public bool touchPad; |
052 |
public Vector2 position = Vector2.zero; |
054 |
public Rect touchZone; |
056 |
public Vector2 deadZone = Vector2.zero; // Control when position is output |
058 |
public bool normalize = false; // Normalize output after the dead-zone? |
062 |
private int lastFingerId = -1; // Finger last used for this joystick |
064 |
private float tapTimeWindow; // How much time there is left for a tap to occur |
066 |
private Vector2 fingerDownPos; |
068 |
//private float fingerDownTime; |
070 |
//private float firstDeltaTime = 0.5f; |
071 |
private GUITexture gui; |
073 |
private Rect defaultRect; // Default position / extents of the joystick graphic |
075 |
private Boundary guiBoundary = new Boundary(); // Boundary for joystick graphic |
077 |
private Vector2 guiTouchOffset; // Offset to apply to touch input |
079 |
private Vector2 guiCenter; // Center of joystick |
082 |
gui = (GUITexture)GetComponent(typeof(GUITexture)); |
083 |
defaultRect = gui.pixelInset; |
085 |
defaultRect.x += transform.position.x * Screen.width;// + gui.pixelInset.x; // - Screen.width * 0.5; |
087 |
defaultRect.y += transform.position.y * Screen.height;// - Screen.height * 0.5; |
088 |
transform.position = Vector3.zero; |
091 |
// If a texture has been assigned, then use the rect ferom the gui as our touchZone |
095 |
touchZone = defaultRect; |
099 |
guiTouchOffset.x = defaultRect.width * 0.5f; |
101 |
guiTouchOffset.y = defaultRect.height * 0.5f; |
102 |
// Cache the center of the GUI, since it doesn't change |
104 |
guiCenter.x = defaultRect.x + guiTouchOffset.x; |
106 |
guiCenter.y = defaultRect.y + guiTouchOffset.y; |
107 |
// Let's build the GUI boundary, so we can clamp joystick movement |
109 |
guiBoundary.min.x = defaultRect.x - guiTouchOffset.x; |
111 |
guiBoundary.max.x = defaultRect.x + guiTouchOffset.x; |
113 |
guiBoundary.min.y = defaultRect.y - guiTouchOffset.y; |
115 |
guiBoundary.max.y = defaultRect.y + guiTouchOffset.y; |
120 |
public Vector2 getGUICenter() { |
127 |
gameObject.active = false; |
129 |
//enumeratedJoysticks = false; |
132 |
private void ResetJoystick() { |
134 |
gui.pixelInset = defaultRect; |
138 |
position = Vector2.zero; |
140 |
fingerDownPos = Vector2.zero; |
143 |
private bool IsFingerDown() { |
145 |
return (lastFingerId != -1); |
148 |
public void LatchedFinger(int fingerId) { |
150 |
// If another joystick has latched this finger, then we must release it |
152 |
if ( lastFingerId == fingerId ) |
159 |
if (!enumeratedJoysticks) { |
161 |
// Collect all joysticks in the game, so we can relay finger latching messages |
163 |
joysticks = (MPJoystick[])FindObjectsOfType(typeof(MPJoystick)); |
165 |
enumeratedJoysticks = true; |
168 |
int count = Input.touchCount; |
169 |
if ( tapTimeWindow > 0 ) |
171 |
tapTimeWindow -= Time.deltaTime; |
184 |
for(int i = 0; i < count; i++) { |
186 |
Touch touch = Input.GetTouch(i); |
188 |
Vector2 guiTouchPos = touch.position - guiTouchOffset; |
189 |
bool shouldLatchFinger = false; |
193 |
if (touchZone.Contains(touch.position)) |
195 |
shouldLatchFinger = true; |
199 |
else if (gui.HitTest(touch.position)) { |
201 |
shouldLatchFinger = true; |
204 |
// Latch the finger if this is a new touch |
206 |
if (shouldLatchFinger && (lastFingerId == -1 || lastFingerId != touch.fingerId )) { |
209 |
//gui.color.a = 0.15; |
211 |
lastFingerId = touch.fingerId; |
213 |
//fingerDownPos = touch.position; |
215 |
//fingerDownTime = Time.time; |
218 |
lastFingerId = touch.fingerId; |
222 |
// Accumulate taps if it is within the time window |
224 |
if ( tapTimeWindow > 0 ) |
232 |
tapTimeWindow = tapTimeDelta; |
235 |
// Tell other joysticks we've latched this finger |
237 |
//for ( j : Joystick in joysticks ) |
239 |
foreach (MPJoystick j in joysticks) { |
243 |
j.LatchedFinger( touch.fingerId ); |
248 |
if ( lastFingerId == touch.fingerId ) { |
250 |
// Override the tap count with what the iPhone SDK reports if it is greater |
252 |
// This is a workaround, since the iPhone SDK does not currently track taps |
254 |
// for multiple touches |
256 |
if ( touch.tapCount > tapCount ) |
258 |
tapCount = touch.tapCount; |
261 |
// For a touchpad, let's just set the position directly based on distance from initial touchdown |
263 |
position.x = Mathf.Clamp( ( touch.position.x - fingerDownPos.x ) / ( touchZone.width / 2 ), -1, 1 ); |
265 |
position.y = Mathf.Clamp( ( touch.position.y - fingerDownPos.y ) / ( touchZone.height / 2 ), -1, 1 ); |
269 |
// Change the location of the joystick graphic to match where the touch is |
271 |
Rect r = gui.pixelInset; |
273 |
r.x = Mathf.Clamp( guiTouchPos.x, guiBoundary.min.x, guiBoundary.max.x ); |
275 |
r.y = Mathf.Clamp( guiTouchPos.y, guiBoundary.min.y, guiBoundary.max.y ); |
280 |
if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled) |
291 |
// Get a value between -1 and 1 based on the joystick graphic location |
293 |
position.x = ( gui.pixelInset.x + guiTouchOffset.x - guiCenter.x ) / guiTouchOffset.x; |
295 |
position.y = ( gui.pixelInset.y + guiTouchOffset.y - guiCenter.y ) / guiTouchOffset.y; |
298 |
// Adjust for dead zone |
300 |
var absoluteX = Mathf.Abs( position.x ); |
302 |
var absoluteY = Mathf.Abs( position.y ); |
306 |
if (absoluteX < deadZone.x) { |
308 |
// Report the joystick as being at the center if it is within the dead zone |
314 |
else if (normalize) { |
316 |
// Rescale the output after taking the dead zone into account |
318 |
position.x = Mathf.Sign( position.x ) * ( absoluteX - deadZone.x ) / ( 1 - deadZone.x ); |
321 |
if (absoluteY < deadZone.y) { |
323 |
// Report the joystick as being at the center if it is within the dead zone |
329 |
else if (normalize) { |
331 |
// Rescale the output after taking the dead zone into account |
333 |
position.y = Mathf.Sign( position.y ) * ( absoluteY - deadZone.y ) / ( 1 - deadZone.y ); |
导出 build and run 看看在iPhone 上的效果,通过触摸游戏摇杆可以控制人物的上,下,左,右 ,左上,右上,左下,右下 8个方向的移动啦,不错吧,哇咔咔~~