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

Posted Zireael2019

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Unity C++] 前端+后端商城和背包系统相关的知识,希望对你有一定的参考价值。

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

基于Unity前端和C++后端实现的联网商城和背包系统,玩家登录后从服务器拉取自身背包和金钱数据,能够从商城购买物品并将物品加入自身背包,玩家退出后,背包信息存储在服务器中

  • 前端:使用Unity实现商城和背包UI,采用MVC模式组织数据的获取、存储和展现
  • 后端:基于C++ Libuv实现网络通信,运行于Windows平台,使用ProtoBuf传输数据
  • 实现玩家登录、玩家数据拉取、商城购买逻辑,利用版本号实现商城的限购

网络通信

在执行业务逻辑前,需要建立客户端和服务器的底层网络链接(TCP)

自定义的协议内容:“TC”(两字节)+包体长度(两字节)+操作码CMD(两字节)+包体内容

其中包体内容通过ProtoBuf编解码

基本的连接建立和收发消息流程如下

业务逻辑

建立底层网络连接后便可处理业务逻辑了。业务逻辑主要有登录逻辑和商城逻辑两大部分。

玩家登录逻辑

登录请求中有玩家ID和密码,登录回复中有登录结果,成功/失败原因,玩家数据

商城逻辑

通过使用版本号来减少商城加载操作的同步量。

服务器每次接受到一次成功的购买操作就会递增服务器的版本号,客户端在加载商城时若发送的版本号与客户端相同则无需发送商城完整信息;同样,当客户端接收到购买成功回复时,若服务器版本号之比自身版本号大一表明这段时间内只有自己进行了购买,因此只需自己更新商店信息而无需重新想服务器请求,否则应想服务器重新请求商城信息

服务器实现

PlayerMgr

服务器的PlayerMgr类负责处理玩家相关业务逻辑,包括玩家的创建、登录和玩家信息的存取与维护

struct Player 
    string PlayerID;
    string Password;
    string Name;
    int money;
    map<int, ShopItem*> bagItems;
;

class PlayerMgr 
public:
    PlayerMgr();
    ~PlayerMgr();

    bool init();
    bool un_init();

    // 处理用户请求
    bool player_login(uv_tcp_t* client, const PlayerLoginReq* req);
    bool player_create(uv_tcp_t* client, const PlayerCreateReq* req);
    
    Player* find_player(string playerID);

    // 有链接断开
    bool on_client_close(uv_tcp_t* client);

    // 背包
    bool changeBagItems(uv_tcp_t* client, const ShopItem* Item, int num = 1);
private:
    // 从文件中读取和存储玩家信息
    int _load_player(string playerID, PlayerSaveData* playerData);
    bool _save_player(const Player* player);
public:
    map<uv_tcp_t*, Player*> m_playerMap;
;

Player结构体用于存储玩家信息,包括玩家ID,昵称,密码和背包数据

PlayerMgr类中有player_loginplayer_create负责处理玩家登录和创建请求,m_playerMap维护了当前登录的玩家信息,用于防止玩家重复登录和更新玩家背包金钱等业务逻辑需要

Shop

Shop类负责处理商城业务逻辑,包括加载和购买请求等

class Shop

public:
	Shop();
	~Shop();

	// 初始化,从json文件加载商品到map
	bool init();
	// 存储商品信息到json文件,清理map内存
	bool un_init();

	//处理用户请求
	bool shop_load(uv_tcp_t* client, const ShopLoadReq* req);
	bool shop_buy(uv_tcp_t* client, const ShopBuyReq* req);
private:

	map<int, ShopItem*> _shopItemsMap;

	int _buySequence;

	// 解析json文件,并写入map
	int _parseShopCfg(const char* const monitor);
	// 从json文件中加载商品到map
	bool _load_items();
	// 存储商品map到json文件
	bool _save_items();
;

_shopItemsMap维护了当前商城列表,_buySequence即商城版本号

客户端实现

客户端采用MVC模式组织商城数据的获取、存储和展现

  • View层由UI和挂载在UI上的脚本组成

  • Controller为单例负责解耦数据存储和数据展示,其中方法有的注册在UI组件中,有的注册在网络组件中

    public class ShopController : MonoBehaviour
    
        private Shop _shop;
        private Bag _bag;
    
        private ShopPanel _shopView;
        private BackpackPanel _bagView;
    
        private Network _network;
    	
        ...
    
    

    可以看到Controller中包含View层和Module层的引用,解耦数据展示和数据存储,Network用于网络通信

  • Module分为Shop和Bag负责存储商城和背包数据以及处理业务逻辑

商城和背包业务逻辑流程均由上面七步操作组成

背包逻辑

背包的业务逻辑不牵扯网络通信,因此较为简单

  1. 用户点击背包按钮
  2. 回调注册在按钮中的Controller.UpdateBagView()
  3. Controller调用Bag.getBagItems()
  4. 无需处理,直接返回背包数据
  5. Bag返回背包数据
  6. Controller调用View.Update()显示背包信息
// 注册在背包按钮中
public void UpdateBagView()

	_bagView.ShowItems(GetBagItems());

// 从Model层获得数据
public List<ShopItem> GetBagItems()

	return _bag.GetBagItems();

商城加载逻辑

商城加载过程分为发送请求和处理回包两部分

  • 请求商店

    1. 点击购买按钮
    2. 回调注册在按钮中的Controller.LoadShopItems()
    3. Controller调用Shop.LoadShop()获取请求包
    4. 构造请求包并返回
    5. 返回请求包
    6. 调用网络组件发送商城加载请求
    // 注册在商店按钮中
    public void LoadShopItems()
    
    	ShopLoadReq req = _shop.LoadShop();
    	_network.SendMsg((int)CLIENT_CMD.ClientShopLoadReq, req);
    
    
  • 处理回包

    1. 收到商城加载回包
    2. 回调注册在网络组件中的Controller.OnShopLoadRsp()
    3. Controller调用Shop.LoadShopRsp()处理请求包
    4. 根据回包更新本地商城数据
    5. Controller调用GetShopItems(), _bag.GetPlayerMoney()获得商店数据和玩家金钱
    6. 更新View
    public void OnShopLoadRsp(int cmd, IMessage msg)
    
    	// 处理返回包
    	_shop.LoadShopRsp((ShopLoadRsp)msg);
    	// 更新View
    	UpdateShopView();
    
    public void UpdateShopView()
    
    	_shopView.ShowItems(GetShopItems(), _bag.GetPlayerMoney());
    
    

购买逻辑

购买逻辑同样分为网络请求和处理回包两部分

  • 请求商店
    1. 点击购买按钮
    2. 回调注册在按钮中的Controller.Buy()
    3. Controller调用Shop.Buy()获取请求包
    4. 自检成功后则构造并返回请求包,否则返回null
    5. 返回请求包
    6. 调用网络组件发送商城购买请求
  • 处理回包
    1. 收到商城购买回包
    2. 回调注册在网络组件中的Controller.OnShopBuyRsp()
    3. Controller调用Bag.BuyRsp()处理请求包
    4. 根据回包更新本地商城数据和背包数据
    5. Controller调用GetShopItems(), _bag.GetPlayerMoney()获得商店数据和玩家金钱
    6. 更新View

效果展示

https://www.bilibili.com/video/BV1pY4y1M7RQ

谷粒商城学习——P16人人开源搭建后台管理系统

在码云上搜索人人开源,使用renren-fast(后端)、renren-fast-vue(前端),renren-security (前后端不分离),renren-generator 代码生成器

使用git控制台克隆后端和前端项目

git clone https://gitee.com/renrenio/renren-fast.git
git clone https://gitee.com/renrenio/renren-fast-vue.git

 

 

 renren-fast(后端)删掉git目录,并放到gulimall项目根目录下,然后加入到pom.xml中

 

这时reren-fast项目是没有作为springboot项目的,要执行build module

 

 

 将db/mysql.sql粘贴到gulimll_admin数据库中执行

修改配置文件,指向虚拟机gulimall数据库

 

 指定jdk

 

 

运行RenrenApplication

运行至8080端口

 

以上是关于[Unity C++] 前端+后端商城和背包系统的主要内容,如果未能解决你的问题,请参考以下文章

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

设计精良的网上商城系统,包括前端、后端、数据库、负载均衡、数据库缓存、分库分表、读写分离、全文检索、消息队列等,使用SpringCloud公司框架,基于Java语言开发。该项目可部署到服务器上,不断完

谷粒商城学习——P16人人开源搭建后台管理系统

Unity游戏开发:背包系统的实现

Siki_Unity_3-3_背包系统

东京商城主页中部商品分类和轮播图代码的编写