目录
1.初衷
2.插件
3.好友排行榜
4.注意事项
5.个人作品
1.初衷
有了Unity转换微信小游戏的插件后,就想着做一款自己的小游戏,跑了一遍开发流程,最终也顺利上线;过程中碰到不少各种各样的坑,记录一下,也许能帮到一些想做的朋友。
书写顺序随心所欲,本文先讲好友排行榜
2.插件
官方插件链接
3.好友排行榜
官方有排行榜的示例(如下图),大家有空去下载看一下,很多博客都有做详情介绍,就不多做介绍了
这里主要讲一下多榜单怎么实现(如下图所示:记录两个不同的数据在榜中显示)
官方插件提供的仅支持单榜,但是多榜单要怎么做呢?
先看一下插件导入后的层次结构,如下图:
这里open-data即为显示排行榜数据的开放数据域模块,我们需要改动以下几个地方(仅做参照):
1)index.js:
A.MessageType新增4个枚举
// setUserRecord(RANK_KEY, Math.ceil(Math.random() * 1000)); // 屏蔽测试数据
const MessageType = {
WX_RENDER: 'WXRender',
WX_DESTROY: 'WXDestroy',
SHOW_FRIENDS_RANK: 'showFriendsRank',
SHOW_GROUP_FRIENDS_RANK: 'showGroupFriendsRank',
SET_USER_RECORD: 'setUserRecord',
// -------------------------------- < 新增4个显示枚举 > --------------------------------
SHOW_FRIENDS_CHALLENGE_RANK: 'showFriendsChallengeRank',
SHOW_FRIENDS_HIDE_RANK: 'showFriendsHideRank',
SHOW_GROUP_FRIENDS_CHALLENGE_RANK: 'showGroupFriendsChallengeRank',
SHOW_GROUP_FRIENDS_HIDE_RANK: 'showGroupFriendsHideRank',
// -------------------------------- < 新增4个显示枚举 > --------------------------------
};
B.main函数改为如下
function main() {
wx.onMessage((data) => {
console.log('[WX OpenData] onMessage', data);
if (typeof data === 'string') {
try {
// eslint-disable-next-line no-param-reassign
data = JSON.parse(data);
}
catch (e) {
console.error('[WX OpenData] onMessage data is not a object');
return;
}
}
switch (data.type) {
// 来自 WX Unity SDK 的信息
case MessageType.WX_RENDER:
initOpenDataCanvas(data);
break;
// 来自 WX Unity SDK 的信息
case MessageType.WX_DESTROY:
Layout.clearAll();
break;
// 下面为业务自定义消息
case MessageType.SHOW_FRIENDS_RANK:
renderFriendsRank(1);
break;
case MessageType.SHOW_FRIENDS_CHALLENGE_RANK:
renderFriendsRank(2);
break;
case MessageType.SHOW_FRIENDS_HIDE_RANK:
renderFriendsRank(3);
break;
case MessageType.SHOW_GROUP_FRIENDS_RANK:
renderGroupFriendsRank(data.shareTicket, 1);
break;
case MessageType.SHOW_GROUP_FRIENDS_CHALLENGE_RANK:
renderGroupFriendsRank(data.shareTicket, 2);
break;
case MessageType.SHOW_GROUP_FRIENDS_HIDE_RANK:
renderGroupFriendsRank(data.shareTicket, 3);
break;
case MessageType.SET_USER_RECORD:
let extra = {challenge:data.challenge, hide:data.hide};
setUserRecord(RANK_KEY, data.score, extra);
break;
default:
console.error(`[WX OpenData] onMessage type 「${data.type}」 is not supported`);
break;
}
});
}
2)data/index.js:
A.getWxGameData函数改为如下
function getWxGameData(item) {
let source;
try {
source = JSON.parse(item.KVDataList[0].value);
}
catch (e) {
source = {
wxgame: {
score: 0,
update_time: getCurrTime(),
},
};
}
// return source.wxgame;
return source;
}
B.以下3个函数新增参数showType及相应的改动,详见如下
function rankDataFilter(res, showType = 1, selfUserInfo = false) {
const data = (res.data || []).filter((item) => item.KVDataList && item.KVDataList.length);
return data
.map((item) => {
let data = getWxGameData(item);
console.log('[WX OpenData] rankDataFilter() data: ', data);
// const { score, update_time: updateTime } = data.wxgame.score;
let score = data.wxgame.score;
switch (showType)
{
case 1:
score = data.wxgame.score;
break;
case 2:
score = data.challenge;
break;
case 3:
score = data.hide;
break;
default:
console.error(`[WX OpenData][Error] rankDataFilter() showType: ${showType} is not case!`);
}
const updateTime = data.wxgame.update_time;
console.log(`[WX OpenData] rankDataFilter() score: ${score}, showType: ${showType}`);
item.score = score;
item.update_time = updateTime;
/**
* 请注意,这里判断是否为自己并不算特别严谨的做法
* 比较严谨的做法是从游戏域将openid传进来,示例为了简化,简单通过 avatarUrl 来判断
*/
if (selfUserInfo && selfUserInfo.avatarUrl === item.avatarUrl) {
item.isSelf = true;
}
return item;
})
// 升序排序
.sort((a, b) => b.score - a.score);
}
/**
* 获取好友排行榜列表
* API文档可见:https://developers.weixin.qq.com/minigame/dev/api/open-api/data/wx.getFriendCloudStorage.html
*/
export function getFriendRankData(key, showType, needMarkSelf = true) {
console.log('[WX OpenData] getFriendRankData with key: ', key);
return getFriendCloudStorage({
keyList: [key],
}).then((res) => {
console.log('[WX OpenData] getFriendRankData success: ', res);
if (needMarkSelf) {
getSelfPromise = getSelfPromise || getSelfData();
return getSelfPromise.then(userInfo => rankDataFilter(res, showType, userInfo));
}
return rankDataFilter(res, showType);
});
}
/**
* 获取群同玩成员的游戏数据。小游戏通过群分享卡片打开的情况下才可以调用。该接口需要用户授权,且只在开放数据域下可用。
* API文档可见: https://developers.weixin.qq.com/minigame/dev/api/open-api/data/wx.getGroupCloudStorage.html
*/
export function getGroupFriendsRankData(shareTicket, key, showType, needMarkSelf = true) {
console.log('[WX OpenData] getGroupFriendsRankData with shareTicket and key: ', shareTicket, key);
return getGroupCloudStorage({
shareTicket,
keyList: [key],
}).then((res) => {
console.log('[WX OpenData] getGroupFriendsRankData success: ', res);
if (needMarkSelf) {
getSelfPromise = getSelfPromise || getSelfData();
return getSelfPromise.then(userInfo => rankDataFilter(res, showType, userInfo));
}
return rankDataFilter(res, showType);
});
}
3)render/styles/friendRank.js:用来设置图片的显示位置、长宽、圆角等;这里可以参照原有改动
4)render/tpls/friendRank.js:用来设置显示的xml,配合上面一条
export default function anonymous(it, showType) {
let out = '<view class="container" id="main"> <view class="rankList"> <scrollview class="list" scrollY="true"> ';
const arr1 = it.data;
if (arr1) {
let item;
let index = -1;
const l1 = arr1.length - 1;
while (index < l1) {
item = arr1[(index += 1)];
let rankIndex = index + 1;
// let name = item.nickname + item.nickname + item.nickname;
let name = item.nickname;
let itemIconIndex = showType;
out += ` <view class="listItem"> <image src="open-data/render/image/rankBg.png" class="rankBg"></image> <text class="rankIndex" value="${rankIndex}"></text>`;
if (rankIndex <= 3)
out += `<image class="rankMark" src="open-data/render/image/ui_rank${rankIndex}.png"></image>`;
out += ` <image class="rankAvatarBg" src="open-data/render/image/rankAvatar.png"></image> <image class="rankAvatar" src="${item.avatarUrl}"></image> <text class="rankName" value="${name}"></text> <text class="rankScoreVal" value="${(item.score || 0) + (itemIconIndex > 1 ? ' 关' : '')}"></text>`;
if (itemIconIndex == 1)
out += `<image class="rankItemIcon1" src="open-data/render/image/ui_item1.png"></image>`;
// else if (itemIconIndex == 2)
// out += `<image class="rankItemIcon2" src="open-data/render/image/ui_item2.png"></image>`;
out += `</view>`;
}
}
out += ' </scrollview> </view></view>';
return out;
}
5)render/image:排行榜的显示图片,配合以上两条
6)Unity端调用:
[System.Serializable]
public class OpenDataMessage
{
public string type;
public string shareTicket;
public int score;
public int challenge;
public int hide;
}
public void SetFriendRankData(int score, int challenge, int hide)
{
OpenDataMessage msgData = new OpenDataMessage();
msgData.type = "setUserRecord";
msgData.score = score;
msgData.challenge = challenge;
msgData.hide = hide;
string msg = LitJson.JsonMapper.ToJson(msgData);
WX.GetOpenDataContext().PostMessage(msg);
}
4.注意事项
1)可以在Unity转换为小游戏后,在微信开发者工具里直接改open-data里的内容,便于运行查看;调整完成后,记得把open-data文件夹替换Unity里WX-WASM-SDK-V2文件夹下的同名目录
2)要显示开放数据域的内容,需要用到小程序插件:开放数据域渲染库,记得添加
3)game.json中添加如下插件
"Layout" : {
"version" : "1.0.7",
"provider" : "wx7a727ff7d940bb3f",
"contexts" : [
{
"type" : "openDataContext"
}
]
}
4)每次更新小程序转换插件时,一般来说open-data不用导入(不然还得自己比对,把改动的内容找回来)