为什么当我在 Android 设备上运行 cocos2dx 游戏时,使用 UTF-8 字符串的 ui::Text 组件的渲染受到限制?

Why is the rendering of ui::Text components which use UTF-8 strings being limited when I run my cocos2dx game on an android device?

提问人:Josh Hardman 提问时间:12/4/2020 更新时间:12/5/2020 访问量:158

问:

我正在cocos2dx游戏引擎上用C++开发游戏。我主要在 win32 平台上测试它,但最近在 android 上尝试了它。当我这样做时,我发现事情没有按预期运行。如果您想知道,我正在三星 Galaxy S8.0.0 上的 Android Oreo (7) 上运行 apk。

我注意到的第一件事是,一些在 win32 上渲染的组件没有在 android 上渲染。

我试图更好地理解为什么会这样,但经过几天的在线帮助板、源代码和教程的挖掘,我没有发现任何特别有希望的东西。

下面是一个问题的示例:

我有一个cocos2d::Scene,它有许多ui::Text组件,可以显示一些文本。如果初始化 ui::Text 组件时没有任何 UTF-8 字符,则它们似乎没有问题。

但是,如果它们使用 UTF-8 字符初始化,则有些会呈现,有些则不会。即使在使用 jni 调试器运行 adb 后,我也没有找到任何有用的错误消息,程序继续运行。

下面是一些示例代码:


using namespace cocos2d;

Scene* MainMenuScene::createScene()
{
    return MainMenuScene::create();
}

bool MainMenuScene::init()
{
    if ( !Scene::init() )
    {
        return false;
    }

 auto visibleSize = Director::getInstance()->getVisibleSize();

    auto ichi = ui::Text::create(u8"一", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto ni = ui::Text::create(u8"二", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto san = ui::Text::create(u8"三", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto yon = ui::Text::create(u8"四", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto go = ui::Text::create(u8"五", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto roku = ui::Text::create(u8"六", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto nana = ui::Text::create(u8"七", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto hachi = ui::Text::create(u8"八", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto kyuu = ui::Text::create(u8"九", "fonts/rounded-mgenplus-1c-black.ttf", 24);

    auto ichi_h = ui::Text::create(u8"いち", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto ni_h = ui::Text::create(u8"に", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto san_h = ui::Text::create(u8"さん", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto yon_h = ui::Text::create(u8"よん", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto go_h = ui::Text::create(u8"ご", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto roku_h = ui::Text::create(u8"ろく", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto nana_h = ui::Text::create(u8"なな", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto hachi_h = ui::Text::create(u8"はち", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto kyuu_h = ui::Text::create(u8"きゅう", "fonts/rounded-mgenplus-1c-black.ttf", 24);


    auto ichi_k = ui::Text::create(u8"イチ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto ni_k = ui::Text::create(u8"ニ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto san_k = ui::Text::create(u8"サン", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto yon_k = ui::Text::create(u8"ヨン", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto go_k = ui::Text::create(u8"ゴ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto roku_k = ui::Text::create(u8"ロク", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto nana_k = ui::Text::create(u8"ナナ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto hachi_k = ui::Text::create(u8"ハチ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto kyuu_k = ui::Text::create(u8"キュウ", "fonts/rounded-mgenplus-1c-black.ttf", 24);

    auto layout = ui::Layout::create();
    layout->setLayoutType(ui::Layout::Type::HORIZONTAL);
    layout->setPosition(Vec2(0, visibleSize.height));

    auto layout_kan = ui::Layout::create();
    layout_kan->setLayoutType(ui::Layout::Type::VERTICAL);
    layout_kan->setContentSize(Size(2 * kyuu_h->getContentSize().width, visibleSize.height));

    auto layout_h = ui::Layout::create();
    layout_h->setLayoutType(ui::Layout::Type::VERTICAL);
    layout_h->setContentSize(Size(2 * kyuu_h->getContentSize().width, visibleSize.height));

    auto layout_k = ui::Layout::create();
    layout_k->setLayoutType(ui::Layout::Type::VERTICAL);
    layout_k->setContentSize(Size(2 * kyuu_h->getContentSize().width, visibleSize.height));


    layout_kan->addChild(ichi);
    layout_kan->addChild(ni);
    layout_kan->addChild(san);
    layout_kan->addChild(yon);
    layout_kan->addChild(go);
    layout_kan->addChild(roku);
    layout_kan->addChild(nana);
    layout_kan->addChild(hachi);
    layout_kan->addChild(kyuu);

    layout_h->addChild(ichi_h);
    layout_h->addChild(ni_h);
    layout_h->addChild(san_h);
    layout_h->addChild(yon_h);
    layout_h->addChild(go_h);
    layout_h->addChild(roku_h);
    layout_h->addChild(nana_h);
    layout_h->addChild(hachi_h);
    layout_h->addChild(kyuu_h);

    layout_k->addChild(ichi_k);
    layout_k->addChild(ni_k);
    layout_k->addChild(san_k);
    layout_k->addChild(yon_k);
    layout_k->addChild(go_k);
    layout_k->addChild(roku_k);
    layout_k->addChild(nana_k);
    layout_k->addChild(hachi_k);
    layout_k->addChild(kyuu_k);

    layout->addChild(layout_kan);
    layout->addChild(layout_h);
    layout->addChild(layout_k);

    this->addChild(layout);

    return true;
} 

下面是 win32 上的样子:

win32 test

这是在 android 上的样子:

android test

ui::Text 组件的实例化顺序似乎会影响渲染组件的数量,而渲染的优先级似乎取决于实例化的顺序。但是,偶尔会显示稍后实例化的 ui::Text,而之前实例化的 ui::Text 不会显示。

以下是我按以下顺序实例化相同的 ui::Text 组件时发生的情况:

    auto ichi = ui::Text::create(u8"一", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto ni = ui::Text::create(u8"二", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto san = ui::Text::create(u8"三", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto yon = ui::Text::create(u8"四", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto go = ui::Text::create(u8"五", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto roku = ui::Text::create(u8"六", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto nana = ui::Text::create(u8"七", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto hachi = ui::Text::create(u8"八", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto kyuu = ui::Text::create(u8"九", "fonts/rounded-mgenplus-1c-black.ttf", 24);

    auto ichi_k = ui::Text::create(u8"イチ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto ni_k = ui::Text::create(u8"ニ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto san_k = ui::Text::create(u8"サン", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto yon_k = ui::Text::create(u8"ヨン", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto go_k = ui::Text::create(u8"ゴ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto roku_k = ui::Text::create(u8"ロク", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto nana_k = ui::Text::create(u8"ナナ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto hachi_k = ui::Text::create(u8"ハチ", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto kyuu_k = ui::Text::create(u8"キュウ", "fonts/rounded-mgenplus-1c-black.ttf", 24);

    auto ichi_h = ui::Text::create(u8"いち", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto ni_h = ui::Text::create(u8"に", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto san_h = ui::Text::create(u8"さん", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto yon_h = ui::Text::create(u8"よん", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto go_h = ui::Text::create(u8"ご", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto roku_h = ui::Text::create(u8"ろく", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto nana_h = ui::Text::create(u8"なな", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto hachi_h = ui::Text::create(u8"はち", "fonts/rounded-mgenplus-1c-black.ttf", 24);
    auto kyuu_h = ui::Text::create(u8"きゅう", "fonts/rounded-mgenplus-1c-black.ttf", 24);

这是在 android 上的样子:

android test 2

其他可能相关的信息:

  • 增加其他 ui 组件的数量似乎会减少 呈现的 UTF-8 初始化 ui::Text 组件的数量。
  • 呈现的 ui:Text 组件和未呈现的组件 对于一组代码块似乎保持一致。换言之, GUI 输出似乎不会随不同代码的不同而变化 运行。
  • 不使用 UTF-8 字符串的 ui::text 组件似乎不是 受影响,并始终显示。
  • 从字符串中删除 u8 前缀会得到相同的结果 android(缺少组件,但渲染的组件显示为 预期),并导致字符由 ???' 表示开启 win32的。
  • 当我在 win32 上编译时,没有这样的问题,所有 ui::Text 无论使用哪个字符集,都会显示组件。
  • 我专门使用日语字符(包括汉字、平假名 和片假名),但据推测这是所有 UTF-8 的问题 字符。

我想知道为什么会发生这种情况,以及我能做些什么来规避它而不诉诸黑客。

我将继续深入研究文档和源代码,以尝试更好地理解问题的根源,但我感觉这可能与 Android 受保护的内部结构有关。咳咳。

到目前为止,我一直在阅读 android 关于 JNI、NDK 和 OpenGL 的文档,并尽可能地浏览所有可能相关的 cocos2dx 和 android 类。我还通读了与字符串和语言环境相关的 C++ 编程部分,但似乎如果不绕过 cocos2dx 框架,我就无法做很多事情。

我想知道这个问题是否可能是由某些 JNI 限制或缓冲错误引起的。或者,这可能与版本控制或硬件有关。也许这与在调试模式下运行的应用程序有关?另外,我知道 Java 在内部使用 UTF-16 作为其字符串,所以我想这也可能在某个地方扔了一个扳手......

安卓 C++ UTF-8 java-native-interface cocos2d-x

评论

0赞 Josh Hardman 12/4/2020
github.com/cocos2d/cocos2d-x/issues/20622链接到 Github 问题

答:

0赞 Josh Hardman 12/5/2020 #1

这个问题似乎源于 Cocos2dx 游戏引擎中的几个错误。请参阅评论中发布的 Github 问题以获取修复。