Unity3D 遊戲引擎之IOS自訂遊戲搖杆與飛機平滑的移動
雨松MOMO原創文章如轉載,請註明:轉載至我的獨立網域名稱部落格雨松MOMO程式研究院,原文地址:http://www.xuanyusong.com/archives/526
移動開發遊戲中使用到的觸摸遊戲搖杆在iPhone上是非常普遍的,畢竟是全觸控螢幕手機,今天MOMO 通過一個小例子和大家討論Unity3D 中如何自訂一個漂亮的全觸摸遊戲搖杆。
值得高興的是,Unity3D 遊戲引擎的標準資源中已經協助我們封裝了一個遊戲搖杆指令碼,所以實現部分的代碼可以完全藉助它的,具體調用需要我們自己來。
Joystick.js是官方提供的指令碼,具體代碼如下,有興趣的朋友可以仔細研究研究,MOMO就不多說啦。哇哢哢~
//////////////////////////////////////////////////////////////// Joystick.js// Penelope iPhone Tutorial//// Joystick creates a movable joystick (via GUITexture) that // handles touch input, taps, and phases. Dead zones can control// where the joystick input gets picked up and can be normalized.//// Optionally, you can enable the touchPad property from the editor// to treat this Joystick as a TouchPad. A TouchPad allows the finger// to touch down at any point and it tracks the movement relatively // without moving the graphic//////////////////////////////////////////////////////////////@script RequireComponent( GUITexture )// A simple class for bounding how far the GUITexture will moveclass Boundary {var min : Vector2 = Vector2.zero;var max : Vector2 = Vector2.zero;}static private var joysticks : Joystick[];// A static collection of all joysticksstatic private var enumeratedJoysticks : boolean = false;static private var tapTimeDelta : float = 0.3;// Time allowed between tapsvar touchPad : boolean; // Is this a TouchPad?var touchZone : Rect;var deadZone : Vector2 = Vector2.zero;// Control when position is outputvar normalize : boolean = false; // Normalize output after the dead-zone?var position : Vector2; // [-1, 1] in x,yvar tapCount : int;// Current tap countprivate var lastFingerId = -1;// Finger last used for this joystickprivate var tapTimeWindow : float;// How much time there is left for a tap to occurprivate var fingerDownPos : Vector2;private var fingerDownTime : float;private var firstDeltaTime : float = 0.5;private var gui : GUITexture;// Joystick graphicprivate var defaultRect : Rect;// Default position / extents of the joystick graphicprivate var guiBoundary : Boundary = Boundary();// Boundary for joystick graphicprivate var guiTouchOffset : Vector2;// Offset to apply to touch inputprivate var guiCenter : Vector2;// Center of joystickfunction Start(){// Cache this component at startup instead of looking up every framegui = GetComponent( GUITexture );// Store the default rect for the gui, so we can snap back to itdefaultRect = gui.pixelInset; defaultRect.x += transform.position.x * Screen.width;// + gui.pixelInset.x; // - Screen.width * 0.5; defaultRect.y += transform.position.y * Screen.height;// - Screen.height * 0.5; transform.position.x = 0.0; transform.position.y = 0.0; if ( touchPad ){// If a texture has been assigned, then use the rect ferom the gui as our touchZoneif ( gui.texture )touchZone = defaultRect;}else{// This is an offset for touch input to match with the top left// corner of the GUIguiTouchOffset.x = defaultRect.width * 0.5;guiTouchOffset.y = defaultRect.height * 0.5;// Cache the center of the GUI, since it doesn't changeguiCenter.x = defaultRect.x + guiTouchOffset.x;guiCenter.y = defaultRect.y + guiTouchOffset.y;// Let's build the GUI boundary, so we can clamp joystick movementguiBoundary.min.x = defaultRect.x - guiTouchOffset.x;guiBoundary.max.x = defaultRect.x + guiTouchOffset.x;guiBoundary.min.y = defaultRect.y - guiTouchOffset.y;guiBoundary.max.y = defaultRect.y + guiTouchOffset.y;}}function Disable(){gameObject.active = false;enumeratedJoysticks = false;}function ResetJoystick(){// Release the finger control and set the joystick back to the default positiongui.pixelInset = defaultRect;lastFingerId = -1;position = Vector2.zero;fingerDownPosition = Vector2.zero;if ( touchPad )gui.color.a = 0.025;}function IsFingerDown() : boolean{return (lastFingerId != -1);}function LatchedFinger( fingerId : int ){// If another joystick has latched this finger, then we must release itif ( lastFingerId == fingerId )ResetJoystick();}function Update(){if ( !enumeratedJoysticks ){// Collect all joysticks in the game, so we can relay finger latching messagesjoysticks = FindObjectsOfType( Joystick );enumeratedJoysticks = true;}var count = Input.touchCount;// Adjust the tap time window while it still availableif ( tapTimeWindow > 0 )tapTimeWindow -= Time.deltaTime;elsetapCount = 0;if ( count == 0 )ResetJoystick();else{for(var i : int = 0;i < count; i++){var touch : Touch = Input.GetTouch(i);var guiTouchPos : Vector2 = touch.position - guiTouchOffset;var shouldLatchFinger = false;if ( touchPad ){if ( touchZone.Contains( touch.position ) )shouldLatchFinger = true;}else if ( gui.HitTest( touch.position ) ){shouldLatchFinger = true;}// Latch the finger if this is a new touchif ( shouldLatchFinger && ( lastFingerId == -1 || lastFingerId != touch.fingerId ) ){if ( touchPad ){gui.color.a = 0.15;lastFingerId = touch.fingerId;fingerDownPos = touch.position;fingerDownTime = Time.time;}lastFingerId = touch.fingerId;// Accumulate taps if it is within the time windowif ( tapTimeWindow > 0 )tapCount++;else{tapCount = 1;tapTimeWindow = tapTimeDelta;}// Tell other joysticks we've latched this fingerfor ( var j : Joystick in joysticks ){if ( j != this )j.LatchedFinger( touch.fingerId );}}if ( lastFingerId == touch.fingerId ){// Override the tap count with what the iPhone SDK reports if it is greater// This is a workaround, since the iPhone SDK does not currently track taps// for multiple touchesif ( touch.tapCount > tapCount )tapCount = touch.tapCount;if ( touchPad ){// For a touchpad, let's just set the position directly based on distance from initial touchdownposition.x = Mathf.Clamp( ( touch.position.x - fingerDownPos.x ) / ( touchZone.width / 2 ), -1, 1 );position.y = Mathf.Clamp( ( touch.position.y - fingerDownPos.y ) / ( touchZone.height / 2 ), -1, 1 );}else{// Change the location of the joystick graphic to match where the touch isgui.pixelInset.x = Mathf.Clamp( guiTouchPos.x, guiBoundary.min.x, guiBoundary.max.x );gui.pixelInset.y = Mathf.Clamp( guiTouchPos.y, guiBoundary.min.y, guiBoundary.max.y );}if ( touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled )ResetJoystick();}}}if ( !touchPad ){// Get a value between -1 and 1 based on the joystick graphic locationposition.x = ( gui.pixelInset.x + guiTouchOffset.x - guiCenter.x ) / guiTouchOffset.x;position.y = ( gui.pixelInset.y + guiTouchOffset.y - guiCenter.y ) / guiTouchOffset.y;}// Adjust for dead zonevar absoluteX = Mathf.Abs( position.x );var absoluteY = Mathf.Abs( position.y );if ( absoluteX < deadZone.x ){// Report the joystick as being at the center if it is within the dead zoneposition.x = 0;}else if ( normalize ){// Rescale the output after taking the dead zone into accountposition.x = Mathf.Sign( position.x ) * ( absoluteX - deadZone.x ) / ( 1 - deadZone.x );}if ( absoluteY < deadZone.y ){// Report the joystick as being at the center if it is within the dead zoneposition.y = 0;}else if ( normalize ){// Rescale the output after taking the dead zone into accountposition.y = Mathf.Sign( position.y ) * ( absoluteY - deadZone.y ) / ( 1 - deadZone.y );}}
單擊Create 建立一個GUI Texture,命名為Joy ,它用來顯示遊戲搖杆,如所示將搖杆的圖片資源,與搖杆的指令碼連線賦值給Joy. Pixel Inset 中可以設定搖杆的顯示位置與顯示寬高。
到這一步 build and run 就可以在iPhone上看到這個遊戲搖杆,並且可以通過觸摸它,360度平滑過度。
在螢幕中繪製一個飛機,通過遊戲搖杆去控制飛機的移動。
建立一個指令碼,命名為Main.js 如所示 將 Main.js 、joy、plan 分別 綁定在Main Camera 上。
moveJoystick.position.x;
moveJoystick.position.y;
這兩個值是非常重要的兩個資訊,它們的取值範圍是 -1 到 +1 ,表示 使用者觸摸搖杆的位置, 上 下 左 右 的資訊。
//遊戲搖杆對象var moveJoystick : Joystick;//飛機的貼圖var plan : Texture;//飛機在螢幕中的座標var x = 0;var y = 0;//避免飛機飛出螢幕,分別是X、Y最大座標,最小座標是0、0var cross_x = 0;var cross_y = 0;//飛機移動的速度var planSpeed = 20;function Start() {//初始化賦值x = 100;y = 100;cross_x = Screen.width - plan.width;cross_y = Screen.height - plan.height;}function Update () {//得到遊戲搖杆的反饋資訊,得到的值是 -1 到 +1 之間 var touchKey_x = moveJoystick.position.x; var touchKey_y = moveJoystick.position.y; //搖杆向左 if(touchKey_x == -1){ x -= planSpeed; } //搖杆向右 else if(touchKey_x == 1){ x += planSpeed; } //搖杆向上 if(touchKey_y == -1){ y += planSpeed; } //搖杆向下 else if(touchKey_y == 1){ y -= planSpeed; } //防止飛機飛出螢幕,出界檢測 if(x < 0){ x = 0; }else if(x > cross_x){ x = cross_x; } if(y < 0){ y = 0; }else if(y > cross_y){ y = cross_y; }}function OnGUI () { //將飛機繪製在螢幕中 GUI.DrawTexture(Rect(x,y,128,128),plan); }
匯出 build and run 看看在iPhone 上的效果,通過觸摸遊戲搖杆可以控制飛機的移動啦,不錯吧,哇哢哢~~
最後歡迎各位盆友可以和MOMO一起討論Unity3D遊戲開發,最近感冒的盆友越來越多,大家要多多注意身體健康噢。哇哢哢~~~ 附上Unity3D工程的,Xcode項目我就不上傳了,須要的自己匯出。
:http://www.xuanyusong.com/archives/526