news 2026/6/19 16:49:47

WEditor:移动端UI自动化测试的可视化利器与工程实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
WEditor:移动端UI自动化测试的可视化利器与工程实践

1. 项目概述:为什么WEditor是移动端UI测试的“瑞士军刀”?

如果你正在为移动端应用的UI自动化测试发愁,面对海量控件、复杂交互和频繁的版本迭代,手动测试早已力不从心,而传统的自动化框架又显得笨重且学习曲线陡峭,那么WEditor的出现,可能就是那个让你眼前一亮的“终极解决方案”。它不是一个全新的编程语言或框架,而是一个基于Python的、专门为移动端(尤其是Android)UI自动化设计的强大工具集和可视化编辑器。简单来说,WEditor让你能用一种更直观、更高效的方式,去定位、操作和断言应用界面上的元素,从而构建稳定可靠的自动化测试脚本。

我第一次接触WEditor是在一个电商App的回归测试项目中。当时我们团队被每周数次的发版节奏压得喘不过气,手工测试覆盖不全,而用Appium写脚本又经常因为控件属性变化导致脚本大面积失效,维护成本极高。直到尝试了WEditor,它的实时控件树查看、坐标录制、以及强大的属性定位能力,彻底改变了我们的工作流。它就像一个连接了你的电脑和手机屏幕的“桥梁”,让你能直接“看到”并“指点”手机上的任何元素,然后自动生成可执行的代码。这不仅大幅提升了脚本编写的效率,更重要的是,它让测试脚本的健壮性上了一个台阶。无论是对于刚入门自动化测试的新手,还是寻求提效的老手,WEditor都提供了一个从探索、录制到脚本生成和维护的完整闭环工具链。

2. WEditor核心优势与工作原理深度拆解

2.1 核心优势:告别“盲人摸象”式的脚本开发

在传统UI自动化中,最令人头疼的环节莫过于元素定位。开发者需要反复查看应用源码或使用UIAutomatorViewer等工具抓取页面快照,然后猜测控件的resource-idxpathclass等属性。这个过程如同“盲人摸象”,效率低下且极易出错,一旦UI微调,定位就可能失效。

WEditor的核心优势在于其**“所见即所得”的可视化交互能力**。它通过ADB(Android Debug Bridge)与设备实时通信,动态获取并渲染出当前屏幕的完整控件层级树(类似于Chrome开发者工具中的Elements面板)。你可以直接在电脑上点击这个控件树中的任意节点,WEditor会高亮显示手机屏幕上对应的UI元素,并列出该元素所有可用的属性(如textresource-idboundsclass等)。你可以即时测试不同的定位策略,并一键生成对应的Python代码(基于uiautomator2库)。这直接将元素定位从“猜测”变成了“验证”,准确率和效率成倍提升。

另一个显著优势是uiautomator2的深度集成与增强uiautomator2是Google官方UIAutomator测试框架的Python封装,性能稳定,但原生API较为底层。WEditor在其之上构建了更友好的高层抽象和实用工具。例如,它提供了强大的“坐标录制”功能,你只需在手机屏幕上手动操作一遍,WEditor就能记录下你的点击、滑动、输入等动作序列,并转换为代码。这对于快速生成冒烟测试或探索性测试的脚本初稿极其有用。

2.2 工作原理:三层架构实现无缝衔接

理解WEditor的工作原理,能帮助我们在遇到问题时更快地排查。其架构可以简化为三层:

  1. 设备连接层:基于ADB。WEditor启动时,会通过ADB命令连接指定的Android设备或模拟器。这是所有操作的基础。确保ADB环境配置正确、设备已开启USB调试模式是使用WEditor的前提。

  2. 服务与通信层:WEditor会在设备上安装一个辅助的ATX代理应用(通常是一个测试辅助APK)。这个代理应用负责在设备端运行,监听来自电脑端WEditor的指令,并调用设备本身的UIAutomator服务来获取UI信息(控件树)和执行操作(点击、滑动等)。电脑端和设备端通过HTTP协议进行JSON-RPC通信。

  3. 应用与展示层:即我们在电脑上看到的WEditor图形界面(GUI)或命令行界面。GUI是其主要形态,它接收来自设备端的控件树数据,渲染成可交互的树状图;同时将用户在界面上的操作(如点击某个定位器)转换为指令,通过通信层发送给设备执行。

注意:首次连接一台新设备时,WEditor通常会自动推送并安装所需的ATX代理APK。如果遇到连接成功但无法获取控件树的情况,很可能是代理APK安装失败或权限未授予,需要检查设备上的相关提示。

3. 从零开始:WEditor环境搭建与核心功能实操

3.1 环境准备与安装避坑指南

WEditor基于Python,因此第一步是确保有一个Python环境(建议3.7及以上版本)。安装过程本身很简单,一条pip命令即可:

pip install weditor

但这里有几个实操中极易踩坑的地方:

  • 坑点一:网络超时与镜像源。直接使用官方PyPI源下载可能会很慢甚至失败。务必使用国内镜像源加速。我个人的习惯是:

    pip install weditor -i https://pypi.tuna.tsinghua.edu.cn/simple
  • 坑点二:依赖冲突。WEditor依赖uiautomator2等库,如果你本地已有其他自动化测试框架(如老版本的Appium),可能会存在库版本冲突。最佳实践是使用虚拟环境(Virtual Environment)。在项目目录下:

    # 创建虚拟环境 python -m venv venv # 激活(Windows) venv\Scripts\activate # 激活(Mac/Linux) source venv/bin/activate # 然后在虚拟环境中安装weditor pip install weditor -i https://pypi.tuna.tsinghua.edu.cn/simple

    这样可以保证每个项目的依赖独立,互不干扰。

  • 坑点三:ADB版本与设备识别。确保你的ADB版本不是太旧,并且设备能被正确识别。连接手机后,在命令行执行adb devices,应该能看到你的设备序列号后面显示device,而不是unauthorized。如果是后者,需要在手机上弹出的“允许USB调试”对话框中点击确认。

3.2 启动与连接:你的第一个WEditor会话

安装成功后,在命令行(确保已在虚拟环境中)输入:

python -m weditor

这条命令会启动WEditor的HTTP服务,并自动在你的默认浏览器中打开它的Web界面(通常是http://localhost:17310)。这个基于Web的GUI是它的操作核心。

首次打开界面,你会看到一个连接设备的输入框。这里通常有两种方式:

  1. 自动连接:如果只有一台设备通过ADB连接,直接点击“连接”即可。
  2. 手动指定:如果有多台设备,需要在输入框中填入设备的序列号(通过adb devices获取)。

连接成功后,界面会分为几个主要区域:顶部的操作工具栏、左侧的实时控件树、右侧的属性面板和代码生成区,以及中央的手机屏幕镜像(可能需要手动点击“刷新”或“Dump Hierarchy”来获取当前页面)。

3.3 核心功能实操:定位、录制与断言

1. 元素定位与探查:这是最常用的功能。点击“刷新”按钮获取当前页面的控件树。在左侧树状图中,你可以展开层层节点,找到目标元素。点击某个节点,右侧属性面板会显示其所有属性,同时手机屏幕上对应的UI元素会被一个红色框高亮(确保“显示点击位置”选项已开启)。

  • 定位策略选择:在属性面板下方,WEditor提供了多种定位器生成选项,如ID(对应resource-id)、XPATHTEXT等。你可以点击“复制”按钮,直接得到像d(resourceId=“com.example:id/login_button”).click()这样的代码片段。
  • 实操心得:优先使用resource-id,因为它通常是唯一且稳定的。如果没有resource-id,则考虑组合使用textclassxpath虽然强大,但易受UI结构变化影响,维护成本较高,可作为最后手段。

2. 坐标录制与动作回放:对于无法通过属性精确定位的元素(比如游戏界面、自定义绘制控件),或者你想快速记录一个操作流程,坐标录制功能就派上用场了。

  • 点击工具栏上的“录制”按钮(或类似图标),然后在中央的手机屏幕镜像上,用鼠标模拟点击、长按、滑动等操作。WEditor会记录下这些动作的坐标和类型。
  • 操作结束后,停止录制,你可以在右侧看到生成的一系列Python代码,对应你刚才的所有动作。这些代码基于坐标,因此对屏幕分辨率有要求,通常需要在同一分辨率设备上回放。

3. 断言与验证:自动化测试不仅仅是操作,还需要验证结果。WEditor可以方便地获取元素的属性值用于断言。

  • 定位到一个元素后,在属性面板可以看到它的textenabledchecked等状态。
  • 例如,登录后要验证是否跳转到首页,可以定位首页的一个特有元素(如“欢迎回来,XXX”的文本框),然后生成类似assert d(text=“欢迎回来”).exists()的断言代码。

4. 代码生成与导出:WEditor不是一个IDE,它的主要作用是辅助生成和调试代码片段。你可以将生成的定位、操作、断言代码复制出来,整合到你自己的Python测试脚本中。一个典型的模式是:用WEditor探索和生成核心步骤的代码,然后在PyCharm或VSCode中编写完整的、带有测试框架(如pytest)的测试用例。

4. 构建健壮测试脚本:超越录制的进阶实践

仅仅依靠录制生成的脚本是脆弱的。要构建可用于持续集成的健壮测试套件,需要更系统的工程化实践。

4.1 Page Object模式在WEditor下的实现

Page Object(PO)模式是UI自动化的最佳实践之一,它将页面元素定位和业务操作分离开,提高代码的可读性和可维护性。WEditor是创建PO模型中“页面对象”的绝佳工具。

具体做法:

  1. 为每个关键页面创建一个Python类。例如LoginPageHomePage
  2. 使用WEditor定位该页面上所有需要操作的元素,将它们的定位器作为该类的属性。例如:
    # login_page.py class LoginPage: def __init__(self, d): self.d = d # uiautomator2的设备对象 self.username_input = (self.d.resourceId, "com.app:id/et_username") self.password_input = (self.d.resourceId, "com.app:id/et_password") self.login_button = (self.d.resourceId, "com.app:id/btn_login") self.error_toast = (self.d.text, "用户名或密码错误")
    注意:这里存储的是定位器的元组,而非直接调用click()。这样更灵活。
  3. 在类中定义页面操作方法。这些方法使用上面定义的定位器来执行操作。
    def input_credentials(self, username, password): self.d(*self.username_input).set_text(username) self.d(*self.password_input).set_text(password) def click_login(self): self.d(*self.login_button).click() def get_error_toast_text(self): if self.d(*self.error_toast).exists(timeout=2): return self.d(*self.error_toast).get_text() return None
  4. 在测试用例中,直接调用页面对象的方法。这样,测试用例的逻辑非常清晰,且当UI元素属性变更时,只需修改对应Page类中的定位器即可。
    # test_login.py def test_login_failure(): page = LoginPage(device) page.input_credentials("wrong", "wrong") page.click_login() assert "用户名或密码错误" in page.get_error_toast_text()

4.2 等待策略:解决“元素找不到”的头号难题

动态加载、网络延迟是导致自动化脚本失败的主要原因。uiautomator2(以及WEditor生成的代码)内置了智能等待,但有时需要更精细的控制。

  • 隐式等待:在创建设备对象后设置,它对所有find_element类的操作生效。

    d = u2.connect() d.implicitly_wait(10) # 等待最多10秒

    但这不够灵活,可能会在不需要等待的地方浪费时间。

  • 显式等待(推荐):使用d.wait()d.xpath().wait()等方法,等待特定条件成立。

    # 等待登录按钮出现并可点击 d(resourceId="com.app:id/btn_login").wait(timeout=10) d(resourceId="com.app:id/btn_login").click() # 等待某个元素消失(如加载进度条) d(text="加载中...").wait_gone(timeout=15)
  • 结合PO模式的等待:可以在页面对象的方法内部加入等待逻辑,使业务操作更稳健。

    class HomePage: def __init__(self, d): self.d = d self.welcome_msg = (self.d.textStartsWith, "欢迎") # 使用模糊匹配 def ensure_loaded(self): """确保首页已加载完成""" self.d(*self.welcome_msg).wait(timeout=10) # 也可以增加其他标志性元素的检查 assert self.d(*self.welcome_msg).exists

4.3 数据驱动与参数化测试

将测试数据与脚本逻辑分离,是提高测试覆盖率和维护性的关键。我们可以使用pytest@pytest.mark.parametrize装饰器轻松实现。

首先,将测试数据(如不同的用户名/密码组合)整理出来,可以放在代码中,或者更好的方式是放在外部文件(如JSON、YAML、CSV)中。

# test_data.py 或从文件读取 login_test_data = [ ("空密码", "admin", "", "密码不能为空"), ("错误密码", "admin", "wrong", "用户名或密码错误"), ("正确登录", "admin", "correct_password", None) # None表示期望成功,无错误信息 ]

然后在测试用例中使用参数化:

import pytest @pytest.mark.parametrize("case_name,username,password,expected_error", login_test_data) def test_login_parametrized(case_name, username, password, expected_error, device): """参数化登录测试""" page = LoginPage(device) page.input_credentials(username, password) page.click_login() if expected_error: # 期望失败的用例 actual_error = page.get_error_toast_text() assert expected_error in actual_error else: # 期望成功的用例 home_page = HomePage(device) home_page.ensure_loaded() # 进一步验证登录成功后的状态...

这样,只需要维护login_test_data这个数据列表,就能轻松扩展测试场景。WEditor在这里的角色是帮助我们快速构建出LoginPageHomePage这两个页面对象的核心操作代码。

5. 集成与进阶:将WEditor融入CI/CD流水线

个人使用WEditor提升效率是第一步,让自动化测试在团队中持续运行并发挥作用,就需要将其集成到持续集成/持续部署(CI/CD)流程中。

5.1 测试脚本的组织与管理

一个可维护的测试项目应该有清晰的结构。我推荐如下目录结构:

mobile_auto_test/ ├── conftest.py # pytest全局配置,如设备初始化 ├── requirements.txt # 项目依赖(包含weditor, uiautomator2, pytest等) ├── pages/ # 页面对象层 │ ├── __init__.py │ ├── login_page.py │ └── home_page.py ├── test_data/ # 测试数据文件 │ └── login_data.json ├── test_cases/ # 测试用例层 │ ├── __init__.py │ ├── test_login.py │ └── test_order.py └── utils/ # 工具函数(如截图、日志) ├── __init__.py └── logger.py

conftest.py中,我们可以使用pytest的fixture来管理设备的生命周期,确保每个测试用例都在一个干净的环境中开始。

# conftest.py import pytest import uiautomator2 as u2 @pytest.fixture(scope="session") def device(): # 这里可以配置连接设备序列号,或从环境变量读取 serial = os.getenv("ANDROID_DEVICE_SERIAL", None) d = u2.connect(serial) if serial else u2.connect() d.implicitly_wait(10) yield d # 测试结束后,可以做一些清理工作,如卸载测试包、关闭应用等 d.app_stop("com.app.package")

5.2 在CI服务器上运行测试

在Jenkins、GitLab CI、GitHub Actions等CI平台上运行移动端UI测试,关键在于环境准备。

  1. Agent环境:CI节点必须安装Android SDK(包含ADB)、Python以及项目依赖。通常可以通过Docker镜像来固化这个环境。
  2. 设备供给:有两种主流方式:
    • 连接真机:CI服务器通过USB Hub连接多台物理手机。需要配置好设备的udev规则,并确保设备屏幕常亮、USB调试开启。
    • 使用模拟器:在CI上启动Android模拟器(如官方模拟器或Genymotion)。这种方式更易于扩展和并行化,但性能开销较大。可以通过命令行工具(如avdmanageremulator)来创建和启动模拟器。
  3. 执行测试:CI任务的脚本步骤通常很简单:
    # 例如 GitHub Actions 的步骤 - name: Run UI Tests run: | python -m pytest test_cases/ -v --alluredir=./allure-results
    这里使用了pytest运行测试,并用allure生成漂亮的测试报告。

5.3 测试报告与失败分析

清晰的测试报告对于分析失败原因至关重要。pytest-html可以生成基础的HTML报告,而allure-pytest能生成功能更强大、更美观的交互式报告。

集成Allure的步骤:

  1. 安装:pip install allure-pytest
  2. 在测试用例中添加装饰器记录步骤:
    import allure @allure.step("输入用户名和密码") def input_credentials(self, username, password): ... @allure.step("点击登录按钮") def click_login(self): ...
  3. 运行测试时指定Allure结果目录:pytest --alluredir=./results
  4. 测试结束后,生成并打开报告:allure serve ./results

当测试失败时,Allure报告会展示失败的步骤、截图和日志。我们可以在conftest.py中编写一个钩子函数,在测试失败时自动用WEditor(实际上是uiautomator2)截图并附加到报告中。

# conftest.py import pytest from datetime import datetime @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): outcome = yield report = outcome.get_result() if report.when == "call" and report.failed: # 获取设备fixture d = item.funcargs.get('device', None) if d: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") screenshot_path = f"./screenshots/failure_{item.name}_{timestamp}.png" d.screenshot(screenshot_path) # 将截图附加到allure报告 allure.attach.file(screenshot_path, name="失败截图", attachment_type=allure.attachment_type.PNG)

6. 常见问题排查与性能优化实战记录

即使一切配置正确,在实际编写和运行测试脚本时,依然会遇到各种“坑”。下面是我在实践中总结的一些高频问题及解决方案。

6.1 连接与控件树获取失败

问题现象可能原因排查步骤与解决方案
WEditor连接设备后,控件树区域空白或一直加载。1. ATX代理APK未成功安装或运行。
2. 设备UIAutomator服务未开启或异常。
3. 应用页面是WebView或Flutter等非原生控件。
1. 检查手机通知栏或应用列表,是否有ATX相关的应用或服务。尝试重启WEditor或重新连接。
2. 在手机“设置”-“开发者选项”中,确保“USB调试(安全设置)”(允许通过USB调试修改权限或模拟点击)已开启。
3. 对于WebView,需要先切换到对应的WebView上下文。对于Flutter,需要使用flutter_driverintegration_test,WEditor对纯Flutter支持有限。
点击“刷新”按钮无反应,或报错。1. 设备锁屏或停留在非目标应用。
2. ADB连接不稳定。
1. 确保设备屏幕已解锁,并停留在你要测试的应用界面。
2. 尝试在命令行执行adb kill-server && adb start-server重启ADB服务,然后重新连接WEditor。
元素可以定位,但点击/输入操作无效。1. 元素实际不可交互(如被遮挡、enabled=false)。
2. 坐标点击在了错误位置。
1. 在WEditor中查看元素属性,确认clickableenabled是否为true。检查屏幕上是否有弹窗遮挡。
2. 尝试使用d.click(x, y)的坐标点击作为临时方案,但需注意适配性问题。更好的方法是联系开发为关键元素添加可访问的resource-id

6.2 脚本稳定性与维护性提升

问题:脚本在本地运行成功,但在CI上或不同设备上失败。

  • 分辨率与密度适配:使用坐标录制的脚本对屏幕分辨率敏感。解决方案是使用相对坐标或百分比。uiautomator2提供了d.click(0.5, 0.5)这样的按屏幕比例点击的方法。更好的做法是永远优先使用属性定位,而非坐标
  • 动态内容与异步加载:列表、弹窗、网络请求后的内容更新是失败重灾区。必须强化等待策略。除了前面提到的显式等待,对于列表,可以结合使用d(className="android.widget.ListView").child()这样的方法来定位子项,即使列表项数量变化也能处理。
  • 应用状态清理:测试用例之间相互影响。每个用例开始前,应确保应用回到一个干净的状态(如首页)。可以在setUp方法中强制停止应用再启动,或使用d.app_start(“package”, stop=True)

问题:UI频繁改动,定位器经常失效,维护成本高。

  • 与开发团队约定:推动开发为所有重要的、需要自动化测试的UI元素添加唯一且稳定的resource-id。这是最根本的解决方案。
  • 使用更灵活的定位器
    • 文本匹配d(text="登录")可能因为国际化而失效。可以使用d(textContains="登")d(textMatches=".*登录.*")进行模糊匹配,但需注意唯一性。
    • 兄弟节点/父子节点定位:当目标元素没有唯一属性,但其相邻兄弟或父节点有稳定属性时,可以使用XPath或child,sibling方法进行相对定位。例如:d(text="用户名").sibling(className="android.widget.EditText")
  • 建立定位器仓库:将所有的定位器字符串集中管理在一个配置文件或特定的Python模块中。当UI变更时,只需修改这个中心文件。这比散落在各个测试用例中修改要高效得多。

6.3 性能优化技巧

当测试用例成百上千时,执行速度变得至关重要。

  • 减少不必要的截图和日志:在conftest.py中,可以通过钩子函数控制只在失败时截图。对于日志,使用不同的级别(INFO, DEBUG),在CI运行时只输出ERROR和WARNING级别日志。
  • 优化等待时间:精确设置等待超时,避免过长的隐式等待。对于已知加载很快的页面,将显式等待的timeout设小一些。
  • 用例并行执行:如果拥有多台测试设备或模拟器,可以使用pytest-xdist插件并行运行测试用例,大幅缩短整体测试时间。这需要测试用例之间完全独立,不共享状态。
  • 使用session级别的Fixture:对于一些耗时的准备工作(如安装APK、登录获取Token),可以将其定义为scope="session"的fixture,这样在整个测试会话中只执行一次,而不是每个用例都执行。

最后,我想分享一个深刻的体会:WEditor这类工具的价值,不在于它能完全替代人工编写代码,而在于它极大地降低了UI自动化测试的探索和调试门槛。它让测试人员能更专注于测试逻辑和场景设计,而不是陷入与元素定位器“搏斗”的泥潭。真正的“终极解决方案”,是WEditor提供的可视化能力与你遵循最佳实践(如PO模式、数据驱动、合理等待)所编写的健壮代码的结合。从这个角度看,WEditor更像是一位强大的助手,帮你扫清了前进道路上的第一道也是最高的一道障碍,剩下的旅程,则需要你带着工程化的思维去规划和构建。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/19 16:47:12

Maya权重平滑终极指南:5分钟掌握brSmoothWeights完整教程

Maya权重平滑终极指南:5分钟掌握brSmoothWeights完整教程 【免费下载链接】brSmoothWeights Advanced skin cluster weights smoothing tool for Autodesk Maya 项目地址: https://gitcode.com/gh_mirrors/br/brSmoothWeights 在3D角色动画制作中&#xff0c…

作者头像 李华
网站建设 2026/6/19 16:43:53

从零到一:基于MATLAB/YALMIP/CPLEX的电力系统机组组合优化实战

1. 初识电力系统机组组合优化 第一次接触电力系统机组组合优化问题时,我正为一个省级电网的调度项目头疼。当时手头有6台发电机组的运行数据,需要制定24小时的最优启停计划。这个看似简单的任务,实际上涉及到复杂的数学建模和优化计算。后来我…

作者头像 李华
网站建设 2026/6/19 16:30:49

从零到一:在AutoDL云平台部署并高效训练YOLOv5模型

1. 环境准备与AutoDL入门 第一次接触云端训练的小白们注意了,AutoDL这个平台对新手特别友好。我去年刚开始用的时候,从注册到跑通第一个模型只用了不到两小时。先说说准备工作:你需要准备一个划分好的数据集(建议用VOC或COCO格式&…

作者头像 李华
网站建设 2026/6/19 16:28:03

DevOps,平台工程才是你的下半场

做DevOps的人,最容易陷入一个错觉: “我把自动化都搭好了,就没我啥事了。” 四年,我从手动部署写到自动化脚本,从脚本写到Jenkins Pipeline,再写到GitOps。现在代码一提交,自动构建、自动测试、…

作者头像 李华
网站建设 2026/6/19 16:22:09

OpCore-Simplify:10分钟搞定黑苹果EFI配置,告别3天调试噩梦

OpCore-Simplify:10分钟搞定黑苹果EFI配置,告别3天调试噩梦 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 你是否曾经被黑苹果…

作者头像 李华
网站建设 2026/6/19 16:21:57

3天完成3个月工作:UE5-MCP如何用AI重构游戏开发范式

3天完成3个月工作:UE5-MCP如何用AI重构游戏开发范式 【免费下载链接】UE5-MCP MCP for Unreal Engine 5 项目地址: https://gitcode.com/gh_mirrors/ue/UE5-MCP 在虚幻引擎5开发中,传统工作流程如同数字时代的"手工作坊"——美术团队创…

作者头像 李华