Flutter嵌入Unity游戏插件flutter_embed_unity_2022_3_ios的使用

Flutter嵌入Unity游戏插件flutter_embed_unity_2022_3_ios的使用

简介

flutter_embed_unity_2022_3_ios 是一个用于在 Flutter 应用中嵌入 Unity 游戏的 iOS 插件。通过该插件,开发者可以将 Unity 开发的游戏无缝集成到 Flutter 应用中。

使用步骤

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 flutter_embed_unity_2022_3_ios 作为依赖项。具体操作如下:

dependencies:
  ...
  flutter_embed_unity_2022_3_ios: ^0.0.1
  ...

保存后,运行 flutter pub get 来获取新添加的依赖。

2. 创建基本的 Flutter 应用

创建一个新的 Flutter 应用,并确保你已经安装了 Flutter SDK 和 Android/iOS 开发环境。你可以使用以下命令创建一个新的 Flutter 项目:

flutter create my_unity_flutter_app
cd my_unity_flutter_app

3. 编写 Flutter 代码

接下来,我们将编写一些 Flutter 代码来展示如何嵌入 Unity 游戏。

示例代码

import 'package:flutter/material.dart';
import 'package:flutter_embed_unity/flutter_embed_unity.dart';
import 'package:intl/intl.dart';

void main() {
  runApp(const ExampleApp());
}

class ExampleApp extends StatefulWidget {
  const ExampleApp({super.key});

  @override
  State<ExampleApp> createState() => _ExampleAppState();
}

class _ExampleAppState extends State<ExampleApp> {

  // 当在消息协议中转换字符串和数字时,始终使用固定的本地化格式,
  // 以防止当用户和开发者的本地化设置不同时出现意外的解析错误(例如小数点符号可能不同)
  static final _fixedLocaleNumberFormatter = NumberFormat.decimalPatternDigits(
    locale: 'en_gb',
    decimalDigits: 2,
  );

  bool? _isUnityArSupportedOnDevice;
  bool _isArSceneActive = false;
  double _rotationSpeed = 30;
  int _numberOfTaps = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('插件示例应用'),
        ),
        body: SafeArea(
          child: Builder(
            builder: (context) {
              final theme = Theme.of(context);
              final bool? isUnityArSupportedOnDevice = _isUnityArSupportedOnDevice;
              final String arStatusMessage;

              if(isUnityArSupportedOnDevice == null) {
                arStatusMessage = "检查中...";
              }
              else if(isUnityArSupportedOnDevice) {
                arStatusMessage = "支持";
              }
              else {
                arStatusMessage = "不支持此设备";
              }

              return Column(
                children: [
                  Expanded(
                    child: EmbedUnity(
                      onMessageFromUnity: (String data) {
                        // 从 Unity 脚本接收到消息
                        if(data == "touch"){
                          setState(() {
                            _numberOfTaps += 1;
                          });
                        }
                        else if(data == "scene_loaded") {
                          _sendRotationSpeedToUnity(_rotationSpeed);
                        }
                        else if(data == "ar:true") {
                          setState(() {
                            _isUnityArSupportedOnDevice = true;
                          });
                        }
                        else if(data == "ar:false") {
                          setState(() {
                            _isUnityArSupportedOnDevice = false;
                          });
                        }
                      },
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(16),
                    child: Text(
                      "Flutter 图标被点击 $_numberOfTaps 次",
                      textAlign: TextAlign.center,
                      style: theme.textTheme.titleMedium,
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 16),
                    child: Row(
                      children: [
                        Text("激活 AR ($arStatusMessage)"),
                        Switch(
                          value: _isArSceneActive,
                          onChanged: isUnityArSupportedOnDevice != null && isUnityArSupportedOnDevice ? (value) {
                            sendToUnity(
                              "SceneSwitcher",
                              "SwitchToScene",
                              _isArSceneActive ? "FlutterEmbedExampleScene" : "FlutterEmbedExampleSceneAR",
                            );
                            setState(() {
                              _isArSceneActive = value;
                            });
                          } : null,
                        ),
                      ],
                    ),
                  ),
                  Row(
                    children: [
                      const Padding(
                        padding: EdgeInsets.only(left: 16),
                        child: Text(
                          "速度",
                        ),
                      ),
                      Expanded(
                        child: Slider(
                          min: -200,
                          max: 200,
                          value: _rotationSpeed,
                          onChanged: (value) {
                            setState(() {
                              _rotationSpeed = value;
                            });
                            _sendRotationSpeedToUnity(value);
                          },
                        ),
                      ),
                    ],
                  ),
                  Row(
                    children: [
                      Expanded(
                        child: Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: ElevatedButton(
                            onPressed: () {
                              pauseUnity();
                            },
                            child: const Text("暂停"),
                          ),
                        ),
                      ),
                      Expanded(
                        child: Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: ElevatedButton(
                            onPressed: () {
                              resumeUnity();
                            },
                            child: const Text("恢复"),
                          ),
                        ),
                      ),
                      Expanded(
                        child: Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: ElevatedButton(
                            onPressed: () {
                              Navigator.push(
                                context,
                                MaterialPageRoute(builder: (context) => const Route2()),
                              );
                            },
                            child: const Text("打开路由 2", textAlign: TextAlign.center),
                          ),
                        ),
                      ),
                    ],
                  )
                ],
              );
            },
          ),
        ),
      ),
    );
  }

  void _sendRotationSpeedToUnity(double rotationSpeed) {
    sendToUnity(
      "FlutterLogo",
      "SetRotationSpeed",
      _fixedLocaleNumberFormatter.format(rotationSpeed),
    );
  }
}

class Route2 extends StatelessWidget {

  const Route2();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('路由 2'),
      ),
      body: SafeArea(
        child: Builder(
          builder: (context) =>
              Column(
                children: [
                  const Padding(
                    padding: EdgeInsets.all(16),
                    child: Text(
                      "Unity 只能在单个部件上显示一次。因此,如果将包含 FlutterEmbed 的第二个路由推送到堆栈上,Unity 将从第一个路由中分离,并附着到第二个路由。当从堆栈中弹出第二个路由时,Unity 将重新附着到第一个路由。",
                    ),
                  ),
                  const Expanded(
                    child: EmbedUnity(),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        const BackButton(),
                        ElevatedButton(
                          onPressed: () {
                            showDialog(context: context, builder: (_) => const Route3());
                          },
                          child: const Text("打开路由 3", textAlign: TextAlign.center),
                        ),
                      ],
                    ),
                  )
                ],
              )
        ),
      )
    );
  }
}

class Route3 extends StatelessWidget {

  const Route3();

  @override
  Widget build(BuildContext context) {
    return const AlertDialog(
      content: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(
            "路由 3",
            textAlign: TextAlign.center,
          ),
          SizedBox(
            height: 100,
            width: 80,
            child: EmbedUnity(),
          ),
        ],
      ),
    );
  }
}

4. 运行应用

现在你可以运行你的 Flutter 应用来查看嵌入的 Unity 游戏。

flutter run

更多关于Flutter嵌入Unity游戏插件flutter_embed_unity_2022_3_ios的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter嵌入Unity游戏插件flutter_embed_unity_2022_3_ios的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter应用中嵌入Unity游戏插件flutter_embed_unity_2022_3_ios的代码案例。这个插件允许你将Unity内容嵌入到Flutter应用中。以下步骤将展示如何在iOS平台上进行集成。

前提条件

  1. 确保你已经安装了Flutter SDK。
  2. 确保你的Flutter项目已经创建好。
  3. 确保你已经下载并安装了Unity,并创建了一个简单的Unity项目。

步骤一:添加flutter_embed_unity依赖

首先,在你的pubspec.yaml文件中添加flutter_embed_unity依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_embed_unity: ^0.1.0+5  # 请注意版本号,使用最新版本

然后运行flutter pub get来安装依赖。

步骤二:准备Unity项目

  1. 在Unity中创建一个简单的项目。
  2. 构建Unity项目为Xcode框架。在Unity中,选择File -> Build Settings,然后选择iOS平台,点击Switch Platform
  3. Player Settings中配置包名(Bundle Identifier)和其他必要的设置。
  4. 点击Build按钮,并选择输出目录,Unity会生成一个Xcode项目。
  5. 打开生成的Xcode项目,选择File -> Workspace Settings,将Build System设置为New Build System(如果尚未设置)。
  6. 构建并运行Unity项目,确保它可以在iOS模拟器或设备上正常运行。然后关闭Xcode项目。

步骤三:将Unity框架集成到Flutter项目中

  1. 将Unity生成的Xcode框架(通常是一个.xcframework文件)复制到你的Flutter项目的ios目录下,例如ios/Frameworks/

  2. 在你的Flutter项目的ios/目录下的Podfile中,添加以下配置来包含Unity框架的搜索路径:

platform :ios, '11.0'

target 'Runner' do
  use_frameworks!
  config = use_native_modules!

  # Flutter Pod
  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

  # Unity Framework
  pod 'UnityFramework', :path => 'Frameworks/UnityFramework.xcframework'

  # Add any additional pods you want to install
  # Install all pods depending on the CocoaPods Podfile.lock attributes
  install_all_specs!(config)
end

注意:这里的路径Frameworks/UnityFramework.xcframework需要根据你的实际路径进行调整。

  1. 在你的ios/Runner/Info.plist文件中,添加Unity所需的配置,比如CFBundleURLTypesLSApplicationQueriesSchemes等。

  2. 在你的Flutter项目的lib/目录下创建一个新的Dart文件,例如unity_view.dart,并添加以下代码:

import 'package:flutter/material.dart';
import 'package:flutter_embed_unity/flutter_embed_unity.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Embed Unity Example'),
        ),
        body: UnityView(
          entryPoint: 'main', // Unity场景中的入口点
          frameworkPath: 'Frameworks/UnityFramework.xcframework', // Unity框架的路径
        ),
      ),
    );
  }
}

注意:这里的frameworkPath也需要根据你的实际路径进行调整。

步骤四:运行Flutter项目

确保你的iOS开发环境已经配置好,然后运行flutter run命令来启动你的Flutter项目。如果一切顺利,你应该能够在Flutter应用中看到嵌入的Unity游戏内容。

注意事项

  • 确保你的Unity项目和Flutter项目的包名(Bundle Identifier)是一致的,或者在Unity的Player Settings中配置正确的包名映射。
  • 根据你的Unity项目配置,可能需要在Info.plist中添加更多的配置信息。
  • 如果遇到编译错误,请检查Xcode的Build Settings和Build Phases配置,确保Unity框架被正确包含和链接。

这个代码案例提供了一个基本的集成流程,你可能需要根据你的具体需求进行调整和扩展。

回到顶部