以委託的方式使用簡易手勢與加速規控制

參考文章:
C# 事件和Unity3D - http://zijan.iteye.com/blog/871207
以兩點座標求其角度與連線之垂直向量方向 - http://blog.happybean.tw/blog/2012/07/04/javascript-yi-liang-dian-zuo-biao-qiu-qi-jiao-du-yu-lian-xian-zhi-chui-zhi-xiang-liang-fang-xiang
NGUI研究院之三种方式监听NGUI的事件方法(七) - http://www.xuanyusong.com/archives/2390

觸控數量 - http://game.ceeger.com/Script/Input/Input.touchCount.html
觸控狀態 - http://game.ceeger.com/Script/Enumerations/TouchPhase/TouchPhase.html
觸控列表 - http://game.ceeger.com/Script/Input/Input.touches.html
獲取觸控 - http://game.ceeger.com/Script/Input/Input.GetTouch.html




不知道該怎麼解釋內容,寫得不是很理想,也不是很懂為什麼這樣用、是不是該這樣理解,感覺有些細節還是沒調整好,反正主要請翻閱『C# 事件和Unity3D』、『NGUI研究院之三种方式监听NGUI的事件方法(七) 』
總之大概是在A腳本內放一些方式去,再到B腳本去監聽A腳本有設定好的函數,不過因為我想有多種控制方式,所以在B腳本可能有可能同時有2.3個函數呼叫同一個函數來控制移動、跳躍、攻擊。
如果理解錯或者寫的不夠好,還請前輩們指正。






要使用的對象請大概這樣去使用,將 EventGestures (判斷手勢) EventAcceleration (判斷加速規)的GameObject指派到 accelerationListener 跟 gesturesListener 上。
我原本的腳本是有加上NGUI的監聽,所以其實我同時有兩個函數去呼叫MoveStand、MoveLeft、MoveRight(只是我這邊就不放上了,直接套用發生錯誤是當然的)



using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
    public GameObject accelerationListener;  
    public GameObject gesturesListener;  
    void Awake()
    {
        accelerationListener.GetComponent<EventAcceleration>().XAccelerationLeft += AccelerationLeft;
        accelerationListener.GetComponent<EventAcceleration>().XAccelerationRight += AccelerationRight;
        accelerationListener.GetComponent<EventAcceleration>().XAccelerationMid += AccelerationMid;
            
        gesturesListener.GetComponent<EventGestures>().SwipeUp += GesturesJump;
        gesturesListener.GetComponent<EventGestures>().SwipeDown += GesturesAttack;
        gesturesListener.GetComponent<EventGestures>().HoldUp += GesturesJump;
        gesturesListener.GetComponent<EventGestures>().HoldDown += GesturesAttack;
    }
    /// <summary>
    /// Accelerations the middle.
    /// 陀螺儀及手勢監聽
    /// </summary>
    /// <param name='g'>
    /// G.
    /// </param>
    void AccelerationMid (){
        MoveStand();
    }
    void AccelerationLeft (){
        MoveLeft();
    }
    void AccelerationRight (){
        MoveRight();
    }
        
    void GesturesJump()
    {
        Jump();
    }
    void GesturesAttack()
    {
         Attack();
    }
}


手勢判斷

using UnityEngine;
using System.Collections;
    
public class EventGestures : MonoBehaviour {
    /// <summary>
    /// Event handler.
    /// </summary>
    public delegate void EventHandler();  
    public event EventHandler SwipeUp;  
    public event EventHandler SwipeDown;  
    public event EventHandler HoldUp;  
    public event EventHandler HoldDown;  
        
    /// <summary>
    /// The touch start move end.
    /// 起始座標
    /// 移動座標
    /// 結束座標
    /// 方向
    /// 移動判斷距離
    /// 起始判斷布林
    /// 移動判斷布林
    /// 判斷X軸手勢布林
    /// 判斷Y軸手勢布林
    /// 判斷斜角手勢布林
    /// 垂直手勢方向記錄
    /// 水平手勢方向記錄
    /// 移動判斷迴圈延遲影格數
    /// </summary>
    public Vector2 touchStart;
    public Vector2 touchMove;
    public Vector2 touchEnd;
    public Vector2 gesturesDir = Vector2.zero;
    public float moveDis = 10.0f;
    public bool startBool;
    public bool moveBool;
    public bool gesturesX;
    public bool gesturesY = true;
    public bool gesturesSlope;
        
    float verticalBool;
    float horizontalBool;
        
    public int yieldFrame = 2;
    /// <summary>
    /// Start this instance.
    /// 以 PlayerPrefs 判斷是否執行腳本迴圈判斷
    /// </summary>
    void Start () 
    {
        PlayerPrefs.SetInt("CE_GesturesControl", 1);
        if (PlayerPrefs.GetInt("CE_GesturesControl") == 1){
            StartCoroutine("TouchPointPosition");
            StartCoroutine("TouchPointMovePosition");
        }
    }
        
    /// <summary>
    /// Touchs the point position.
    /// 迴圈判斷觸控 起始 與 結束
    /// </summary>
    /// <returns>
    /// The point position.
    /// </returns>
    IEnumerator TouchPointPosition()
    {
        while(true)
        {
            if (Input.touchCount > 0)
            {
                // 將觸碰進入點座標放置相對應陣列
                if (Input.GetTouch(0).phase == TouchPhase.Began && !startBool)
                {
                    startBool = true;
                    touchStart = Input.GetTouch(0).position;
                    touchMove = Input.GetTouch(0).position;
                        
                }
                // 將觸碰離開點座標放置相對應陣列,並判斷方向、執行相對應函數
                if (Input.GetTouch(0).phase == TouchPhase.Ended && startBool)
                {
                    startBool = false;
                    moveBool = false;
                    touchEnd = Input.GetTouch(0).position;
                    GesturesCtrl(touchStart,touchEnd);
                    if (gesturesDir == new Vector2(0.0f,1.0f)){
                        onSwipeUp();
                    }else if(gesturesDir == new Vector2(0.0f,-1.0f)) {
                        onSwipeDown();
                    }
                }
            }
            yield return 0;
        }
    }
    /// <summary>
    /// Touchs the point move position.
    /// 迴圈判斷觸控移動,並判斷與起始座標距離是否超出,是則判斷方向,並執行相對應函數
    /// </summary>
    /// <returns>
    /// The point move position.
    /// </returns>
    IEnumerator TouchPointMovePosition()
    {
        while(true)
        {
            if (Input.touchCount > 0 && startBool && !moveBool)
            {
                if (Input.GetTouch(0).phase == TouchPhase.Moved)
                {
                    touchMove = Input.GetTouch(0).position;
                    float moveDiff = Vector2.Distance(touchStart,touchMove);
                    if (moveDiff > moveDis)
                    {
                        moveBool = true;
                        GesturesCtrl(touchStart,touchMove);
                        if (gesturesDir == new Vector2(0.0f,1.0f)){
                            onHoldUp();
                        }else if(gesturesDir == new Vector2(0.0f,-1.0f)) {
                            onHoldDown();
                        }
                    }
                }
        
            }
            yield return yieldFrame;
        }
    }
    /// <summary>
    /// Gestureses the ctrl.
    /// 判斷手勢兩點方向函數
    /// </summary>
    /// <param name='startPoint'>
    /// Start point.
    /// </param>
    /// <param name='endPoint'>
    /// End point.
    /// </param>
    void GesturesCtrl(Vector2 startPoint, Vector2 endPoint)
    {
        float xDiff = endPoint.x - startPoint.x;
        float yDiff = endPoint.y - startPoint.y;
        float slope = Mathf.Abs(yDiff / xDiff);
            
        if (gesturesY){
            if (yDiff>0){
                verticalBool = 1.0f;
            }else if(yDiff<0){
                verticalBool = -1.0f;
            }else{
                verticalBool = 0.0f;
            }
        }
        if (gesturesX){
            if (xDiff>0){
                horizontalBool = 1.0f;
            }else if(xDiff<0){
                horizontalBool = -1.0f;
            }else{
                horizontalBool = 0.0f;
            }
        }
        if (gesturesSlope){
            if (slope>2){
                gesturesDir.y = verticalBool;
                gesturesDir.x = 0.0f;
            }else if(slope<0.5){
                gesturesDir.x = horizontalBool;
                gesturesDir.y = 0.0f;
            }else{
                gesturesDir.x = horizontalBool;
                gesturesDir.y = verticalBool;
            }
        }else{
            gesturesDir.y = verticalBool;
            gesturesDir.x = horizontalBool;
        }
    }
    /// <summary>
    /// Ons the swipe up.
    /// 監聽用空函數
    /// </summary>
    void onSwipeUp ()
    {
        if (SwipeUp != null){
            SwipeUp ();  
        }
    }
    void onSwipeDown ()
    {
        if (SwipeDown != null){
            SwipeDown ();  
        }
    }
    void onHoldUp ()
    {
        if (HoldUp != null){
            HoldUp ();  
        }
    }
    void onHoldDown ()
    {
        if (HoldDown != null){
            HoldDown ();  
        }
    }
}



加速規判斷(主要判斷X軸)

using UnityEngine;
using System.Collections;
    
public class EventAcceleration : MonoBehaviour {
    /// <summary>
    /// Event handler.
    /// </summary>
    public delegate void EventHandler();  
    public event EventHandler XAccelerationLeft;  
    public event EventHandler XAccelerationRight;  
    public event EventHandler XAccelerationMid;  
        
        
    public float accelerationX;
    public float accelerationXSensitivity = 0.2f;
    public int accelerationXDir;
    public float accelerationY;
    public float accelerationZ;
        
    public int yieldFrame = 2;
    // Use this for initialization
    void Start () {
        PlayerPrefs.SetInt("CE_AccelerationControl", 1);
        if (PlayerPrefs.GetInt("CE_AccelerationControl") == 1){
            StartCoroutine("XAcceleration");
        }
    }
    IEnumerator XAcceleration () {
        while(true)
        {
            accelerationX = Input.acceleration.x;
            if (accelerationX > accelerationXSensitivity && accelerationXDir != 1){
                OnXAccelerationRight();
            }else if (accelerationX < -accelerationXSensitivity && accelerationXDir != -1){
                OnXAccelerationLeft();
            }else if (accelerationXDir != 0 && accelerationX < accelerationXSensitivity  && accelerationX > -accelerationXSensitivity){
                OnXAccelerationMid();
            }
            yield return yieldFrame;
        }
            
    }
    void OnXAccelerationLeft (){
        if (XAccelerationLeft != null){
            XAccelerationLeft ();  
        }
        accelerationXDir = -1;
    }
    void OnXAccelerationRight (){
        if (XAccelerationRight != null){
            XAccelerationRight ();  
        }
        accelerationXDir = 1;
    }
    void OnXAccelerationMid (){
        if (XAccelerationMid != null){
            XAccelerationMid ();  
        }
        accelerationXDir = 0;
    }
}

留言

這個網誌中的熱門文章

參加畢業展之設計類展場小心得

Unity 判斷兩物之間距離、角度,並注視目標

Action Game Maker 1.03 正體中文漢化版