【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

相关推荐
nnsix1 天前
Unity 贴图压缩格式 笔记
笔记·unity·贴图
故渊at1 天前
第二板块:Android 四大组件标准化学理 | 第六篇:四大组件架构总论与 Manifest 规范
android·架构·zygote·manifest·四大组件
Jinkxs1 天前
Python基础 - 文件的写入操作 write与writelines方法
android·服务器·python
jason.zeng@15022071 天前
(第二讲)Android开发取摄像头流的基础(ImageAnalysis)
android
敲代码的瓦龙1 天前
操作系统?Android与Linux!!!
android·linux·运维
愚公搬代码1 天前
【愚公系列】《移动端AI应用开发》017-Android端应用开发(网络通信与API集成)
android·人工智能
say_fall1 天前
可编程中断控制器8259A工作方式超详细解析
android·开发语言·学习·硬件架构·硬件工程
甜瓜看代码1 天前
SystemUI 启动与组成机制
android·源码·源码阅读
黄林晴1 天前
Kotlin 2.4.0 正式稳定!Android 升级、Compose、KMP 全变化详解
android·kotlin
恋猫de小郭1 天前
Android 官方给 Compose 搞了个不需要 UI 环境的 Composable
android·前端·flutter