UWA Pipeline 使用前的准备工作
UWA Pipeline 使用前的准备工作
Pipeline1 简介
后面简称为 ppl
ppl 是集合了目前 UWA所有产品功能为一身的工具,可以用很小的成本,从一些真机自动化等机械性重复性劳动中解放出来,如:自动化性能测试、可靠性真机测试等等,当然里面功能很多,如果不了解 ppl,推荐去官网1 了解一下具体功能,或者找 UWA 的工作人员申请一下试用
目前整体使用下来,对我们项目而言,最重要的是解放重复性劳动,以及整体项目的性能把控上。比如在还没有跑 GOT 性能测试之前,我就可以精准预测游戏性能瓶颈到底在什么地方,这种对项目整体心中有数,会让人感觉非常靠得住
目标 & 背景
- Airtest 调用 GM 指令
- SDK 动态剔除
老样子,我们还是从需求和背景开始,由于我们游戏目前的限制,需要在自动化测试开始之前,先执行一些游戏框架中的代码,才能开始进行测试,再加上我们游戏中使用的 GM 工具是 IngameDebugConsole2,所以必须要解决代码复用问题
除此之外,在我们正常打包时,仅在自动化性能测试这个场景下才会加载 UWA 相关的代码,普通 dev 并不会,而且在 Release 环境下,UWA 代码和 IngameDebugConsole2 相关代码也需要完全裁剪,因此 SDK 动态剔除也是很有必要的
具体实现
这里非常感谢 UWA 的工程师解答了我接入时遇到的问题,节省了我不少时间~
首先说一下这里的过程,我们需要在 Airtest 中的 py 脚本直接调用 C# 的代码,而两者之间的通讯用到了 Poco3 组件的 rpc 功能,根据我们传入的字符串对执行内容进行分发
这里必须要吐槽一下 Poco3 rpc 的设计,最开始看到 rpc attribute 我以为框架内部已经做了自动扫描,没想到居然还需要手动添加指令,这样我们每增加一个指令都需要入侵 SDK 的源码
那么我们第一个要解决的问题就是现有 Poco3 设计缺陷问题
Poco 事件分发
这里思路也很简单,需要注意的是,我们这里还有 SDK 动态剔除的问题需要解决,那么需要做到只要这个代码被打进这个包,业务逻辑不需要做任何额外的事情,这个 SDK 就可以自动开启,这样就是一个懂事的 SDK,自己管自己
public static class SDKSelfInit
{
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
private static void _Init()
{
EventSystem.Instance.Add(typeof(SDKSelfInit).Assembly);
}
}
紧接着我们定义一个从业务逻辑分发的 GMCodeEvent 和 AfterUpdateCheck,在合适的时机对 SDK 具体的逻辑进行初始化
namespace EventType
{
public struct AfterUpdateCheck
{
}
public struct GMCodeEvent
{
public string command;
}
}
这里的 AfterUpdateCheck 调用时,会对 SDK 进行初始化,如 GM 工具的加载、UWA 的初始化等等,而另一个 GMCodeEvent,作为通用的 GM 指令调用实现,这里特指 Poco 调用 GM 指令
接着我们要对这两个事件写具体的实现,没啥可说的,代码也很简单,主要是 command 要转给 IngameDebugConsole2
public class AfterUpdateCheck_InitPoco : AEvent<EventType.AfterUpdateCheck>
{
protected override UniTask Run(EventType.AfterUpdateCheck args)
{
// 这里可以考虑增加强制验证
// if(!valid) return;
var go = new GameObject();
go.AddComponent<PocoManager>();
Object.DontDestroyOnLoad(go);
return UniTask.CompletedTask;
}
}
public class PocoEvent_Handle : AEvent<EventType.GMCodeEvent>
{
protected override UniTask Run(EventType.GMCodeEvent args)
{
DebugLogConsole.ExecuteCommand(args.command);
return UniTask.CompletedTask;
}
}
最后我们需要在 Poco3 源码中增加执行 GM 事件的注册代码,这里也是唯一一处我们需要入侵 SDK 的地方
public class PocoManager : MonoBehaviour
{
void Awake()
{
// ...
rpc.addRpcMethod("Publish", Publish);
// ...
}
// 我不理解这个 RPC 的 attribute 到底是干嘛的
// 为了保持一致还是加上吧
[RPC]
private object Publish(List<object> param)
{
EventSystem.Instance.Publish(new EventType.GMCodeEvent {command = param[0] as string}).ForgetLog("Poco");
return param[0];
}
}
Airtest 调用
首先我们将如下代码写在 UWA.py
脚本中,作为一个项目标准实现
@sync_wrapper
def PublishGM(pocoHdl, command):
# 此处 Publish 对应的就是 PocoManager 中的 Publish 函数
return pocoHdl.agent.c.call("Publish", command)
具体调用方式如下
# 导入UWA模块
from UWA import *
poco = UnityPoco()
# 这里的 GM 指令就和 IngameDebugConsole 的调用保持一致了
# 比如你有一个名为 test 的指令,包含一个参数 int a
# 那么此时填写 "test 1" 即可
command=PublishGM(poco, "GM指令")
log(command)
这样我们就打通了从 python 直接调用项目中现有 GM 指令的整体流程,既保证对 SDK 入侵较小、方便扩展的同时,也完全利用了目前 GM 指令的所有设计,如果 Poco3 自己实现了扫描,我们连代码都不需要侵入,我这也是懒得写扫描,用最小成本先实现功能
SDK 动态剔除
动态剔除的原理非常简单,根据打包参数在指定目录名追加 ~
即可,或者从外部拷入、内部删除等方案都是可以的,这里我们项目使用的方案就是追加 ~
但是无论哪种我们都需要对目录进行规划,下方为我们当前目录规划的参考:
Plugins/DynamicSDK
# GM 的原生代码
├── IngameDebugConsole
├── IngameDebugConsole.meta
├── Custom.SDK
# GM 的初始化等
│ ├── IngameDebugConsole
│ ├── IngameDebugConsole.meta
│ ├── Custom.SDK.asmdef
│ ├── Custom.SDK.asmdef.meta
# Poco 的初始化等
│ ├── Poco
│ ├── Poco.meta
# 动态 SDK 自启代码
│ ├── SDKSelfInit.cs
│ ├── SDKSelfInit.cs.meta
# UWA 的初始化等
│ ├── UWA
│ ├── UWA.meta
├── Custom.SDK.meta
# Poco 的原生代码
├── Poco
├── Poco.meta
# SDK 中需要动态加载的资源
├── Res
# GM Prefab 存放位置
│ ├── IngameDebugConsole
│ └── IngameDebugConsole.meta
├── Res.meta
# UWA 的原生代码
├── UWA
└── UWA.meta
按照这个规划,我们需要对如下三个目录进行动态剔除
- Assets/Plugins/DynamicSDK
- Assets/Plugins/DynamicSDK/Custom.SDK
- Assets/Plugins/DynamicSDK/Res
剩下的实现过程就非常简单了,根据参数判断是否存在,然后改名即可
在具体实现时,我们碰到一个问题,GOT 并不支持安卓 29~30,而切换时,需要手动点一下 UWA 提供的工具,才可以打包
适配 uwa.aar
这里我们需要用到如下命令
unzip uwa.aar -d tempFolder
# 修改文件后,重新打回 aar
jar cvf new-uwa.aar -C tempFolder/ .
把 AndroidManifest.xml 最后的 application 修改一下即可
<application>
<service
android:name="com.uwa.uwascreen.CaptureScreenService"
android:enabled="true" />
</application>
最后
这样我们就完成了 ppl 针对 GOT 自动化的前期准备工作,更具体的 ppl 使用后续会开新的文章进行介绍
参考
- 感谢你赐予我前进的力量