物品拖拽[u3d_rpg遊戲開發之物品管理(五)]_遊戲開發

來源:互聯網
上載者:User
之前在網上找了好多方法,總是不適合自己,要麼就是不能用之類的,我用的是2017的版本,在這裡"全面"解析一下.首先建立一個指令碼InventoryItem掛在需要拖拽的Image上,這裡的Image是另一個Image的子物體,因為子的Imget我用來顯示物品的相應物品的圖片,而父的Image我用來顯示格子的圖片,這樣就有了格子裡面的物品,可以用來拖動,而且,格子的標籤我設為"InventoryItemGird",拖拽結束時就可以通過標籤判斷是不是格子.
1. 繼承介面

u3d的ugui有相應的介面來方便我們實現拖拽功能,除了本來就需要繼承的MonoBehaviour外,我們寫的指令碼再繼承三個介面,還得先匯入標頭檔 UnityEngine.EventSystems;

using UnityEngine.EventSystems;public class InventoryItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler{}
2. 實現抽象方法

抽象方法同樣是三個

using UnityEngine.EventSystems;public class InventoryItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler{    /// <summary>    /// 實現介面的OnBeginDrag方法,處理開始拖拽時要做的事情    /// </summary>    /// <param name="eventData"></param>    public void OnBeginDrag(PointerEventData eventData)    {    }    /// <summary>    /// 實現介面的OnDrag方法,處理拖動中要做的事情    /// </summary>    /// <param name="eventData"></param>    public void OnDrag(PointerEventData eventData)    {    }    /// <summary>    /// 實現介面的OnEndDrag方法,處理結束時的方法    /// </summary>    /// <param name="eventData"></param>    public void OnEndDrag(PointerEventData eventData)    {    }}
3. 去遮擋
拖拽的時候我們會遇到一個問題,就是拖拽物品的父物體是是一個格子,而格子又位於不同的層,如圖:

我把格子取名為Inventory-Item-gird-00至Inventory-Item-gird-34共20個格子,這裡的第一個格子Inventory-Item-gird-00在其他格子的後面,ui物體越靠下就越顯示在攝像機的越靠外層,所以,當Inventory-Item-gird-00下的物品拖拽到Inventory-Item-gird-34格子的位置時,會被其遮擋我們這裡就在最下面再建立一個隱形而不能用畫布:Canvas,當我們需要拖動物品時就將該物品的父物體設定為Canvas,拖拽物品就會位於最外層,不會被任何ui遮擋,需要注意的是,當拖拽結束我們需要將父物體設定回來,不然會導致原來格子下的Image沒了.
    private Transform imageParent;//拖拽物品的父物體    private Canvas imageFather;//擷取最外層的畫布    private Vector2 drugingRectTransform;//正在被拖拽的圖片的原始位置    public void OnBeginDrag(PointerEventData eventData)    {        imageFather = GameObject.Find("Canvas").GetComponent<Canvas>();//擷取在最外層的格子        drugingRectTransform = myImage.rectTransform.position;//擷取初始位置        imageParent = transform.parent;//擷取父物體的transform        transform.SetParent(imageFather.transform);//將物品放在最外層    }    /// <summary>    /// 將一個物體放在另一個物體下    /// </summary>    /// <param name="child">作為子物體</param>    /// <param name="parent">作為父物體</param>    private void SetParentAndPosition(Transform child, Transform parent)//將child放到parent下作為子物體    {        child.SetParent(parent);        child.position = parent.position;    }
4. 實現穿透
當我們拖拽結束的時候,我們需要判斷滑鼠停留的位置是否是一個格子,如果是格子才有可能吧物品放進去,如果不是就要讓物品還原位置.那麼問題來了,拖拽物品始終在滑鼠位置,也就是說判斷滑鼠停留位置的時候,射線判斷到的永遠是我們正在拖拽的物品.所以我們我讓我們在拖拽中的物品不被滑鼠射線檢測到,也就是使物品實現穿透.這個時候我們的物品位於Canvas下,所以我們只需要讓Canvas實現穿透就行了,先給其添加一個組件:Canvas Group

這個組件下的Blocks Raycasts選項就表示所在物體是否會遮擋滑鼠射線,這時我們就可以通過代碼來控制其開關了.
    /// <summary>    /// 實現介面的OnBeginDrag方法,處理開始拖拽時要做的事情    /// </summary>    /// <param name="eventData"></param>    public void OnBeginDrag(PointerEventData eventData)    {        imageFather = GameObject.Find("Canvas").GetComponent<Canvas>();//擷取在最外層的畫布        drugingRectTransform = myImage.rectTransform.position;//擷取初始位置        imageParent = transform.parent;//擷取父物體的transform        transform.SetParent(imageFather.transform);//將物品放在最外層        GameObject.Find("Canvas").GetComponent<CanvasGroup>().blocksRaycasts = false;//射線可以穿透物體    }
至此開始拖拽物品的方法完全實現
5. 物品置入
物品置入前還有一個拖拽方法需要實現:
    /// <summary>    /// 實現介面的OnDrag方法,處理拖動中要做的事情    /// </summary>    /// <param name="eventData"></param>    public void OnDrag(PointerEventData eventData)    {        this.GetComponent<RectTransform>().position=Input.mousePosition;//滑鼠左鍵按住拖拽的時候,物體跟著滑鼠移動    }
最後就是拖拽結束的方法了.最後一個交換物品的方法可以不用管,我寫給自己看的,所有的思路已經很清晰了.
    /// <summary>    /// 實現介面的OnEndDrag方法,處理結束時的方法    /// </summary>    /// <param name="eventData"></param>    public void OnEndDrag(PointerEventData eventData)    {        SetParentAndPosition(transform, imageParent);//複原父物體        transform.position = drugingRectTransform;//原圖歸位        ExchangeOfGoods(eventData);//交換物品        GameObject.Find("Canvas").GetComponent<CanvasGroup>().blocksRaycasts = false;//ui事件穿透:置為不能穿透    }    /// <summary>    /// 格子內的物品進行交換    /// </summary>    /// <param name="eventData">參數PointerEventData用於擷取滑鼠終點位置</param>    private void ExchangeOfGoods(PointerEventData eventData)    {        GameObject go = eventData.pointerCurrentRaycast.gameObject;//擷取滑鼠下的物體        //如果物體不為空白且該物體為物品格子        if (go != null && go.tag.Equals("InventoryItemGird"))        {            InventoryItemGrid fatherOfThis = this.GetComponentInParent<InventoryItemGrid>();//擷取起點格子的指令碼            InventoryItemGrid fatherOfThat = go.GetComponent<InventoryItemGrid>();//擷取終點格子的指令碼            //如果格子為空白格子            if (fatherOfThat.id == 0)            {                fatherOfThat.SetId(fatherOfThis.id,fatherOfThis.num);//向終點格子儲存物品                fatherOfThis.ClearInfo();//清空原來格子資訊            }            else//兩格子交換物品            {                InventoryItemGrid temp = fatherOfThat;//臨時儲存終點格子的指令碼                fatherOfThat.SetId(fatherOfThis.id, fatherOfThis.num);//向終點格子儲存物品                fatherOfThis.SetId(temp.id, temp.num);//向起點格子儲存物品            }        }    }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.