【Unity安卓】Unity 嵌入 Android Studio 完整流程

示例工程链接

完整工程链接

基于你当前环境:Unity 2022.3.62f3c1Gradle 7.5.1AGP 7.4.2JDK 11compileSdk 33ARM64。按顺序做即可。


一、版本对照(先记住,避免踩坑)

组件 推荐版本 不要混用
Gradle(Wrapper) 7.5.1 ≠ AGP 版本号(没有 7.5.1 的 AGP)
Android Gradle Plugin 7.4.2 ≠ 8.11(新版 Studio 默认)
Gradle JDK 11(Unity 自带 OpenJDK) 不用 8、不用 21
compileSdk / targetSdk 33(与 Unity 一致) 不必追 API 37
Unity 架构 ARM64 真机调试优先

Unity OpenJDK 路径示例:

text 复制代码
F:\UnityEditor\2022.3.62f3c1\Editor\Data\PlaybackEngines\AndroidPlayer\OpenJDK

Unity SDK 路径示例:

text 复制代码
F:\UnityEditor\2022.3.62f3c1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK

二、Unity 侧(导出 unityLibrary)

1. Player Settings

Edit → Project Settings → Player → Android

  • Package Name:按项目填写(可与宿主不同)
  • Minimum / Target API:与宿主一致
  • Scripting BackendIL2CPP
  • Target Architectures :与宿主一致(如 ARM64

2. 导出工程

File → Build Settings → Android

  1. Switch Platform(若未切换)
  2. 勾选 Export Project
  3. Export ,输出到空目录,例如 F:\UnityExport\AndroidDemoExport

导出后重点目录:

text 复制代码
AndroidDemoExport/
└── unityLibrary/     ← 整个拷贝到 Android 工程
    ├── libs/           ← 含 unity-classes.jar(必须有)
    ├── src/main/
    └── build.gradle

3.(可选)自定义 Gradle 模板

若项目有 Assets/Plugins/Android/

  • settingsTemplate.gradle:仓库顺序 google()mavenCentral()gradlePluginPortal()
  • gradle.properties 需含:unityStreamingAssets=

三、Android Studio 侧(新建宿主工程)

1. 新建工程

  • 模板:Empty Views Activity(或 Empty Activity)
  • Language:Java
  • Package :如 com.zg.MyTest
  • Minimum SDK:≥ Unity 的 Min SDK

2. 拷贝 unityLibrary

将 Unity 导出的 unityLibrary 整个文件夹 放到工程根目录,与 app 同级:

text 复制代码
HostApp/
├── app/
├── unityLibrary/
├── build.gradle
└── settings.gradle

3. settings.gradle

gradle 复制代码
include ':app'
include ':unityLibrary'
project(':unityLibrary').projectDir = new File(rootDir, 'unityLibrary')

4. 根 build.gradle / libs.versions.toml(AGP 版本)

AGP 必须是 7.4.2,不是 7.5.1、不是 8.11:

gradle 复制代码
// build.gradle 示例
id 'com.android.application' version '7.4.2' apply false
id 'com.android.library' version '7.4.2' apply false

5. gradle-wrapper.properties

properties 复制代码
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip

(可改 file:///F:/Tools/gradle-7.5.1-bin.zip 使用本地 zip)

6. 工程根 gradle.properties

properties 复制代码
org.gradle.jvmargs=-Xmx4096M
android.useAndroidX=true
android.enableJetifier=true
unityStreamingAssets=
org.gradle.java.home=F\:\\UnityEditor\\2022.3.62f3c1\\Editor\\Data\\PlaybackEngines\\AndroidPlayer\\OpenJDK
android.builder.sdkDownload=false

7. app/build.gradle

gradle 复制代码
dependencies {
    implementation project(':unityLibrary')
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.9.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
}

不要 使用过高的 activity:1.13+(会拉 navigationevent 等难解析依赖)。

如编译报错可以去掉部分代码

8. unityLibrary/build.gradle

  • 确认有:api fileTree(dir: 'libs', include: ['*.jar'])api 不是 implementation,否则 app 找不到 UnityPlayer
  • 删除 buildToolsVersion '34.0.0'(若 AGP 提示与 35 冲突)

  • compileSdk / minSdk 与 app 一致

9. Android Studio 设置

设置
Gradle JDK Unity OpenJDK 11(勿用 1.8 / 21)
Android SDK Location 与 Unity 一致(Unity 自带 SDK 更稳)
安装向导 Custom,不要装 Emulator、Build-Tools 37、API 37
SDK 保留 API 33Build-Tools 34.0.0 ;删掉本机 SDK 里的 android-36build-tools 35(若曾装过)

四、Manifest(嵌入最关键)

1. unityLibrary/AndroidManifest.xml

  • 删除 UnityPlayerActivityMAIN + LAUNCHER(避免桌面进全屏 Unity 闪退)

  • UnityPlayerActivity 可保留但 exported="false",或最终在 app 里 tools:node="remove"

  • 嵌入时建议:unity.launch-fullscreen = False

2. app/AndroidManifest.xml 要点

  • 只有 MainActivity 带 LAUNCHER

  • MainActivity 使用 @style/UnityThemeSelector

  • Application:android:extractNativeLibs="true"

  • 不要 在 app 里重复写与 unityLibrary 相同的 Unity meta-data(会合并冲突)

    Unity meta-data 由 unityLibrary中 AndroidManifest.xml合并,勿在 app 重复声明

xml 复制代码
        <!-- Unity meta-data 由 unityLibrary 合并,勿在 app 重复声明 -->
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<meta-data android:name="notch_support" android:value="true" />

3. uses-feature

从 unityLibrary 合并或复制到 app:glEsVersion、vulkan、touchscreen 等。


五、资源与代码

1. unityLibrary 补充 strings.xml

路径:unityLibrary/src/main/res/values/strings.xml

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="game_view_content_description">Game view</string>
</resources>

避免 UnityPlayer 初始化时 String resource ID #0x0

2. 布局 activity_main.xml

app>src>main>res>layout>activity_main.xml

全部替换

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- 上半:原生 UI(可改成按钮、列表等) -->
    <TextView
        android:id="@+id/native_title"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.55"
        android:gravity="center"
        android:text="这是原生 Android 区域"
        android:textSize="20sp"
        android:background="#EEEEEE" />

    <!-- 下半:Unity 嵌入区域(指定位置 = 这块容器) -->
    <FrameLayout
        android:id="@+id/unity_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.45"
        android:background="#000000" />

</LinearLayout>

3. MainActivity.java(嵌入核心)

要点:

  • 继承 Activity (不要 AppCompatActivity
  • requestWindowFeature(Window.FEATURE_NO_TITLE)super.onCreate 之前
  • 处理 Intent 的 unity 命令行参数(与 UnityPlayerActivity 一致)
  • new UnityPlayer(this, this)addViewunity_container
  • 完整转发 生命周期:onResume/onPause/onDestroy/onStart/onStoponWindowFocusChangedonConfigurationChanged、按键/触摸等(参考 UnityPlayerActivity

包名与目录一致,例如:package com.zg.MyTest; 对应 .../com/zg/MyTest/MainActivity.java


完整代码,需替换安卓项目包名

csharp 复制代码
package com.zg.Debug001;//你的包名

import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.FrameLayout;


import com.unity3d.player.UnityPlayer;
import com.unity3d.player.IUnityPlayerLifecycleEvents;

public class MainActivity extends Activity implements IUnityPlayerLifecycleEvents {
    private UnityPlayer unityPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        requestWindowFeature(Window.FEATURE_NO_TITLE);

        super.onCreate(savedInstanceState);

        String cmdLine = getIntent().getStringExtra("unity");
        getIntent().putExtra("unity", cmdLine);

        setContentView(R.layout.activity_main);

        FrameLayout container = findViewById(R.id.unity_container);
        unityPlayer = new UnityPlayer(this, this);
        container.addView(
                unityPlayer,
                new FrameLayout.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT
                )
        );
        unityPlayer.requestFocus();
    }
    @Override
    protected void onNewIntent(Intent intent) {
        setIntent(intent);
        if (unityPlayer != null) {
            unityPlayer.newIntent(intent);
        }
    }

    @Override
    protected void onDestroy() {
        if (unityPlayer != null) {
            unityPlayer.destroy();
        }
        super.onDestroy();
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (unityPlayer != null) {
            unityPlayer.onStop();
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (unityPlayer != null) {
            unityPlayer.onStart();
        }
    }

    @Override
    protected void onPause() {
        if (unityPlayer != null) {
            unityPlayer.onPause();
        }
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (unityPlayer != null) {
            unityPlayer.onResume();
        }
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        if (unityPlayer != null) {
            unityPlayer.lowMemory();
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (unityPlayer != null) {
            unityPlayer.configurationChanged(newConfig);
        }
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (unityPlayer != null) {
            unityPlayer.windowFocusChanged(hasFocus);
        }
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_MULTIPLE && unityPlayer != null) {
            return unityPlayer.injectEvent(event);
        }
        return super.dispatchKeyEvent(event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        return unityPlayer != null ? unityPlayer.onKeyUp(keyCode, event) : super.onKeyUp(keyCode, event);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        return unityPlayer != null ? unityPlayer.onKeyDown(keyCode, event) : super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return unityPlayer != null ? unityPlayer.onTouchEvent(event) : super.onTouchEvent(event);
    }

    @Override
    public void onUnityPlayerUnloaded() {
    }

    @Override
    public void onUnityPlayerQuitted() {
    }
}

六、编译与运行

  1. File → Sync Project with Gradle Files
  2. Build → Clean Project → Rebuild Project
  3. 终端验证(可选):
bat 复制代码
cd F:\A_UTest
gradlew -version

应显示:Gradle 7.5.1JVM 11.x

  1. 手机 USB 调试 → 顶部选 app + 设备 → Run
  2. 每次改 Unity 场景后:Unity 重新 Export → 覆盖 unityLibrary → 再 Rebuild

七、常见问题速查

现象 处理
Java 21 + Gradle 7.5 不兼容 Gradle JDK 改为 11
AGP 7.5.1 找不到 AGP 应为 7.4.2,不是 Gradle 版本号
unityStreamingAssets 报错 gradle.propertiesunityStreamingAssets=
UnityPlayer 找不到符号 api fileTree(libs) + 确认 unity-classes.jar 存在
navigationevent 解析失败 降低 AndroidX 版本,去掉 activity:1.13
SDK XML v4 警告 删 API 36 / build-tools 35;用 Unity SDK;AGP 保持 7.4.2
要求下载 API 37 安装向导选 Custom 不装;SDK 指 Unity;勿追 37
桌面启动闪退 UnityPlayerActivity 去掉 unityLibrary 的 LAUNCHER;app 只保留 MainActivity
Manifest 合并冲突 meta-data 只在 unityLibrary 写 Unity meta-data,app 不重复
String resource ID #0x0 strings.xml;MainActivity 用 Activity + UnityThemeSelector ;加 unityplayer.UnityActivity meta-data
黑屏无画面 检查生命周期是否转发给 unityPlayer
模拟器不行 Unity 用 ARM64 真机

八、推荐目录结构(最终)

text 复制代码
A_UTest/
├── app/
│   ├── build.gradle              ← implementation project(':unityLibrary')
│   └── src/main/
│       ├── AndroidManifest.xml   ← 仅 MainActivity 为 LAUNCHER
│       ├── java/.../MainActivity.java
│       └── res/layout/activity_main.xml
├── unityLibrary/                 ← Unity 导出,可整体覆盖更新
│   ├── libs/unity-classes.jar
│   ├── build.gradle              ← api fileTree(libs)
│   └── src/main/AndroidManifest.xml  ← 无 LAUNCHER
├── gradle.properties             ← JDK 11、unityStreamingAssets
├── settings.gradle               ← include unityLibrary
└── gradle/wrapper/               ← Gradle 7.5.1

九、流程总览(一张表)

步骤 位置 动作
1 Unity Player 设 Android / IL2CPP / API 33
2 Unity Build Settings → Export Project
3 AS 新建 app 工程
4 磁盘 拷贝 unityLibrary 到工程根
5 Gradle 7.5.1 + AGP 7.4.2 + JDK 11
6 Gradle app 依赖 unityLibrary;unityLibrary api jars
7 Manifest 仅 MainActivity 启动;去掉 Unity LAUNCHER
8 代码 MainActivity 嵌入 UnityPlayer + 生命周期
9 资源 game_view_content_description + Unity 主题
10 SDK 使用 Unity SDK,不装 API 37
11 运行 Sync → Rebuild → 真机 Run

完整工程链接:https://pan.baidu.com/s/1GS8dVtry9wSkwl3NvJI0xg?pwd=vjwc

相关推荐
星间都市山脉5 小时前
Windows 环境 Android 系统 APK 签名操作文档
android·windows
shuaiqinke5 小时前
【分享】OrbitV工具箱| 手表手环全能适配 |表盘应用一键装
android·智能手机
子非吾喵5 小时前
HBuilder X本地打包的资源放到Android Studio本地打包的记录
android·ide·android studio
simplepeng16 小时前
我们都知道但总是忽略的5个Jetpack Compose细节
android·android jetpack
刮风那天16 小时前
Android 如何提高进程优先级避免被查杀?
android
修行者对66618 小时前
安卓阿里云镜像
android
刮风那天18 小时前
Android AMS创建进程不用Binder而用Socket?
android·java·binder
知行合一。。。20 小时前
Python--05--面向对象(继承,多态)
android·开发语言·python