一个SDK管理器
游戏若要在渠道上架,通常需要接入渠道方提供的SDK,如用户系统、支付系统等等。虽然市面上已有许多打包工具(AnySDK,U8SDK)让游戏开发者可以快速接入各个渠道,但是因为不见得所有的渠道都能得到支持,游戏开发者仍然需要自己去设计代码架构,可以更方便地接入SDK。
我自己用TypeScript写了一个简易的SDK管理器。它肯定是丑陋并且不完善的,但是至少提供了一个原型;它与具体的游戏逻辑分离,又可以适当扩展;这样,当我下一次开始新项目的时候就不需要重复造轮子了。
设计
单例类SDKManager
负责管理所有SDK插件。用户通过getUserPlugin()
、getIAPPlugin()
方法获取用户插件、支付插件。
SDKManager.getInstance().getUserPlugin().login((code, msg) => {
// ...
});
SDKManager.getInstance().getIAPPlugin().payForProduct(productInfo, (code, msg) => {
// ...
});
接入渠道SDK的时候,需要按需求继承UserPlugin
、IAPPlugin
等等,并重写它们的方法。
在游戏启动之后的适当时机,执行以下代码完成初始化:
const manager = SDKManager.getInstance();
manager.setChannel(999);
manager.init();
manager.loadAllPlugins();
部分实现
/**
* 渠道代理,每个渠道应当继承ChannelAgent
*/
export class ChannelAgent {
/**
* Override this.
* 通常是在这个方法里加载渠道的库
*/
public init() {
}
/**
* Override this.
* 渠道代理自己决定要注册哪些插件
*/
public loadAllPlugins() {
SDKManager.getInstance().registerUserPlugin(new UserPlugin);
SDKManager.getInstance().registerIAPPlugin(new IAPPlugin);
}
}
export class SDKManager {
private userPlugin: UserPlugin; // 用户插件
// Other plugins...
private currentChannelID: ChannelID = ChannelID.NONE; // 当前渠道ID
private agent: ChannelAgent; // 渠道代理,每个渠道应当继承ChannelAgent
/**
* 设置当前渠道
*/
public setChannel(id: ChannelID) {
this.currentChannelID = id;
}
public init() {
switch (this.currentChannelID) { // 根据当前渠道ID,选择加载对应的代理
case ChannelID.QUICK:
{
const m = require('./registers/RegisterQuick');
this.agent = new m.QuickAgent();
}
break;
// Other channels...
default:
console.log(`WARNING: no channel`);
this.agent = new ChannelAgent();
break;
}
this.agent.init();
}
/**
* 加载所有插件
*/
public loadAllPlugins() {
this.agent.loadAllPlugins();
}
public getUserPlugin(): UserPlugin {
return this.userPlugin;
}
}
export class UserPlugin {
/**
* Override this
*/
public login(callback?: (code: UserActionResultCode, msg: any) => void) {
}
// Other methods...
}
假设现在要接入一个名为Foo的渠道,可以创建一个脚本registers/RegisterFoo.ts
,代码内容如下:
export class FooAgent extends ChannelAgent {
public init() {
// 加载Foo提供的代码库
}
public loadAllPlugins() {
SDKManager.getInstance().registerUserPlugin(new FooUserPlugin);
SDKManager.getInstance().registerIAPPlugin(new FooIAPPlugin);
}
}
export class FooUserPlugin extends UserPlugin {
// ...
}
export class FooIAPPlugin extends IAPPlugin {
// ...
}
最后别忘了修改SDKManager
的init
方法,插入:
case ChannelID.FOO:
{
const m = require('./registers/RegisterFoo');
this.agent = new m.FooAgent();
}
break;
全部代码
见仓库XDSDK。