Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Unity/Unreal 插件集成iOS/Android 的血泪总结

Unity/Unreal 插件集成iOS/Android 的血泪总结

原创
作者头像
windseeker
修改于 2023-11-09 10:55:45
修改于 2023-11-09 10:55:45
3.2K210
代码可运行
举报
运行总次数:0
代码可运行

项目背景

近期我们开发了2个原生的 iOS 和 Android 组件,希望能用到游戏端,为了便于游戏开发人员更轻松的集成原生SDK,我们针对主流的游戏引擎:Unity 和 Unreal Engine (UE) 开发了相应的插件。对于我这样一个之前从未涉足游戏开发领域的人来说,这个过程中遇到了许多挑战,消耗了大量时间来解决一些初学者可能会遇到的问题。许多现在看似简单的问题,我当时都是通过观看 YouTube 视频和阅读大量 Unreal 论坛帖子逐步得到解决的。

为了帮助未来可能需要开发类似游戏原生插件的人少走弯路,我把几乎所有我遇到过的问题进行了总结,并包括了针对 Unity 和 UE编辑器的基础入门教程。

Unity 插件集成原生安卓的 aar 包和 iOS 动态库

Unity 插件开发,对比 UE 的插件开发,要简单不少。

一般而言,Unity 集成原生的插件的目录结构是这样:

代码语言:txt
AI代码解释
复制
Plugins
├── Android
│   ├── SurveyPopupView.aar
├── iOS
│   ├── SurveyPopupView
│   │   ├── SurveyPopupView.framework
│   │   │   ├── Headers
│   │   │   ├── Info.plist
│   │   │   ├── SurveyPopupView
│   │   └── SurveyPopupView.framework.meta
Scripts
├── SurveyPopupView.cs

集成 iOS Framework 动态库

在 Objective-C 中,我们需要把给 C# 使用的函数放在 extern "C" 代码块中:

代码语言:c
代码运行次数:0
运行
AI代码解释
复制
#ifdef __cplusplus
extern "C" {
#endif
void ImurOpenSurvey(const char *surveyId, const char *params) {
    NSString *nsSurveyId = [NSString stringWithUTF8String:surveyId];
    NSString *nsParams = [NSString stringWithUTF8String:params];
    dispatch_async(dispatch_get_main_queue(), ^{
        [[SurveyPopupView sharedInstance] open:nsSurveyId withParams:nsParams];
    });
}
#ifdef __cplusplus
}
#endif
extern "C" 的作用

在 Unity 环境中,C# 代码可以通过 IL2CPP(Intermediate Language to C++)技术调用 Objective-C 代码,IL2CPP是一种将.NET Intermediate Language (IL)代码转换为 C++ 代码的编译器技术。通过这种转换,Unity 可以将 C# 代码编译为本地代码,从而提高性能并允许与本地代码(如Objective-C或C++)的交互。

当在 Unity 中编写 C# 代码时,该代码首先被编译为.NET Intermediate Language (IL)。

通过 IL2CPP,这些 IL 代码被转换为 C++ 代码。一旦 C# 代码被转换为 C++ 代码,它可以直接与其他本地代码交互,包括 Objective-C。

使用 extern "C" 语法可以确保函数具有 C 链接约定,从而可以从 C++ 代码(由 IL2CPP 生成)中调用它们。

extern "C"还可以确保跨平台兼容性,特别是在涉及不同编译器和链接器的情况下。在后面部分的 UE 中,我们也需要使用到。

Unity iOS 桥接代码

一般调用不同平台的原生代码,我们会用一个 C# 的文件来桥接,保证调用方不需要考虑平台差异。

使用 DllImport("__Internal") 可以导入和调用 Framework 中的方法,需要注意的是 __Internal 标识是不能修改的,因为__Internal 被用来指示这些函数是在主执行文件本身中实现的,而不是在外部动态链接库(DLL)中实现的。这是因为 iOS 不允许应用程序加载外部的动态链接库,所有的代码都必须链接到主执行文件中。

代码语言:c#
AI代码解释
复制
[DllImport("__Internal")]
private static extern void ImurOpenSurvey(string surveyId, string urlparams);
Add to Embedded Binaries

在打包成插件的时候,我们需要注意的是,最好把 .framework.meta 文件也一起放进去,因为需要设置 AddToEmbeddedBinaries 属性为 true,不然最终把游戏打包成 iOS 应用的时候,不会自动嵌入我们的 framework。另外一个方案就是在 Unity 编辑器的 Inspector 中手动配置Add to Embedded Binaries,参考文档 Manual/PluginInspector

集成安卓的 aar 包

Unity 能自动识别并处理 Assets/Plugins/Android目录下的 .aar文件,包括在构建时将其包含在APK中。

主要是 AndroidJavaClass 和 AndroidJavaObject 类提供了一种在运行时从 C# 调用 Java 的能力。这是通过JNI(Java Native Interface)实现的,它是Java虚拟机(JVM)提供的一种允许 Java 代码与本地代码(例如C或C++代码)交互的接口。

这是我们在 C# 桥接代码中调用原生 Java 的示例:

代码语言:c#
AI代码解释
复制
private static void ImurOpenSurvey(string surveyId, string urlparams)
{
    AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
    AndroidJavaClass surveyClass = new AndroidJavaClass("com.tencent.imur.survey.IMurSurveyAdapter");
    surveyClass.CallStatic("openSurvey", currentActivity, surveyId, urlparams);
}

【新手篇】如何创建一个Unity项目,并绑定 C# 中的方法

1、创建一个空的 2d 项目
create_unity_project
create_unity_project
2、添加按钮

在“Hierarchy”窗口中,右键点击 -> UI -> Button。这将创建一个新的按钮对象,并将其添加到当前场景中。在“Inspector”窗口中,你可以看到新按钮的属性。你可以调整它的位置、大小、颜色和文本等。

create_button
create_button

创建完成之后 Unity 可能会提示你是否想要导入TextMesh Pro(TMP),我们选择 Import,TextMesh Pro 是 Unity 的一个高质量文本渲染和布局系统。

3、创建 C# 脚本

在 Assets 目录下,右键单击选择创建 C# 脚本,命名为 ButtonHandler。

create_c#
create_c#

编辑 C# 脚本,添加一个 Public 方法,输出一个 Log 文本用来测试

代码语言:c#
AI代码解释
复制
public class ButtonHandler : MonoBehaviour
{
    public void OnButtonClick()
    {
        Debug.Log("Button was clicked!");
    }
}
4、绑定 C# 方法到 Button 的点击事件中

点击左上角的“Hierarchy”窗口中的 Button,展开 Inspector,把 ButtonHandler 脚本拖动到 Inspector 中。

然后,点击 "On Click()" 面板右下角的加号,把 “Hierarchy”窗口中的 Button拖动到 Click 的 Object 中,再选择 ButtonHandler 的 OnButtonClick 方法。

bind_c#
bind_c#

点击运行,可以看到控制台正常输出了我们自定义的 Log:

log
log

UE4 插件集成原生安卓的 jar 包和 iOS 动态库

打包成 UE Plugin 之后,调用原生功能的方式会简单很多,可以极大的提高 SDK 接入效率。但是打包一个 UE 的插件是比较复杂的,接下来就详细说明我们是如何做的,以及所有遇到的问题和解决方案。

首先,在 UE 中,一般插件完整的目录结构是这样:(ThirdParty 目录也有放在第一层的)

代码语言:txt
AI代码解释
复制
ImurSurvey
├── ImurSurvey.uplugin
├── Resources
│   └── Icon128.png
└── Source
    └── ImurSurvey
        ├── ImurSurvey.Build.cs
        ├── ImurSurveyPlugin_Android_UPL.xml
        ├── ImurSurveyPlugin_iOS_UPL.xml
        ├── Private
        │   └── ImurSurvey.cpp
        ├── Public
        │   ├── ImurSurvey.h
        └── ThirdParty
            ├── Android
            │   ├── java
            │   └── libs
            └── iOS
                └── SurveyPopupView.embeddedframework.zip

在这个目录结构中,会把原生的包放在 Source/ThirdParty 对应的平台目录。

集成 iOS Framework 动态库

插件引用 Framework

假设构建好的 framework 名称是 MyFramework.framework,按照下面的文件目录 zip 压缩。

代码语言:txt
AI代码解释
复制
MyFramework.embeddedframework.zip
  > MyFramework.embeddedframework/
    > MyFramework.framework/

在 Plugins 下的 .build.cs 文件中,使用 PublicAdditionalFrameworks 方法添加 embeddedframework.zip

代码语言:c#
AI代码解释
复制
PublicAdditionalFrameworks.Add(new Framework("SurveyPopupView", libPath, ""));

如果构建后,在 Binaries/IOS/Payload/xxx.app 中,没有看到对应的 framework,那么打开构建后的app时会crash,报错:dyld: Library not loaded: @rpath/xxx.framework

看了 Unreal 论坛关于这个问题各种讨论之后,我最终还是使用了通过 UPL.xml 中copyDir 的方式复制 framework,参考 https://rassadin.net/swift-frameworks-unreal/

Unreal 构建工具会把 embeddedframework.zip 文件解压到 $S(EngineDir)/Intermediate/UnzippedFrameworks 这个目录,绝对路径一般是/Users/Shared/Epic Games/UE_4.xx/Engine/Intermediate/UnzippedFrameworks

代码语言:html
AI代码解释
复制
<?xml version="1.0" encoding="utf-8"?>
<root>
    <init>
        <copyDir src="$S(EngineDir)/Intermediate/UnzippedFrameworks/SurveyPopupView/SurveyPopupView.embeddedframework/SurveyPopupView.framework" dst="$S(BuildDir)/Frameworks/SurveyPopupView.framework"/>
    </init>
</root>

然后在 .Build.cs iOS 部分再添加一行:

代码语言:c#
AI代码解释
复制
AdditionalPropertiesForReceipt.Add("IOSPlugin", Path.Combine(moduleDir, "ImurSurveyPlugin_iOS_UPL.xml"));
调用 Framework 中的方法

因为在我在 object-c 中已经使用 extern "C" 暴露了可供调用的 C 函数,所以在 Public/ImurSurvey.h 头文件中,使用 extern 确保正确的链接规则,并声明这些函数即可:

代码语言:c++
AI代码解释
复制
#ifdef __cplusplus
extern "C" {
#endif
	extern void ImurOpenSurvey(const char* surveyId, const char* params);
	extern void ImurCloseSurvey(void);
	extern void ImurSetSurveyPopupConfig(const char* configJson);
	extern void ImurEnableLog(bool enable);
#ifdef __cplusplus
}
#endif

// 使用
void Open(FString surveyId, FString params)
{
	ImurOpenSurvey(TCHAR_TO_UTF8(*surveyId), TCHAR_TO_UTF8(*params));
}

集成 Android jar 包

在 UE 中,集成原生安卓的包有多种方式,可以使用 Java源码、aar、jar 等方式。在调试阶段,建议先直接使用源码方式,然后再根据情况选择 jar 或者 aar 的方式引入。

先说源码的方式,把 Java 的代码放到 Source/ThirdParty/Android 目录下,保持和原来的结构一致:

代码语言:txt
AI代码解释
复制
Android
├── java
│   ├── res
│   │   ├── drawable
│   │   ├── layout
│   │   ├── values
│   │   └── values-en
│   └── src
│       └── com
└── libs
    └── tbs_sdk_thirdapp_v4.3.0.386_44286_sharewithdownloadwithfile_withoutGame_obfs_20230210_114429.jar

因为我们需要在安卓中使用 Dialog 组件,所以必须确保在 UI 线程中调用,使用一个 JNIAdapter 的辅助类来桥接 C++ 的代码:

代码语言:java
AI代码解释
复制
public static void openSurvey(final NativeActivity activity, final String surveyID, final String urlParams) {
    activity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            openSurvey(activity, surveyID, urlParams);
        }
    });
}

然后在 C++ 中使用 AndroidJNI 的方法调用 JNIAdapter 中 Java 的方法:

代码语言:c++
AI代码解释
复制
#include "Android/AndroidJNI.h"
#include "Android/AndroidApplication.h"

void Open(FString surveyId, FString params)
{
	if (JNIEnv* Env = FAndroidApplication::GetJavaEnv(true))
	{
		jclass Class = FAndroidApplication::FindJavaClass("com/tencent/imur/survey/ImurSurveyJNIAdapter");
		jmethodID Method = Env->GetStaticMethodID(Class, "openSurvey", "(Landroid/app/NativeActivity;Ljava/lang/String;Ljava/lang/String;)V");
		jobject Activity = FAndroidApplication::GetGameActivityThis();
		jstring SurveyIdJava = Env->NewStringUTF(TCHAR_TO_UTF8(*surveyId));
		jstring ParamsJava = Env->NewStringUTF(TCHAR_TO_UTF8(*params));
		Env->CallStaticVoidMethod(Class, Method, Activity, SurveyIdJava, ParamsJava);
		Env->DeleteLocalRef(Class);
		Env->DeleteLocalRef(SurveyIdJava);
		Env->DeleteLocalRef(ParamsJava);
	}
}

记得在 .Build.cs 中的安卓部分引入 Launch 的依赖:PublicDependencyModuleNames.Add("Launch");

安卓 UPL.xml 文件的编写比 iOS 复杂的多,而且每一项配置都是有意义的,所有有必要说明一下 UPL 中的重点语法:

resourceCopies
代码语言:html
AI代码解释
复制
<resourceCopies>
    <copyDir src="$S(PluginDir)/ThirdParty/Android/libs/" dst="$S(BuildDir)/libs/" />
    <copyDir src="$S(PluginDir)/ThirdParty/Android/java/" dst="$S(BuildDir)" />
</resourceCopies>

把源代码复制到 BuildDir,一定要注意文件路径。

buildGradleAdditions
代码语言:html
AI代码解释
复制
<buildGradleAdditions>
    <insert>
        allprojects {
	        repositories {
		        flatDir {
		        	dirs 'src/main/libs'
	        	}
        	}
        }
        dependencies {
        	compile fileTree(include: '*.jar', dir: 'libs')
        }
    </insert>
</buildGradleAdditions>

flatDir 指定了 Gradle 会在这个目录中查找jar文件和aar文件,dependencies 用于指定项目的依赖项的,告诉Gradle在libs目录下查找所有的.jar文件,并将它们作为编译时依赖项添加到项目中。

androidManifestUpdates
代码语言:html
AI代码解释
复制
<androidManifestUpdates>
    <uses-permission android:name="android.permission.INTERNET" />
</androidManifestUpdates>

如果需要获取相关权限,需要使用 androidManifestUpdates 来更新 Android 应用的 Manifest 文件。

gameActivityImportAdditions
代码语言:html
AI代码解释
复制
<gameActivityImportAdditions>
    <insert>
        import com.tencent.imur.survey.ImurSurveyJNIAdapter;
    </insert>
</gameActivityImportAdditions>

添加额外的导入语句到 GameActivity.java 文件中,该文件是 Unreal 为 Android 应用生成的主活动文件。这里我们把上面创建的桥接java的 JNIAdapter 类导入。

proguardAdditions
代码语言:html
AI代码解释
复制
<proguardAdditions>
    <insert>
        -keep class com.tencent.smtt.** { *; }
        -keep public class com.tencent.imur.survey.ImurSurveyJNIAdapter
    </insert>
</proguardAdditions>

ProGuard 是 Android 中用于缩小、优化和混淆代码的工具,但是,有时ProGuard可能会删除或更改应用中重要的类和方法,这可能会导致运行时错误。使用 keep class 告诉 ProGuard 保留我们所依赖的libs包及其子包中的所有类和它们的所有成员(包括字段和方法)。JNIAdapter 类也一定要保留,确保它不会被 ProGuard 删除或更改,不然在编译安卓阶段会导致依赖找不到的问题。

构建安卓应用时 R 类找不到的问题
代码语言:txt
AI代码解释
复制
IMurLayout.java:17: 错误: 找不到符号
import com.tencent.imur.survey.webview.R;
                                      ^
符号:   类 R
位置: 程序包 com.tencent.imur.survey.webview

R 类是一个在 Android 开发中自动生成的类,它提供了对项目 res(资源)目录中资源的引用,每当你在 res 目录中添加一个新的资源(例如,一个新的布局 XML 文件、图片、字符串资源等),Android 构建系统会在 R 类中为该资源生成一个新的静态字段。但是在 Unreal 中,引用 Android 资源(通过R类)会有些不同,因为 Unreal Engine 的构建系统不会为你的 Java 代码生成一个传统的R类,最好解决方案是在 Java源码中通过完全限定的资源ID来引用资源: context.getResources().getIdentifier("com.example.myapp:id/web_close_btn", null, null);

jar 包集成的方式

从 Java 源码集成的方式修改成 jar 包的形式非常简单,保持原有的目录结构和 JNIAdapter 类源码,然后打包成 aar 之后,把 aar 中的 jar 包,放在 lib 文件夹中,然后在 proguardAdditions 中加上 keep class 你的类名 ,删除原来的 Java 源码就可以了。

代码语言:html
AI代码解释
复制
<proguardAdditions>
    <insert>
    	<!-- 其他规则... -->
        -keep class com.tencent.imur.** { *; }
    </insert>
</proguardAdditions>

最终的目录结构:

代码语言:txt
AI代码解释
复制
Android
├── java
│   ├── res
│   │   ├── drawable
│   │   ├── layout
│   │   ├── values
│   └── src
│       └── com
│           └── tencent
│               └── imur
│                   └── survey
│                       └── ImurSurveyJNIAdapter.java
└── libs
    ├── imur_survey_popupview.jar
    └── tbs_sdk_thirdapp_v4.3.0.386_44286_sharewithdownloadwithfile_withoutGame_obfs_20230210_114429.jar

【新手篇】如何创建一个UE项目,并绑定 C++ 中的方法

1. 创建空白项目

按照以下步骤,创建一个空白的 UE 项目

s1
s1
s2
s2
s3
s3

如果在mac电脑上遇到 "No compiler was found in order to use C++ template, you must first install Xcode" 这个报错,在 Unreal Editor 的设置中的 Source Code ––> Source Code Editor 选择 "Xcode" 即可。

s4
s4

2. 创建按钮

Button1
Button1

点击顶部的 "Content" ,然后在"内容浏览器"的空白区域右键单击,选择 "User Interface" => "Widget Blueprint",创建完成之后,可以重命名 Widget,然后双击打开,拖动左边栏的 "common" 下面的 UI 组件,比如 Button 和 Text,在右边的区域可以设置组件的样式、文本等。

Button2
Button2

修改完成之后,不要忘记点击左上角的 "Compile"。

3. 创建 GameMode

同样的,在"内容浏览器"中右键单击,然后选择 "Blueprint Class"。在弹出的窗口中,选择"GameModeBase"作为父类(或者如果需要更多控制,选择"GameMode"),然后点击"选择"。为新的Blueprint命名,例如"MyGameMode"。

MyGameMode
MyGameMode

4. 把按钮添加到游戏中

在顶部菜单中选择 "Edit" -> "Project Settings" -> "Maps and Modes",在 Default GameMode 选项中选择刚刚创建的 "MyGameMode"。

gameMode
gameMode

点击顶部菜单的"Blueprints" -> "Open Level Blueprint"。

blueprint
blueprint

在 Level Blueprint 中,右键单击并添加一个 "Event Begin Play" 节点(如果还没有)。从 "Event Begin Play" 节点拖出一个线,并添加一个 "Create Widget" 节点。

在 "Create Widget" 节点中,从 Class 下拉菜单中选择您的按钮Widget类(例如"MyButtonWidgetBlueprint")。再次拖出一个线,并添加一个 "Add to Viewport" 节点,并连接 "Return Value" 节点。

Level
Level

点击顶部菜单的“Compile”按钮,保存好 Level 之后,关闭 Level Blueprint 编辑,在项目设置的“Maps & Modes”中,选择默认的 Level:

level
level

点击顶部菜单的“Play”按钮来运行游戏,就可以看到我们刚刚添加的按钮了。

Play
Play

5. 创建 C++ 文件

在顶部 "file" 菜单中选择 "New C++ class" ,继承 Object ,选择 "Public" class,Path 使用默认的就好。生成文件之后,比如我的 class 名是 MyTestObject,在 项目根目录/Source/项目名/Public项目根目录/Source/项目名/Private 中可以看到生成的文件。

create_c++
create_c++

编辑一下,增加一个 Click 事件,并使用宏绑定到 Blueprint 中

MyTestObject.h

代码语言:c++
AI代码解释
复制
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once

#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "MyTestObject.generated.h"

UCLASS(Blueprintable, BlueprintType)
class EMPTYUEPROJECT_API UMyTestObject : public UObject
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintCallable, Category = "Button")
	void ButtonClicked();
};

MyTestObject.cpp

代码语言:c++
AI代码解释
复制
#include "MyTestObject.h"

void UMyTestObject::ButtonClicked()
{
	UE_LOG(LogTemp, Warning, TEXT("Button clicked!"));
}

修改完成之后,记得编译 C++ 文件。

6. 绑定 C++ 事件到 Button 组件

回到"内容浏览器",双击 ButtonWidget ,进入 Blueprint,并点击 Grapha。新建一个变量,并把类型设置为刚刚创建的 C++ 的类: MyTestObject。变量名的话,我这里使用的是: MyTestObjectInstance。

b1
b1

在编辑器中右键生成 Event ConstructGet Game Instance 节点,从 Event Construct 拖出一条线,选择 Construct Object from class,选择 MyTestObject ,并按照下图连接好各个节点。

b2
b2

把变量拖到编辑器,拖出一条线,选择 ButtonClicked,然后选择 Button 变量,点击下面的 Click 事件,生成节点,并连接好。

b3
b3

再次点击 Play ,点击按钮,我们就可以在 Output log 中,看到输出的文本了。

output
output

UE 打包真机的 iOS 和安卓 app

iOS

iOS 打包配置相对来说更简单,只要选择正确的证书和签名即可:

iOS_platform
iOS_platform
常见问题
1、 __has_trivial_assign __has_trivial_copy 编译错误
代码语言:txt
AI代码解释
复制
UATHelper: Packaging (iOS):   /Users/Shared/Epic Games/UE_4.27/Engine/Source/Runtime/Core/Public/Templates/IsTriviallyCopyAssignable.h:13:17: error: builtin __has_trivial_assign is deprecated; use __is_trivially_assignable instead [-Werror,-Wdeprecated-builtins]
UATHelper: Packaging (iOS):           enum { Value = __has_trivial_assign(T) }
...
UATHelper: Packaging (iOS):   /Users/Shared/Epic Games/UE_4.27/Engine/Source/Runtime/Core/Public/HAL/Event.h:122:18: note: in instantiation of template class 'TAtomic<unsigned int>' requested here
UATHelper: Packaging (iOS):           TAtomic<uint32> EventStartCycles;
UATHelper: Packaging (iOS):                           ^
PackagingResults: Error: builtin __has_trivial_copy is deprecated; use __is_trivially_copyable instead [-Werror,-Wdeprecated-builtins]
PackagingResults: Error: builtin __has_trivial_assign is deprecated; use __is_trivially_assignable instead [-Werror,-Wdeprecated-builtins]

一般这种问题是由于 Xcode 版本过高,UE4的话,建议选择 Xcode14及以下版本,使用 xcodes 这个软件可以比较方便的管理 Xcode 版本。

iOS_build_err
iOS_build_err
2、证书、签名问题相关
代码语言:txt
AI代码解释
复制
Error        PackagingResults          CodeSign Failed
Error        PackagingResults          AutomationTool was unable to run successfully.
Error        PackagingResults          Failed to Code Sign

之前使用免费证书,在 unreal 编辑器构建一直失败,主要是签名的问题,可以在 Intermediate/ProjectFilesIOS 中打开 xcodeproj ,自己在 xcode 中选择证书和签名并构建。或者充值一个苹果开发者,生成一个 provision ,导入到 project setting 中即可。折腾免费版证书半天之后,我选择了充钱解决。

配置好 teamId 并选择 Automatic Signing 即可:

sign
sign

打包安卓

打包安卓相对麻烦很多,因为依赖的环境更多。首先要安装对应版本的 Java 和 Anroid Studio(最好按照官方指定的版本,不然大概率踩坑,反正我踩过了🤦‍♂️),可以查看官方的文档:

v
v

然后跟着官方的文档一步步操作:https://docs.unrealengine.com/4.27/en-US/SharingAndReleasing/Mobile/Android/Setup/AndroidStudio/

这是我在Mac上的配置:

sdk
sdk
常见问题

我也不知道常不常见,反正我都遇到了,🤦‍♂️

1、如何打包 Arm64 架构

在 Android -> Build 中选择 arm64

arm
arm
2、 直接 Launch ,运行报错 "Failed to open descriptor file ../../.uproject"

使用安卓 build 目录中的 Install_UE4demo-arm64.command 安装

3、安卓启动报错 Error: CDO Constructor
run_err
run_err

.uproject 中禁用 OculusVR 插件

代码语言:json
AI代码解释
复制
{
	"Name": "OculusVR",
	"Enabled": false
}
4、安卓启动报错 No Google Play Store Key, No OBB found ...
obb
obb

在项目设置的Android Packing 配置中,禁用 OBB:

obb2
obb2

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
21 条评论
热度
最新
你好,有用UE集成过远程推送嘛? ios端
你好,有用UE集成过远程推送嘛? ios端
11点赞举报
都是用 usb 打包的,只是用来测试用的
都是用 usb 打包的,只是用来测试用的
回复回复点赞举报
android和ue的交互已经完成,不论是ue打包到android中,还是android集入到ue中(作者博客内容)都做好demo了,特别感谢作者的无私分享,内容s是我研究的所有博客中,最详细的一篇,再次感谢作者的无私分享。
android和ue的交互已经完成,不论是ue打包到android中,还是android集入到ue中(作者博客内容)都做好demo了,特别感谢作者的无私分享,内容s是我研究的所有博客中,最详细的一篇,再次感谢作者的无私分享。
11点赞举报
demo 在哪里,想研究一下
demo 在哪里,想研究一下
回复回复点赞举报
大佬研究过soLoadLibrary吗,能说说soLoadLibrary的使用方法,感觉像集成android项目的module
大佬研究过soLoadLibrary吗,能说说soLoadLibrary的使用方法,感觉像集成android项目的module
回复回复点赞举报
您的文章挺好,但是我使用android集入ue时遇到几个问题,方面私下交流下吗,wx:13521851585
您的文章挺好,但是我使用android集入ue时遇到几个问题,方面私下交流下吗,wx:13521851585
1515点赞举报
具体是什么问题呢?是出包阶段还是集成的阶段?
具体是什么问题呢?是出包阶段还是集成的阶段?
回复回复点赞举报
2个问题,一个是集成aar和jar包时报错,找不到包,后面我把aar和jar去掉,单纯的创建了一个android方法,然后APL.xml调用处理,结果也报错,告诉我缺少android资源
2个问题,一个是集成aar和jar包时报错,找不到包,后面我把aar和jar去掉,单纯的创建了一个android方法,然后APL.xml调用处理,结果也报错,告诉我缺少android资源
回复回复点赞举报
查看全部15条回复
推荐阅读
编辑精选文章
换一批
Unity与Android Studio✨之间那些不清不楚的小秘密✨(Android Studio与unity交互)
前言:因为最近在学习Unity与安卓之间的交互,所以在网上搜寻了很多关于这方面的东西。因为自己在网上搜的时候,感觉大家的东西都有些零碎,该有的差不多都有了,但是都不够全面,所以自己写篇文章用来整理这些精华 Unity与Android Studio互相调用的知识给大家分享一下
呆呆敲代码的小Y
2021/08/12
4.1K0
Unity-SDK接入
游戏客户端和第三方包进行组合 第三方代码: JAVA代码 游戏U3D代码 eclipse AndroidStudio
祝你万事顺利
2019/06/20
2.6K0
Unity-SDK接入
游戏开发完整学习路线(各个版本都有)
在软件开发中,游戏开发这个方向看起来目标很明确,但其实是个领域很广的方向,入门的时候如果得不到指点一二,很容易误入歧途,相反,如果走这条路之前能得到前人的一些指路,是可以事半功倍的。 一 平台与编程语言选择 首先,游戏开发的平台就有很多类型:  个人主机平台:Windows、Linux、Mac OC; 移动平台:iOS、Android、Windows Phone、BlackBerryOS、Symbian; 专业主机平台:Xbox、PlayStation、Will等。 如果你想从事移动平台的游戏开发,An
用户1198337
2018/01/19
3.1K0
游戏开发完整学习路线(各个版本都有)
【Unity3D】Android Studio 工程中使用 Java 代码调用 Unity 的 C# 脚本 ( Java 中调用 UnityPlayer#UnitySendMessage 方法 )
在 Android 中调用 Unity 的 C# 脚本 , 需要借助 Unity 官方提供的依赖库进行 ; 在 Unity 编辑器的安装目录中 ,
韩曙亮
2023/03/30
2.2K0
【Unity3D】Android Studio 工程中使用 Java 代码调用 Unity 的 C# 脚本 ( Java 中调用 UnityPlayer#UnitySendMessage 方法 )
Unity与Android交互之✨| 使用AndroidJavaProxy代理方式,让Android与Unity通讯
下面我们就先从Android Studio端开始一步一步做起,Android Studio下面统称AS
呆呆敲代码的小Y
2021/10/29
3.9K0
Unity与Android交互之✨| 使用AndroidJavaProxy代理方式,让Android与Unity通讯
Unity 和 Android 的工程集成
有时候,我们需要在 Unity 里调用一些 Android 的功能,这些功能在 Unity 中可能并没有提供接口,需要在 Android 平台上实现。此时,我们需要有一个方法来让 Android 代码和 Unity 代码互调用。这里记录一下操作方法,并提供一个工具来简化两个工程之间的集成流程。
zhiruili
2023/10/20
6770
Unity 和 Android 的工程集成
Android 与 Unity扯不清的关系
近期在游戏SDK接入的技术支持中,不断有游戏反馈希望有现成的unity插件可以直接接入,为了减轻和方便游游戏方接入,对SDK进行unity的插件开发
包子388321
2020/06/16
2.2K0
u3d与安卓交互(Android studio)
AndroidStudio导出 .jar文件,在Unity里使用 开发环境:as2.3.2.0,u3d5.6.0
立羽
2023/08/24
2750
u3d与安卓交互(Android studio)
unity和android的项目交互
由于近期工作要求需要给实现unity5.6.5上打包android的项目,个人算是研究一天左右,才完成这个工作,将自己遇到的坑和一些学习操作的过程,总结一下与大家分享。
包子388321
2020/06/16
2.3K0
【Unity游戏开发】SDK接入与集成——小白入门篇
  通常一款游戏开发到后期,一般都会涉及到第三方SDK的接入与集成,对于不熟悉SDK接入的同学来说,接SDK每次都是云里雾里,而熟悉SDK接入的同学又觉得不断地重复做接入SDK工作这样没有成就感,太尼玛无聊了(Android渠道一弄就十几个,直接吐血)。其实通常情况下接入SDK都是很简单的一个过程,本系列博客就让马三和大家从小白开始,从零基础开始学习如何接入SDK以及一些常见的SDK的接入流程。本系列博客规划为以下几篇:
马三小伙儿
2018/09/12
5.6K2
【Unity游戏开发】SDK接入与集成——小白入门篇
Unity与Android调用交互
AS 和 Unity 之间如何通信。AS 和 Unity 之间通信的方法介绍如下:
呆呆敲代码的小Y
2021/08/12
1.3K0
unity3d+androidstudio:接微信官方分享sdk
1.得到的签名在微信后台一定要填对,不然返回-6 2.如果测试微信调不起来,清除微信缓存,即可,因为上次的错误信息保存了
立羽
2023/08/24
2400
unity3d+androidstudio:接微信官方分享sdk
零基础入门 30:获取移动端手机的电量/时间/网络
大家在玩手游的时候经常会看到游戏里有一些提醒状态,图示如下,右上角有当前手机端的时间,wifi网络状态展示,以及电量的展示效果
韩东吉
2018/10/19
1.1K0
零基础入门 30:获取移动端手机的电量/时间/网络
【Unity】QQ登录SDK接入(Unity&Android)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
bering
2019/12/03
2.9K0
Android/Unity大乱斗-完整双方集成交互指南
源码地址:https://github.com/RXlung/Android-Unity---
芝麻粒儿
2021/08/03
1.4K0
Android/Unity大乱斗-完整双方集成交互指南
Unity Android Plugin开发指南
本文将介绍如何在Unity工程中使用Android或者Java的库,包括: 如何在Unity项目中使用Android Plugin Unity-Android相互调用 Unity接口设计的最佳实践 如何构建Unity-Android混合项目 如何调试Unity和Android代码 附录:跨虚拟机调用的实现 如何在Unity项目中使用Android Plugin Android Plugin需要包含一个jar和对应的封装代码。后者用来封装Android代码,提供给Unity项目使用。 jar放在Unity项目
QQ音乐技术团队
2018/01/31
8.3K3
Unity Android Plugin开发指南
Unity3D与Android的交互通信(Unity3D)
&emsp; 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧。
恬静的小魔龙
2022/08/07
2.3K0
Unity3D与Android的交互通信(Unity3D)
【Unity3D】Unity 中使用 C# 调用 Java ③ ( C# 调用 Java 实例 | 进行 Android 工程打包 | Android Studio 中运行 Android 工程 )
在 【Unity3D】Android 打包 ④ ( Android 工程打包 | Unity 中导出安卓工程 | Android Studio 打开 Unity 导出的 Android 工程 ) 博客中将 Unity 项目导出为了 Android 项目 , 并在 Android Studio 中编译并运行了该项目 ;
韩曙亮
2023/03/30
1.8K0
【Unity3D】Unity 中使用 C# 调用 Java ③ ( C# 调用 Java 实例 | 进行 Android 工程打包 | Android Studio 中运行 Android 工程 )
Unity编译Android的原理解析和apk打包分析
张坤
2017/01/17
7.4K0
unity+android:大版本更新安装下好的apk,兼容任意安卓5.0,7.0,8.0版本
Android Studio 1:在项目的res目录下创建xml目录,再创建file_paths.xml文件。
立羽
2023/08/24
4380
unity+android:大版本更新安装下好的apk,兼容任意安卓5.0,7.0,8.0版本
推荐阅读
相关推荐
Unity与Android Studio✨之间那些不清不楚的小秘密✨(Android Studio与unity交互)
更多 >
LV.1
腾讯高级开发工程师
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档