Unity笔记-25-简单的商城系统&数据库操作

Posted 韩天衣

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity笔记-25-简单的商城系统&数据库操作相关的知识,希望对你有一定的参考价值。

Unity笔记-25-简单的商城系统&数据库操作

要求与分析

英雄属性界面

展示英雄头像,英雄名称,英雄属性(AD,AP,AR,SR,自左向右,自上向下),金币数量

商店界面

展示可购买的物品,点击即可购买

背包界面

展示背包中的五瓶,点击即可出售

数据库(数据库为**Sqlite**本地数据库)

英雄表:存储英雄名称,英雄属性,金币数量,背包物品

商店表:存储物品名称,物品属性,物品价格

UI搭建

运行完成图展示


UI对象的父子级关系如图。英雄属性,BagShop添加了布局组件以方便网格布局。

自上而下分别为:英雄头像,英雄名称,英雄属性图,英雄属性值,金币数量,背包,商店

脚本模块

数据库部分

数据库功能&一次封装

提供数据库的基本功能:开启,关闭,更新,插入等方法

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mono.Data.Sqlite;

public class DatabaseFrame
{
  //单例
    #region Single
    private static DatabaseFrame instance;
    public static DatabaseFrame GetInstance()
    {
        if (instance == null)
        {
            instance = new DatabaseFrame();
        }
        return instance;
    }
    protected DatabaseFrame() { }
    #endregion
    public SqliteConnection con;
    public void OpenDatabase(string databaseName)
    {
        string connectPath;
        if (!databaseName.EndsWith(".sqlite"))
        {
            databaseName += ".sqlite";
        }
#if UNITY_EDITOR
        connectPath = "Data Source = " + Application.streamingAssetsPath + "/" + databaseName;
#endif
        con = new SqliteConnection(connectPath);
        con.Open();
    }
    public void CloseDatabase(SqliteConnection con,SqliteCommand command,SqliteDataReader reader)
    {
        if (con != null)
        {
            con.Close();
            con = null;
        }
        if (command != null)
        {
            command.Dispose();
            command = null;
        }
        if (reader != null)
        {
            reader.Close();
            reader = null;
        }
    }
    public int ModifyData(SqliteCommand command,string query)
    {
        command.CommandText = query;
        return command.ExecuteNonQuery();
    }
    public object SelectSingleData(SqliteCommand command,string query)
    {
        command.CommandText = query;
        return command.ExecuteScalar();
    }
    public List<ArrayList> SelectMultipleData(SqliteCommand command,SqliteDataReader reader,string query)
    {
        command.CommandText = query;
        reader = command.ExecuteReader();
        List<ArrayList> results = new List<ArrayList>();
        while (reader.Read())
        {
            ArrayList currentRow = new ArrayList();
            for(int i = 0; i < reader.FieldCount; i++)
            {
                currentRow.Add(reader.GetValue(i));
            }
            results.Add(currentRow);
        }
        return results;
    }
}

商店数据库&二次封装

继承DatabaseFrame类,也就是继承一次封装的类

在数据库的基础上,提供购买装备,出售装备,获得英雄属性,获取物品属性等数据库层面上的操作

其次,数据表需要提前定义映射类,方便数据接收

英雄表-背包物品使用格式:**|装备名称|装备名称**通过‘|‘隔开,在通过字符串的拆解判断

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mono.Data.Sqlite;

namespace ShopJDBC
{
    public class ShopFrame : DatabaseFrame
    {
        #region Single
        private static ShopFrame instance;
        //这里的new修饰符可以是的此方法覆盖调父类的同名方法或者属性
        public static new ShopFrame GetInstance()
        {
            if (instance == null)
            {
                instance = new ShopFrame();
            }
            return instance;
        }
        private ShopFrame()
        {

        }
        #endregion
        /// <summary>
        /// 买装备
        /// </summary>
        /// <param name="heroName">英雄名称</param>
        /// <param name="equipName">装备名称</param>
        public void BuyEquip(string heroName, string equipName)
        {
            HeroTable hero = GetHeroProperties(heroName);
            if (hero.heroEquips.Split('|').Length > 8)
            {
                Debug.Log("No BagBox");
                return;
            }
            EquipTable equip = GetEquipProperties(equipName);
            if (hero.heroMoney < equip.equipCost)
            {
                Debug.Log("Money is not enough");
                return;
            }
            hero.heroMoney -= equip.equipCost;
            PropertiesOperation(hero, equip, 1);
            EquipOperation(hero, equipName);
            UpdateHeroTable(hero);
        }
        /// <summary>
        /// 卖装备
        /// </summary>
        /// <param name="heroName">英雄名称</param>
        /// <param name="equipName">装备名称</param>
        /// <param name="equipIndex">装备位置</param>
        public void SellEquip(string heroName, string equipName, int equipIndex)
        {
            HeroTable hero = GetHeroProperties(heroName);
            EquipTable equip = GetEquipProperties(equipName);
            hero.heroMoney += equip.equipCost;
            PropertiesOperation(hero, equip, 2);
            EquipOperation(hero, equipName, equipIndex);
            UpdateHeroTable(hero);
        }
        /// <summary>
        /// 获得装备属性
        /// </summary>
        /// <param name="equipName">装备名称</param>
        /// <returns></returns>
        public EquipTable GetEquipProperties(string equipName)
        {
            SqliteCommand command = con.CreateCommand();
            SqliteDataReader reader = null;
            string query = "Select * from Shop where equipName='" + equipName + "'";
            List<ArrayList> result = SelectMultipleData(command, reader, query);
            CloseDatabase(null, command, reader);
            return new EquipTable(System.Convert.ToString(result[0][0]), System.Convert.ToInt32(result[0][1]), System.Convert.ToInt32(result[0][2]), System.Convert.ToInt32(result[0][3]), System.Convert.ToInt32(result[0][4]), System.Convert.ToInt32(result[0][5]));
        }
        /// <summary>
        /// 获得英雄属性
        /// </summary>
        /// <param name="heroName">英雄名称</param>
        /// <returns></returns>
        public HeroTable GetHeroProperties(string heroName)
        {
            SqliteCommand command = con.CreateCommand();
            SqliteDataReader reader = null;
            string query = "Select * from Hero where heroName='" + heroName + "'";
            List<ArrayList> result = SelectMultipleData(command, reader, query);
            HeroTable hero = new HeroTable(System.Convert.ToString(result[0][0]), System.Convert.ToInt32(result[0][1]), System.Convert.ToInt32(result[0][2]), System.Convert.ToInt32(result[0][3]), System.Convert.ToInt32(result[0][4]), System.Convert.ToInt32(result[0][5]), System.Convert.ToString(result[0][6]));
            if (hero.heroEquips == "NULL")
            {
                hero.heroEquips = "";
            }
            CloseDatabase(null, command, reader);
            return hero;
        }
        /// <summary>
        /// 更新英雄数据
        /// </summary>
        /// <param name="hero"></param>
        public void UpdateHeroTable(HeroTable hero)
        {
            SqliteCommand command = con.CreateCommand();
            string query = "Update Hero Set heroMoney=" + hero.heroMoney + ",ADProperty=" + hero.AD + ",APProperty=" + hero.AP + ",ARProperty=" + hero.AR + ",SRProperty=" + hero.SR + ",heroEquips='" + hero.heroEquips + "' where heroName='" + hero.heroName + "'";
            ModifyData(command, query);
            CloseDatabase(null, command, null);
        }
        /// <summary>
        /// 英雄-装备-属性操作
        /// </summary>
        /// <param name="hero">英雄</param>
        /// <param name="equip">装备</param>
        /// <param name="operationID">操作编号</param>
        public void PropertiesOperation(HeroTable hero, EquipTable equip, int operationID)
        {
            if (operationID == 1)
            {
                hero.AD += equip.AD;
                hero.AP += equip.AP;
                hero.AR += equip.AR;
                hero.SR += equip.SR;
            }
            else if (operationID == 2)
            {
                hero.AD -= equip.AD;
                hero.AP -= equip.AP;
                hero.AR -= equip.AR;
                hero.SR -= equip.SR;
            }
        }
        /// <summary>
        /// 英雄-装备-装备操作
        /// </summary>
        /// <param name="hero">英雄</param>
        /// <param name="equipName">装备名称</param>
        /// <param name="equipIndex">装备位置,不填则为空</param>
        public void EquipOperation(HeroTable hero, string equipName, int? equipIndex = null)
        {
            if (equipIndex == null)
            {
                hero.heroEquips += "|" + equipName;
            }
            else
            {
                hero.heroEquips = RemoveEquip(hero.heroEquips, 1) == "" ? "NULL" : RemoveEquip(hero.heroEquips, equipIndex.Value);
            }
        }
        /// <summary>
        /// 字符串-移除装备
        /// </summary>
        /// <param name="root"></param>
        /// <param name="valueIndex"></param>
        /// <returns></returns>
        public string RemoveEquip(string root, int valueIndex)
        {
            int index = 0;
            int endIndex = 0;
            for (int i = 0; i < valueIndex; i++)
            {
                index = root.IndexOf("|", index) + 1;
            }
            endIndex = root.IndexOf("|", index) != -1 ? root.IndexOf("|", index) : root.Length;
            root = root.Substring(0, index - 1) + root.Substring(endIndex);
            return root;
        }
        /// <summary>
        /// 获取所有装备信息
        /// </summary>
        /// <returns></returns>
        public List<EquipTable> GetEquips()
        {
            List<EquipTable> allEquip = new List<EquipTable>();
            SqliteCommand command = con.CreateCommand();
            SqliteDataReader reader = null;
            string query = "Select * from Shop";
            List<ArrayList> equips = SelectMultipleData(command, reader, query);
            for (int i = 0; i < equips.Count; i++)
            {
                EquipTable equip = new EquipTable(System.Convert.ToString(equips[i][0]), System.Convert.ToInt32(equips[i][1]), System.Convert.ToInt32(equips[i][2]), System.Convert.ToInt32(equips[i][3]), System.Convert.ToInt32(equips[i][4]), System.Convert.ToInt32(equips[i][5]));
                allEquip.Add(equip);
            }
            return allEquip;
        }
    }
    public class HeroTable
    {
        public string heroName;
        public int heroMoney;
        public int AD;
        public int AP;
        public int AR;
        public int SR;
        public string heroEquips;
        public HeroTable(string heroName, int heroMoney, int AD, int AP, int AR, int SR, string heroEquips)
        {
            this.heroName = heroName;
            this.heroMoney = heroMoney;
            this.AD = AD;
            this.AP = AP;
            this.AR = AR;
            this.SR = SR;
            this.heroEquips = heroEquips;
        }
    }
    public class EquipTable
    {
        public string equipName;
        public int equipCost;
        public int AD;
        public int AP;
        public int AR;
        public int SR;
        public EquipTable(string equipName, int equipCost, int AD, int AP, int AR, int SR)
        {
            this.equipName = equipName;
            this.equipCost = equipCost;
            this.AD = AD;
            this.AP = AP;
            this.AR = AR;
            this.SR = SR;
        }
    }
}

UI部分

UI界面

提供UI界面的所有初始化操作,购买或者出售后的更新操作

其余请看代码注释

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using ShopJDBC;

public class ShopView : MonoBehaviour
{
    private ShopFrame shop;
    private Transform shopWindow;
    private Transform bagWindow;
    private List<EquipTable> equips;
    private GameObject shopPerfabs;
    private GameObject bagPerfabs;
    private HeroTable hero;
    Transform propertiesParent;
    private List<Text> propertiesList;

    private void Awake()
    {
        shop = ShopFrame.GetInstance();
        UI_Init();
    }
    private void Start()
    {
        shop.OpenDatabase("ShopDatabase");
        HeroInitOrUpdate();
        BagInitOrUpdate();
        ShopInit();
    }
    /// <summary>
    /// UI初始化
    /// </summary>
    private void UI_Init()
    {
        shopWindow = transform.Find("Shop");
        shopPerfabs = Resources.Load<GameObject>("ShoppingCenterTest/Prefabs/ShopBox");
        bagWindow = transform.Find("Bag");
        bagPerfabs = Resources.Load<GameObject>("ShoppingCenterTest/Prefabs/BagBox");

        propertiesParent = transform.Find("HeroPropertiesText");
        propertiesList = new List<Text>();
        propertiesList.Add(transform.Find("HeroNameText").GetComponent<Text>());
        propertiesList.Add(propertiesParent.GetChild(0).GetComponent<Text>());
        propertiesList.Add(propertiesParent.GetChild(1).GetComponent<Text>());
        propertiesList.Add(propertiesParent.GetChild(2).GetComponent<Text>());
        propertiesList.Add(propertiesParent.GetChild(3).GetComponent<Text>());
        propertiesList.Add(transform.Find("Money").GetChild(0).GetComponent<Text>());

    }
    /// <summary>
    /// 获取精灵
    /// </summary>
    /// <param name="SpriteName">精灵名称</param>
    /// <returns></returns>
    private Sprite GetSprite(string SpriteName)
    {
        return Resources.Load<Sprite>("ShoppingCenterTest/Icon/"+SpriteName);
    }
    /// <summary>
    /// 商店初始化
    /// </summary>
    private void ShopInit()
    {
        equips = shop.GetEquips();
        for(int i = 0; i < equips.Count; i++)
        {
            GameObject shopbox = Instantiate(shopPerfabs);
            shopbox.GetComponent<ShopButton>().Init(hero.heroName,equips[i]);
            shopbox.GetComponent<ShopButton>().viewUpdate += HeroUpdate;
            shopbox.transform.SetParent(shopWindow.GetChild(i));
            shopbox.transform.localPosition = Vector3.zero;
            shopbox.transform.localScale = Vector3.one;
            shopbox.GetComponent<Image>().sprite = GetSprite(equips[i].equipName);
        }
    }
    /// <summary>
    /// 英雄属性初始化或者更新
    /// </summary>
    private void HeroInitOrUpdate()
    {
        hero = shop.GetHeroProperties("SKT_Faker");
        propertiesList[0].text = hero.heroName;
        propertiesList[1].text = hero.AD.ToString();
        propertiesList[2].text = hero.AP.ToString();
        propertiesList[3].text = hero.AR.ToString();
        propertiesList[4].text = hero.SR.ToString();
        propertiesList[5].text = hero.heroMoney.ToString();
    }
    /// <summary>
    /// 背包初始化
    /// </summary>
    private void BagInitOrUpdate()
    {
        string[] heroEquips = hero.heroEquips.Split('|');
        for (int i = 1; i < heroEquips.Length; i++)
        {
            GameObject bagbox = Instantiate(bagPerfabs);
            bagbox.GetComponent<BagButton>().Init(hero.heroName,heroEquips[i],i);
            bagbox.GetComponent<BagButton>().viewUpdate += HeroUpdate;
            bagbox.transform.SetParent(bagWindow.GetChild(i - 1));
            bagbox.transform.localPosition = Vector3.zero;
            bagbox.transform.localScale = Vector3.one;
            bagbox.GetComponent<Image>().sprite = GetSprite(heroEquips[i]);
        }
    }
    /// <summary>
    /// 背包更新
    /// </summary>
    private void BagUpdate()
    {
        string[] heroEquips = hero.heroEquips.Split('|');
        for(int i = 1; i < heroEquips.Length; i++)
        {
            if (bagWindow.GetChild(i - 1).childCount != 0)
            {
                Transform bagbox = bagWindow.GetChild(i - 1).GetChild(0);
                bagbox.GetComponent<BagButton>().Init(hero.heroName, heroEquips[i], i);
                bagbox.GetComponent<Image>().sprite = GetSprite(heroEquips[i]);
            }
            else
            {
                GameObject bagbox = Instantiate(bagPerfabs);
                bagbox.GetComponent<BagButton>().Init(hero.heroName, heroEquips[i], i);
                bagbox.GetComponent<BagButton>().viewUpdate += HeroUpdate;
                bagbox.transform.SetParent(bagWindow.GetChild(i - 1));
                bagbox.transform.localPosition = Vector3.zero;
                bagbox.transform.localScale = Vector3.one;
                bagbox.GetComponent<Image>().sprite = GetSprite(heroEquips[i]);
            }
        }
        for (int i = heroEquips.Length; i <= 8; i++)
        {
            if (bagWindow.GetChild(i - 1).childCount != 0) 
                Destroy(bagWindow.GetChild(i-1).GetChild(0).gameObject);
        }
    }
    /// <summary>
    /// 面板更新
    /// </summary>
    private void HeroUpdate()
    {
        HeroInitOrUpdate();
        BagUpdate();
    }
    /// <summary>
    /// 退出
    /// </summary>
    private void OnApplicationQuit()
    {
        shop.CloseDatabase(shop.con, null, null);
    }
}

装备按钮(商店&背包)

Shop下的装备按钮

唯一需要说明的是:UI界面的更新,需要通过装备按钮脚本的事件绑定UI界面脚本里的更新方法,再操作完购买或者出售的时候更新面板

另外在鼠标进入装备按钮,会显示装备的名称,价格,属性,通过鼠标事件实现

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using ShopJDBC;
using System;
using UnityEngine.EventSystems;
using Random = System.Random;

public class ShopButton : MonoBehaviour,IPointerEnterHandler,IPointerExitHandler
{
    public Action viewUpdate;
    public string heroName;
    public EquipTable equip;
    private Button button;
    private GameObject tipPrefab;
    private GameObject tip;
    private Random random;
    private Transform parent;
    private Transform ShopWindow;
    private void Awake()
    {
        random = new Random();
        button = transform.GetComponent<Button>();
        button.onClick.AddListener(OnChick);
        tipPrefab= Resources.Load<GameObject>("ShoppingCenterTest/Prefabs/Tip");
    }
    private void Start()
    {
        parent = transform.parent;
        ShopWindow = parent.parent;
    }
    public void Init(string heroName,EquipTable equip)
    {
        this.heroName = heroName;
        this.equip = equip;
    }
    public void OnChick()
    {
        ShopFrame.GetInstance().BuyEquip(heroName, equip.equipName);
        viewUpdate();
    }
    public void OnPointerEnter(PointerEventData eventData)
    {
        tip = Instantiate(tipPrefab);
        //tip.GetComponent<Image>().color = new Color(random.Next(0,255)/255f,random.Next(0,255)/255f,random.Next(0,255)/255f,0.2f);
        tip.transform.position =new Vector3(parent.position.x,parent.position.y,parent.position.z);
        tip.transform.SetParent(ShopWindow);
        tip.transform.GetChild(0).GetComponent<Text>().text = equip.equipName;
        tip.transform.GetChild(1).GetComponent<Text>().text = "Cost:"+equip.equipCost.ToString();
        tip.transform.GetChild(2).GetComponent<Text>().text = "AD:"+equip.AD.ToString();
        tip.transform.GetChild(3).GetComponent<Text>().text = "AP:"+equip.AP.ToString();
        tip.transform.GetChild(4).GetComponent<Text>().text = "AR"+equip.AR.ToString();
        tip.transform.GetChild(5).GetComponent<Text>().text = "SR"+equip.SR.ToString();     
    }
    public void OnPointerExit(PointerEventData eventData)
    {
        Destroy(tip);
        tip = null;
    }
}
Bag下的装备按钮
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using ShopJDBC;
using System;

public class BagButton : MonoBehaviour
{
    public Action viewUpdate;
    public string heroName;
    public string equipName;
    public int buttonIndex;
    private Button button;
    private void Awake()
    {
        button = transform.GetComponent<Button>();
        button.onClick.AddListener(OnChick);
    }
    public void Init(string heroName,string equipName,int index)
    {
        this.heroName = heroName;
        this.equipName = equipName;
        this.buttonIndex = index;
    }
    public void OnChick()
    {
        ShopFrame.GetInstance().SellEquip(heroName,equipName,buttonIndex);
        viewUpdate();
    }
}

以上是关于Unity笔记-25-简单的商城系统&数据库操作的主要内容,如果未能解决你的问题,请参考以下文章

[Unity C++] 前端+后端商城和背包系统

学习笔记:Vue+Node+Mongodb构建简单商城系统

Unity 游戏黑暗之光笔记第四章 任务系统的实现

谷粒商城学习笔记-- 项目简介和分布式基础概念

谷粒商城学习笔记-- 环境搭建&项目结构创建

Unity图形节点插件xNode简单使用说明