前言
本文基於MVC模式,用UGUI初步實現了背包系統。
Control層包括了點擊和拖拽兩種邏輯。
博文首發:http://blog.csdn.net/duzixi
下載地址:https://github.com/duzixi/InventorySystem
一、project准備(詳見project文件)
場景中Canvas上的對象:
- Bag:用於顯示背包內容
- PickedItem:用於顯示拾取道具的圖片
資源中的預設體:
- Item:生成背包的格子
二、源碼
Model 層
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 腳本功能:MVC模式——Model層。定義物品結構,保存物品數據
/// 加入對象:Bag 背包(Canvas下的空對象)
/// 版權聲明:Copyright (c) 2015 duzixi.com All Rights Reserved
/// 創建日期:2015.5.8
/// 知識要點:
/// 1. MVC
/// 2. 自己定義類
/// 3. 類的嵌套
/// </summary>
public class ItemModel : MonoBehaviour {
// 物品類的定義
public class Item
{
public string name; // 物品名稱
public Sprite img; // 物品圖片
// 構造器
public Item(string name, Sprite img) {
this.name = name;
this.img = img;
}
}
public static List<Item> items; // 保存物品對象的集合
// 物品圖片數組
public int size = 16;
Sprite[] sprites;
void Awake() // 數據初始化
{
items = new List<Item>(); // 初始化List<Item>
sprites = new Sprite[size];
// 依據行列值初始化物品列表
for (int i = 0; i < BagView.row; i++) {
for (int j = 0; j < BagView.col; j++) {
items.Add(new Item("", null));
}
}
// 【注意】實際開發中下面部分應由數據庫取代
for (int i = 0; i < size; i++) {
string name = i < 9 ? "0" + (i + 1) : "" + (i + 1);
sprites[i] = Resources.Load(name, typeof(Sprite)) as Sprite;
items[i] = new Item(" ", sprites[i]);
}
}
}
View 層
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
/// <summary>
/// 腳本功能:MVC模式 —— View視圖,控制背包的顯示方式
/// 加入對象:Bag 背包 (Canvas下的空對象)
/// 版權聲明:Copyright (c) 2015 duzixi.com All Rights Reserved
/// 創建時間:2015.05.08
/// 改動記錄:2015.05.18 加入編號
/// 改動記錄:2015.07.03 封裝顯示物品行子方法
/// 知識要點:
/// 1. MVC
/// 2. UGUI
/// </summary>
public class BagView : MonoBehaviour {
// 背包規格
public static int row = 4; // 行
public static int col = 5; // 列
// 背包格子
public GameObject grid;
float width; // 格子寬度
float height; // 格子高度
// 依據格子預設體獲取寬和高
void Awake() {
width = grid.GetComponent<RectTransform>().rect.width;
height = grid.GetComponent<RectTransform>().rect.height;
}
// 初始狀態:平鋪格子。創建背包
void Start () {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
// 計算ID值(物品列表下標)
int id = j + i * col;
// 實例化格子預設,按寬高布局
GameObject itemGrid = Instantiate(grid, transform.position + new Vector3(j * width, -i * height, 0), Quaternion.identity) as GameObject;
// 將實例化的格子對象設置為背包的子對象
itemGrid.transform.SetParent(transform);
// 調用自己定義方法:顯示某個id的格子內容
ShowItem(itemGrid.transform, id);
// 給格子 PickUpDrop 組件編號。拾取放下時用
itemGrid.GetComponent<PickUpDrop>().gridID = id;
}
}
}
// 又一次刷新背包顯示(物品位置發生變化時)
public void ShowItems() {
for (int i = 0; i < row * col; i++) {
Transform itemGrid = transform.GetChild(i);
ShowItem(itemGrid, i);
}
}
// 顯示物品行子
private void ShowItem(Transform itemGrid, int id) {
// 顯示物品名稱
Text txtUGUI = itemGrid.GetComponentInChildren<Text>();
txtUGUI.text = ItemModel.items[id].name;
// 獲取物品Icon的Image組件
Image imageUGUI = itemGrid.GetChild(0).GetComponent<Image>();
// 假設有物品。就顯示圖片
if (ItemModel.items[id].img != null) {
imageUGUI.color = Color.white;
} else { // 否則不顯示
imageUGUI.color = Color.clear;
}
imageUGUI.sprite = ItemModel.items[id].img;
}
}
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
/// <summary>
/// 腳本功能:讓拾取的背包物品隨鼠標移動
/// 加入對象:PickedItem 拾取的物品
/// 版權聲明:Copyright (c) 2015 duzixi.com All Rights Reserved
/// 創建日期:2015.05.18
/// 改動記錄:2015.07.03 加入射線忽略
/// 知識要點:
/// 1. UGUI RectTransform、錨點、中心點
/// 2. 忽略射線接口 ICanvasRaycastFilter
/// </summary>
public class MoveWithMouse : MonoBehaviour, ICanvasRaycastFilter {
RectTransform rect; // 獲取UGUI定位組件
Image icon; // 顯示當前拾取物品的圖標
void Awake() {
rect = GetComponent<RectTransform>();
// 【注意】圖標對象是第0個子對象
icon = transform.GetChild(0).GetComponent<Image>();
}
void Update () {
// 用鼠標位置給圖標圖片定位
rect.anchoredPosition3D = Input.mousePosition;
// 依據是否有圖片確定透明度
if (PickUpDrop.pickedItem.img != null) {
icon.color = Color.white;
} else {
icon.color = Color.clear;
}
icon.sprite = PickUpDrop.pickedItem.img;
}
// 忽略鼠標圖標上的射線
public bool IsRaycastLocationValid (Vector2 sp, Camera eventCamera) {
return false;
}
}
Control 層
using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections;
/// <summary>
/// 腳本功能:MVC模式 —— Control控制,背包內物品擺放
/// 加入對象:Item 物品行子預設體
/// 版權聲明:Copyright (c) 2015 duzixi.com All Rights Reserved
/// 創建日期:2015.05.18 duzixi.com
/// 改動記錄:2015.07.03 加入射線忽略
/// 知識要點:
/// 1. UGUI、MVC設計模式
/// </summary>
public class PickUpDrop : MonoBehaviour, IDropHandler {
public int gridID;
public static ItemModel.Item pickedItem; // 當前拾取的物品
void Start () {
// 初始化當前拾取物品為空
pickedItem = new ItemModel.Item("", null);
}
// 背包核心邏輯:交換
public static void SwapItem(int gridID)
{
// 交換背包中的物品和拾取物品
ItemModel.Item temp = pickedItem;
pickedItem = ItemModel.items[gridID];
ItemModel.items[gridID] = temp;
// 刷新背包顯示
GameObject.Find("Bag").GetComponent<BagView>().ShowItems();
}
// 當物品button被點下時(點擊觸發模式)
public void Drop() {
SwapItem(gridID);
}
// 當物品放在格子中時(拖拽觸發模式)
public void OnDrop (PointerEventData eventData) {
SwapItem(gridID);
}
}
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
/// <summary>
/// 腳本功能:MVC模式 —— Control控制。操作邏輯。拖拽事件處理
/// 加入對象:Bag 背包 (Canvas下的空對象)
/// 版權聲明:Copyright (c) 2015 duzixi.com All Rights Reserved
/// 創建時間:2015.07.03
/// 知識要點:
/// 1. UnityEngine.EventSystem
/// 2. IBeginDragHandlder, IDragHandler, IEndDragHander
/// </summary>
public class DragEvent : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler {
int gridID = 0; // 格子編號
void Start() {
gridID = GetComponentInParent<PickUpDrop>().gridID; // 獲取格子編號
}
// 開始拖拽
public void OnBeginDrag (PointerEventData eventData) {
// 調用交換方法
PickUpDrop.SwapItem(gridID);
}
// 拖拽中
public void OnDrag (PointerEventData eventData) {
// 【注意】即使沒有不論什么代碼處理也要實現該接口。否則拖拽不成功
}
// 結束拖拽
public void OnEndDrag (PointerEventData eventData) {
// 調用交換方法
PickUpDrop.SwapItem(gridID);
}
}
后語
眼下還有點Bug。拖拽模式下當前物體拖拽會導致物品尾隨。
另外屏幕適配還沒有搞。
