update
This commit is contained in:
@@ -303,4 +303,65 @@ https://tianchi.aliyun.com/dataset/93864
|
||||
- 将 tuanjieLibrary/build.gradle 替换为完整的 Android library 模块构建文件(apply plugin: 'com.android.library'),
|
||||
参考 launcher/build.gradle 的配置(compileSdkVersion、ndkVersion、ndkPath、aaptOptions、buildTypes 等),
|
||||
并在 dependencies 中添加 implementation files('libs/unity-classes.jar')。
|
||||
- 注意:每次从 Tuanjie 重新导出后都需要重新替换该文件。
|
||||
- 注意:每次从 Tuanjie 重新导出后都需要重新替换该文件。
|
||||
|
||||
14. 从 Unity 导出 Android 项目(IL2CPP)推荐步骤
|
||||
下面按 Unity 2021/2022+ 通用流程写(菜单名可能略有差异,但逻辑一致)。
|
||||
|
||||
1. 切到 Android 平台
|
||||
File → Build Settings…
|
||||
左侧选中 Android
|
||||
若未切换过,点 Switch Platform(等切换完成)
|
||||
2. Player Settings(Android)
|
||||
Build Settings 窗口里点 Player Settings…(或 Edit → Project Settings → Player)
|
||||
|
||||
选中 Android 图标(或 Android 标签页)
|
||||
|
||||
在 Other Settings 里检查并设置:
|
||||
|
||||
Scripting Backend:选 IL2CPP
|
||||
Target Architectures:勾选 ARM64(你现在 app 的 abiFilters 也是 arm64-v8a,要一致)
|
||||
Minimum API Level:与你们 Android 工程要求一致(你工程 minSdk 22,Unity 不要设得更高除非你有意为之)
|
||||
(可选但常见)Publishing Settings / Keystore:导出后若要直接装真机,后面 Build 时可用 debug;发版再配正式签名。
|
||||
|
||||
3. 选择导出方式
|
||||
在 Build Settings:
|
||||
|
||||
Export Project ✅ 勾选(你们要集成到现有 Android Studio 工程,必须勾)
|
||||
Development Build:调试可开,发版关
|
||||
4. Export 输出目录
|
||||
点 Export(不要只点“生成文件夹”就关掉),选一个空目录或新版本目录,例如:
|
||||
|
||||
D:\unity_export\MyProject_Android_IL2CPP_20260424\
|
||||
|
||||
等 Unity 完整跑完(控制台无失败)。
|
||||
|
||||
5. 在导出结果里确认 libil2cpp.so
|
||||
在导出根目录里找 unityLibrary(或你们模块名):
|
||||
|
||||
unityLibrary\src\main\jniLibs\arm64-v8a\libil2cpp.so
|
||||
同目录通常还有 libmain.so、libunity.so 等
|
||||
若这里仍然没有,再回到 Player Settings → Android → Scripting Backend 逐项核对(尤其是是否被 Override 成 Mono)。
|
||||
|
||||
6. 集成到你们 digital_person 工程
|
||||
原则:同一轮 Export 的 jniLibs/arm64-v8a 整包拷贝到你们 tuanjieLibrary/src/main/jniLibs/arm64-v8a/(或你们实际使用的 Unity module),不要“只替换较新文件”,也不要混两次导出的 so。
|
||||
|
||||
15. Unity导出安卓工程目录之后,找不到 libil2cpp.so,可以通过先不export,先编译出apk,得到这个so,然后复制到对应的目录下:
|
||||
|
||||
power shell 命令
|
||||
# 源文件路径
|
||||
$source = "C:\Users\42087\My project\Library\Bee\Android\Prj\IL2CPP\Gradle\tuanjieLibrary\build\intermediates\stripped_native_libs\release\out\lib\arm64-v8a\libil2cpp.so"
|
||||
|
||||
# 目标路径(你的导出工程)
|
||||
$targetDir = "D:\code\digital_person\tuanjieLibrary\src\main\jniLibs\arm64-v8a"
|
||||
|
||||
# 创建目标目录(如果不存在)
|
||||
New-Item -ItemType Directory -Force -Path $targetDir
|
||||
|
||||
# 复制文件
|
||||
Copy-Item -Path $source -Destination $targetDir -Force
|
||||
|
||||
# 验证复制成功
|
||||
Get-ChildItem -Path $targetDir\libil2cpp.so | Select-Object Name, Length
|
||||
|
||||
16. 有些Unity导出的问题,可以参考:https://blog.csdn.net/weixin_45774916/article/details/144171875
|
||||
@@ -503,6 +503,10 @@ class UnityDigitalPersonActivity : UnityPlayerActivity(), LifecycleOwner {
|
||||
val filteredText = ttsController.speakLlmResponse(finalText)
|
||||
Log.d("UnityDigitalPerson", "LOCAL filtered: ${filteredText?.take(60)}")
|
||||
if (filteredText != null) appendChat("助手: $filteredText")
|
||||
// 本地 LLM 回复也要进入互动状态机:否则不会进入 WAITING_REPLY / PROACTIVE 的计时流程
|
||||
val spoken = filteredText ?: finalText.trim()
|
||||
maybeShowMatchedRefImage(spoken)
|
||||
interactionCoordinator.onCloudFinalResponse(spoken)
|
||||
}
|
||||
localThoughtSilentMode = false
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ object AppConfig {
|
||||
const val SAMPLE_RATE = 16000
|
||||
const val WINDOW_SIZE = 512
|
||||
|
||||
const val SHOW_DEBUG_TEXT = true
|
||||
const val SHOW_DEBUG_TEXT = false
|
||||
const val USE_HOLD_TO_SPEAK = true // true: 按住说话, false: 传统按钮
|
||||
|
||||
object Tts {
|
||||
|
||||
@@ -148,12 +148,13 @@ abstract class BaseDigitalPersonCoordinator(
|
||||
* (i.e. after a cloud LLM response), NOT after greeting / farewell / proactive TTS.
|
||||
*/
|
||||
fun onTtsPlaybackCompleted() {
|
||||
// Let the controller advance its own timers (greeting/proactive/dlg all count as assistant speaking).
|
||||
controller.onAssistantTtsPlaybackCompleted()
|
||||
if (pendingDialogueFinish) {
|
||||
pendingDialogueFinish = false
|
||||
controller.onDialogueResponseFinished()
|
||||
}
|
||||
// Let the controller advance its own timers after state transitions above.
|
||||
// (greeting/proactive/dlg all count as assistant speaking)
|
||||
controller.onAssistantTtsPlaybackCompleted()
|
||||
}
|
||||
|
||||
fun isLlmInFlight(): Boolean = llmInFlight
|
||||
|
||||
@@ -7,6 +7,27 @@
|
||||
android:background="@android:color/transparent"
|
||||
tools:context="com.digitalperson.UnityDigitalPersonActivity">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline_mid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.5" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ref_match_image"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="0dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="@+id/guideline_mid"
|
||||
app:layout_constraintBottom_toTopOf="@+id/button_row"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/scroll_view"
|
||||
android:layout_width="0dp"
|
||||
@@ -14,10 +35,12 @@
|
||||
android:layout_margin="12dp"
|
||||
android:background="#55000000"
|
||||
android:fillViewport="true"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/button_row"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/my_text"
|
||||
@@ -31,18 +54,6 @@
|
||||
android:textIsSelectable="true" />
|
||||
</ScrollView>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ref_match_image"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="200dp"
|
||||
android:layout_margin="12dp"
|
||||
android:background="#66000000"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/button_row"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_row"
|
||||
android:layout_width="0dp"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<string name="start">开始</string>
|
||||
<string name="stop">结束</string>
|
||||
<string name="hint">点击“开始”说话;识别后会请求大模型并用 TTS 播放回复。</string>
|
||||
<string name="system_prompt">你是一个特殊学校一年级的数字人老师,你的名字叫,小鱼老师,你的任务是教这些特殊学校的学生一些基础的生活常识,如生活语文,生活数学,生活适应等课程。和这些小学生说话要有耐心,一定要讲明白,尽量用简短的语句、活泼的语气来回复。你可以和他们日常对话和《教材》相关的话题。在生成回复后,请你先检查一下内容是否符合我们约定的主题。请使用口语对话的形式跟学生聊天。在每次回复的最前面,用方括号标注你的心情,格式为[中性、悲伤、高兴、生气、恐惧、撒娇、震惊、厌恶],例如:[高兴]同学你好呀!请问有什么问题吗?</string>
|
||||
<string name="system_prompt">你是一个特殊学校一年级的数字人老师,你的名字叫,小鱼老师,你是女性,你的任务是教这些特殊学校的学生一些基础的生活常识,如生活语文,生活数学,生活适应等课程。和这些小学生说话要有耐心,一定要讲明白,尽量用简短的语句、活泼的语气来回复。你可以和他们日常对话和《教材》相关的话题。在生成回复后,请你先检查一下内容是否符合我们约定的主题。请使用口语对话的形式跟学生聊天。在每次回复的最前面,用方括号标注你的心情,格式为[中性、悲伤、高兴、生气、恐惧、撒娇、震惊、厌恶],例如:[高兴]同学你好呀!请问有什么问题吗?</string>
|
||||
|
||||
<!-- Unity 的字符串
|
||||
有人建议是: 将Launcher/src/main/res/values/strings.xml 文件拷贝进unityLibrary/src/main/res/values/里,这样做的确就避免了那个变量值为0 的问题。
|
||||
|
||||
Reference in New Issue
Block a user