Unity 结合数据库实现商城购买装备以及数据更新

放假在家没事可做,游戏荒ing,做个商城教学,针对有一定基础的新手,先分析下商城购买装备是怎么实现的

购买流程

  1. 查询改装备的价格
  2. 查询当前玩家有多少钱
  3. 判断钱够不够买装备
  4. 如果够:召唤师的钱-=装备的钱
  5. 查询现在玩家有什么装备
  6. 给玩家添加改装备
  7. 查询该装备的属性加成
  8. 查询玩家属性值
  9. 更新玩家属性值:英雄属性+=装备属性加成

先看下最终效果图

在这里插入图片描述

我们一步一步的来,先从最简单的开始

一、准备工作

随便搭个简单的商城界面,配置下sql数据像这样

请添加图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

二、封装数据库(SqlBase)

之后另开一篇来讲sql框架是怎么封装的,先列几个用到的api。
ExecuteNonQuery:如果您不希望返回任何结果集,请使用此操作在SQL Server中执行任意SQL语句。
ExecuteReader:如果希望将结果集作为DataSet数组返回(如果有的话),请使用此操作在SQL Server中执行任意SQL语句。
ExecuteScalar:使用此操作可以执行SQL Server中的任何任意SQL语句以返回单个值。此操作仅在SQL语句返回的结果集中第一行的第一列中返回值。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mono.Data.Sqlite;
public class SqlBase
{
    //单例
    private static SqlBase Instance;
    public static SqlBase GetInstance()
    {
        if (Instance == null)
        {
            Instance = new SqlBase();
        }
        return Instance;
    }

    private SqliteConnection con;
    private SqliteCommand command;
    private SqliteDataReader reader;

    /// <summary>
    /// 打开数据库
    /// </summary>
    /// <param name="dbName">文件名</param>
    public void OpenSqlData(string dbName)
    {
        if (!dbName.EndsWith(".sqlite"))
        {
            dbName += ".sqlite";
        }

        string path = "";
#if UNITY_EDITOR || UNITY_STANDALONE
        path = "Data Source = "
                 + Application.streamingAssetsPath
                 + "/" + dbName;
#endif
        //实例化连接对象
        con = new SqliteConnection(path);
        //打开连接
        con.Open();
        //实例化指令对象
        command = con.CreateCommand();

    }
    public void CloseSqlData()
    {
        con.Close();
        command.Dispose();

        con = null;
        command = null;
    }
    /// <summary>
    /// 执行语句
    /// </summary>
    /// <param name="sqlQuery"></param>
    /// <returns></returns>
    public int JustExecute(string sqlQuery)
    {
        command.CommandText = sqlQuery;

        return command.ExecuteNonQuery();
    }
    /// <summary>
    /// 查询单个语句
    /// </summary>
    /// <param name="sqlQuery"></param>
    /// <returns></returns>
    public object SeletSingleData(string sqlQuery)
    {
        command.CommandText = sqlQuery;

        return command.ExecuteScalar();
    }
    /// <summary>
    /// 查询多种数据
    /// </summary>
    /// <param name="sqlQuery"></param>
    /// <returns></returns>
    public List<ArrayList> SeletMultipleData(string sqlQuery)
    {
        command.CommandText = sqlQuery;

        reader = command.ExecuteReader();
        //存储数据 List<ArrayList>==>List<List<Object>>
        List<ArrayList> result = new List<ArrayList>();

        while (reader.Read())
        {
            //新建ArrayList存储当行的数据
            ArrayList rowData = new ArrayList();
            //遍历所有的列
            for (int i = 0; i < reader.FieldCount; i++)
            {
                //将当前行的当前列添加到rowData
                rowData.Add(reader.GetValue(i));
            }
            //将储存好的当前行数据添加到List
            result.Add(rowData);
        }
        reader.Close();

        return result;
    }
}


三、进行二次封装

根据购买流程的分析,我们需要在数据库中查询到:
英雄:英雄金币、英雄属性
商店:装备列表、装备价格、装备属性

主要进行的操作:
对于英雄:花费金钱,英雄属性变化(买装备)

封装功能:

  1. 查询英雄名称
  2. 查询英雄有多少钱
  3. 查询英雄属性
  4. 查询英雄装备列表
  5. 查询商城中所有装备
  6. 查询装备属性信息
  7. 设置玩家金钱
  8. 花费玩家金钱
  9. 给玩家添加装备给英雄添加装备属性
  10. 买装备

之后在进行一系列操作,对于商城数据库的封装做到这些功能就ok了

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShopSqlFrameWork : SqlBase
{
    //单例方便调用
    private static ShopSqlFrameWork Instance;
    public static ShopSqlFrameWork GetInstance()
    {
        if (Instance == null)
        {
            Instance = new ShopSqlFrameWork();
        }
        return Instance;
    }

    //sql语句
    private string sqlQuery;
    public delegate void CallBack();
   
    /// <summary>
    /// 查询英雄有多少钱
    /// </summary>
    /// <param name=""></param>
    /// <returns></returns>
    public int SeletHeroMoney(string heroName)
    {
        sqlQuery = string.Format("Select PlayerMoney From PlayerInfo Where HeroName='{0}'", heroName);

        object money = SeletSingleData(sqlQuery);

        if (money==null)
        {
            return -1;
        }
        return Convert.ToInt32(money);
    }
   
    /// <summary>
    /// 查询英雄属性
    /// </summary>
    /// <param name="heroName"></param>
    /// <returns></returns>
    public int[] SeletHeroProperties(string heroName)
    {
        sqlQuery =string .Format("Select * From PlayerInfo Where HeroName = '{0}'",heroName);
        List<ArrayList> properties = SeletMultipleData(sqlQuery);

       //定义长度是因为自己知道,其他功能要令处理
        int[] result = new int[2];

        if (properties.Count!=0)
        {
            for (int i = 1; i <= 2  ; i++)
            {
                result[i - 1] = Convert.ToInt32(properties[0][i]);
            }
            return result;
        }
        return null;
    }

    /// <summary>
    /// 查询英雄名称
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    public string SeletHeroName(int index)
    {
        sqlQuery = "Select HeroName From PlayerInfo";
       
        List<ArrayList> heros = SeletMultipleData(sqlQuery);
        
        return heros[index][0].ToString();
    }

    /// <summary>
    /// 查询英雄装备列表
    /// </summary>
    /// <param name="heroName"></param>
    /// <param name="call"></param>
    /// <returns></returns>
    public string SelectHeroEquips(string heroName, CallBack call)
    {
        sqlQuery =string .Format("Select PlayerEquips From PlayerInfo Where HeroName='{0}'",heroName);

        object result = SeletSingleData(sqlQuery);

        if (result == null)
        {
            call();
           // Debug.Log("没有改英雄!");
            return null;
        }
        return result.ToString();
    }

    /// <summary>
    /// 查询商城所有装备  方便加载
    /// </summary>
    /// <returns></returns>
    public string [] SeletAllShopEquips()
    {
        sqlQuery= "Select * From ShopData";

        List<ArrayList> result = SeletMultipleData(sqlQuery);

        string[] equipNames = new string[result.Count];

        for (int i = 0; i < result.Count; i++)
        {
            //打印所有sql表中shopdata第一列装备名字
            equipNames[i] = result[i][0].ToString();
        }
        return equipNames;
    }


    /// <summary>
    /// 查询装备价格
    /// </summary>
    /// <param name="equipName"></param>
    /// <returns></returns>
    private int SelectEquipPrice(string equipName,CallBack call)
    {
        sqlQuery =string .Format("Select EquipMoney From ShopData Where EquipName='{0}'",equipName);

        object price = SeletSingleData(sqlQuery);

        if (price ==null)
        {
            call();
            //Debug.Log("没有改装备");
        }
        return Convert.ToInt32(price);
    }


    /// <summary>
    /// 查询装备属性信息
    /// </summary>
    /// <param name="equipName"></param>
    /// <returns></returns>
    private int[] SeletEquipProperties(string equipName)
    {
        sqlQuery = string.Format("Select * From ShopData Where EquipName = '{0}'", equipName);

        List<ArrayList> properties = SeletMultipleData(sqlQuery);

        int[] result = new int[2];

        if (properties.Count!=null)
        {
            for (int i = 1; i <=2; i++)
            {
                result[i - 1] = Convert.ToInt32(properties[0][i]);
            }
            return result;
        }
        return null;
    }


    /// <summary>
    /// 设置玩家金钱
    /// </summary>
    /// <param name="heroName"></param>
    /// <param name="newMoney"></param>
    private void SetHeroMoney(string heroName,int newMoney)
    {
        sqlQuery = string.Format("Update PlayerInfo Set PlayerMoney={0} Where HeroName='{1}'", newMoney, heroName);

        JustExecute(sqlQuery);
    }


    /// <summary>
    ///判断玩家是否能花 花费玩家金钱
    /// </summary>
    /// <param name="heroName"></param>
    /// <param name="cost"></param>
    /// <returns></returns>
    private bool CostHeroMoney(string heroName,int cost)
    {
        int heroMoney = SeletHeroMoney(heroName);

        if (heroMoney>=cost)
        {
            SetHeroMoney(heroName, heroMoney - cost);
            return true;
        }
        return false;
    }

    /// <summary>
    /// 给英雄添加装备
    /// </summary>
    /// <param name="heroName"></param>
    /// <param name="equipName"></param>
    public void AddHeroEquip(string heroName,string equipName)
    {
        //查询英雄装备
        string heroEquips = SelectHeroEquips(heroName,null);

        if (heroEquips!=null)
        {
            heroEquips += equipName + "|";
        }
        //跟信道数据库中
        sqlQuery = string.Format("Update PlayerInfo Set PlayerEquips='{0}'", heroEquips);

        JustExecute(sqlQuery);
    }

    /// <summary>
    /// 给英雄添加一个属性
    /// </summary>
    /// <param name="heroName"></param>
    /// <param name="equipName"></param>
    private void AddHeroEquipProperties(string heroName,string equipName)
    {
        //获取英雄属性
        int[] heroProperties = SeletHeroProperties(heroName);
        //获取装备属性
        int[] equipProperties = SeletEquipProperties(equipName);
        //给英雄加buff
        for (int i = 0; i < 2; i++)
        {
            heroProperties[i] += equipProperties[i];
        }
        //更新英雄数据
        sqlQuery = string.Format("Update PlayerInfo Set SpellPower = {0}," +
                                 "DefenceValue={1} Where HeroName='{2}'", heroProperties[0], heroProperties[1], heroName);

        JustExecute(sqlQuery);
    }


    public void BuyEquip(string heroName,string equipName, CallBack call)
    {
        int price = SelectEquipPrice(equipName,null);

        if (!CostHeroMoney(heroName,price))
        {
            call();
            return;
        }

        AddHeroEquipProperties(heroName, equipName);

        AddHeroEquip(heroName, equipName);
    }

}

四、设置商城图片,背包图片

新建两个脚本ShopEquip,BagEquip
新建两个Image设置好大小之后,分别添加ShopEquip(另外添加Button组件),BagEquip。
建一个Resources和Textures文件夹,像这样
在这里插入图片描述


using UnityEngine;
using UnityEngine.UI;
public class BagEquip : MonoBehaviour
{
    private Image _image;

    /// <summary>
    /// 设置装备的图片
    /// </summary>
    /// <param name="equipName"></param>
    public void SetEquipSprite(string equipName)
    {
        //找到Image
        _image = GetComponent<Image>();
        //动态加载图片
        _image.sprite = Resources.Load<Sprite>("Textures/" + equipName);
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ShopEquip : MonoBehaviour
{
    private Image _image;
    private Button _button;

    /// <summary>
    /// 设置装备图片
    /// </summary>
    /// <param name="equiName"></param>
    public void SetEquipSprite(string equipName)
    {
        _image = GetComponent<Image>();
        _button = GetComponent<Button>();

        _image.sprite = Resources.Load<Sprite>("Textures/" + equipName);
       
        _button.onClick.AddListener(() =>
        {
            //买装备的数据库操作
            ShopSqlFrameWork.GetInstance().BuyEquip(
                ShopView.Instance.heroName,
                _image.sprite.name, NoMoney);
            //更新数据库内容到界面
            ShopView.Instance.UpdateView();
        });
    }
    /// <summary>
    /// 没钱了  在这里进行一些弹出界面等操作
    /// </summary>
    private void NoMoney()
    {
        Debug.Log("兄弟没钱了");
    }
}

五、UI显示设置更新数据

在这里插入图片描述
代码并不难,后面的代码比较乱 做了注释

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ShopView : MonoBehaviour
{
    public static ShopView Instance;

    [Header("召唤师名称")]
    public Text heroNameText;
    [Header("英雄属性")]
    public Text[] heroPropertiesText;
    [Header("召唤师金钱")]
    public Text heroMoneyText;
    [Header("背包")]
    public Transform bagTra;
    [Header("商城")]
    public Transform shopTra;

    public string heroName;

    private ShopSqlFrameWork ShopSql;

    private GameObject bagEquipPrefab;
    private GameObject shopEquipPrefab;

    private void Awake()
    {
        Instance = this;
        ShopSql = ShopSqlFrameWork.GetInstance();
    }
    private void Start()
    {
        bagEquipPrefab = GetRes("Prefabs/BagEquip");
        shopEquipPrefab = GetRes("Prefabs/ShopEquip");

        ShopSql.OpenSqlData("ShopData");

        ShowShopEquips();
        UpdateView();
    }
    //程序退出的时候 关闭数据库
    private void OnApplicationQuit()
    {
        ShopSql.CloseSqlData();
    }
    private GameObject GetRes(string path)
    {
        return Resources.Load<GameObject>(path);
    }
    /// <summary>
    /// 加载商店里的所有装备
    /// </summary>
    private void ShowShopEquips()
    {
        string[] names = ShopSql.SeletAllShopEquips();

        for (int i = 0; i < names.Length; i++)
        {
            GameObject resEquips = Instantiate(shopEquipPrefab);

            resEquips.transform.SetParent(shopTra.GetChild(i));

            resEquips.transform.localPosition = Vector3.zero;

            resEquips.transform.localPosition = Vector3.zero;

            resEquips.GetComponent<ShopEquip>().SetEquipSprite(names[i]);
        }
    }
   /// <summary>
   /// 更新界面
   /// </summary>
    public void UpdateView()
    {
        //获取英雄名称
        heroName = ShopSql.SeletHeroName(0);
        //显示名称
        heroNameText.text = heroName;
        //获取英雄属性
        int[] heroProperties = ShopSql.SeletHeroProperties(heroName);
        //显示英雄属性
        for (int i = 0; i <2; i++)
        {
            heroPropertiesText[i].text = heroProperties[i].ToString();
        }
        //获取金钱
        int heroMoney = ShopSql.SeletHeroMoney(heroName);
        //显示金钱
        heroMoneyText.text = heroMoney.ToString();
        //获取英雄装备列表
        string equips = ShopSql.SelectHeroEquips(heroName,null);

        //清空背包的所有装备
        for (int i = 0; i < bagTra.childCount - 1; i++)
        {
            if (bagTra.GetChild(i).childCount > 0)
            {
                //销毁原来的装备图片
                Destroy(bagTra.GetChild(i).GetChild(0).gameObject);
            }
        }

        //获取每个装备的名称
        string[] equipNames = equips.Split('|');

        for (int i = 0; i < equipNames.Length; i++)
        {
            //如果装备名称不正常,跳过
            if (string.IsNullOrEmpty(equipNames[i]))
                continue;
            //生成背包装备
            GameObject crtEquip = Instantiate(bagEquipPrefab);
            //设置父物体
            crtEquip.transform.SetParent(bagTra.GetChild(i));
            //设置相对坐标
            crtEquip.transform.localPosition = Vector3.zero;
           
            //设置当前装备的图片
            crtEquip.GetComponent<BagEquip>().SetEquipSprite(equipNames[i]);
        }
    }
}


好啦大体功能就实现了 ,之后有时间继续完善,比如卖装备,装备限制等功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值