android集成unity后动态导入 assetsBundle

1、Unity 中创建空物体 BundleLoader 并挂载脚本

csharp 复制代码
using System.Collections;
using System.Diagnostics;
using System.IO;
using UnityEngine;
using static System.Net.Mime.MediaTypeNames;

public class LoadSphereBundle : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(LoadSphere());


        // 测试 Android 或 Editor
        //#if UNITY_EDITOR
        //            string path = UnityEngine.Application.dataPath + "/AssetBundles/Android/spherebundle";
        //#else
        //        string path = UnityEngine.Application.persistentDataPath + "/spherebundle"; // Android 可读路径
        //#endif
        //        LoadSphereByPathBridge(path);
    }

    public IEnumerator LoadSphere()
    {
        // 正确的路径构建方式
        #if UNITY_EDITOR
                    // 编辑器模式下的路径
                    string path = UnityEngine.Application.dataPath + "/AssetBundles/Android/spherebundle";
        #else
            // 运行时模式下的路径(打包后)
            string path = UnityEngine.Application.streamingAssetsPath + "/spherebundle";
        #endif

        UnityEngine.Debug.Log("尝试从路径加载: " + path);

        // 加载 AssetBundle
        AssetBundle bundle = AssetBundle.LoadFromFile(path);
        if (bundle == null)
        {
            UnityEngine.Debug.LogError("Failed to load spherebundle from: " + path);
            UnityEngine.Debug.Log("请确认文件是否存在且路径正确");
            yield break;
        }

        // 加载 prefab
        GameObject spherePrefab = bundle.LoadAsset<GameObject>("sphere");
        if (spherePrefab != null)
        {
            Instantiate(spherePrefab, Vector3.zero, Quaternion.identity);
            UnityEngine.Debug.Log("成功加载并实例化 sphere prefab!");
        }
        else
        {
            UnityEngine.Debug.LogError("Failed to load prefab 'sphere' from bundle!");

            // 调试:列出bundle中所有资源
            UnityEngine.Debug.Log("Bundle中包含的资源:");
            foreach (string name in bundle.GetAllAssetNames())
            {
                UnityEngine.Debug.Log("- " + name);
            }
        }

        bundle.Unload(false);
    }




    // UnitySendMessage 调用入口
    public void LoadSphereByPathBridge(string path)
    {
        UnityEngine.Debug.Log("LoadSphereByPathBridge,收到 UnitySendMessage 调用, 路径 = " + path);
        StartCoroutine(LoadSphereByPath(path));
    }


    public IEnumerator LoadSphereByPath(string path)
    {
       
        UnityEngine.Debug.Log("尝试从路径加载: " + path);

        // 加载 AssetBundle
        AssetBundle bundle = AssetBundle.LoadFromFile(path);
        if (bundle == null)
        {
            UnityEngine.Debug.LogError("Failed to load spherebundle from: " + path);
            UnityEngine.Debug.Log("请确认文件是否存在且路径正确");
            yield break;
        }

        // 加载 prefab
        GameObject spherePrefab = bundle.LoadAsset<GameObject>("sphere");
        if (spherePrefab != null)
        {
            Instantiate(spherePrefab, Vector3.zero, Quaternion.identity);
            UnityEngine.Debug.Log("成功加载并实例化 sphere prefab!");
        }
        else
        {
            UnityEngine.Debug.LogError("Failed to load prefab 'sphere' from bundle!");

            // 调试:列出bundle中所有资源
            UnityEngine.Debug.Log("Bundle中包含的资源:");
            foreach (string name in bundle.GetAllAssetNames())
            {
                UnityEngine.Debug.Log("- " + name);
            }
        }

        bundle.Unload(false);
    }
}

2、android 中 使用 UnitySendMessage 调用 LoadSphereByPathBridge方法 加载 ab

(注意 assetsBundle 全部文件拷贝到 /storage/emulated/0/Android/data/com.example.dockwithtuanjie/files/ 目录下 )

csharp 复制代码
package com.example.dockwithtuanjie

// 在 app/src/main/java/你的包名/ 下创建 UnityFragment.kt   【step 1. 添加此文件】

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.unity3d.player.UnityPlayer


class UnityFragment : Fragment() {

    // 移除 static,使用 lateinit 延迟初始化
    lateinit var mUnityPlayer: UnityPlayer

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 初始化 UnityPlayer,使用 requireActivity() 作为 context
        mUnityPlayer = UnityPlayer(requireActivity())
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val view = mUnityPlayer.view
        // 防止视图已有父布局的重要检查
        if (view.parent != null) {
            (view.parent as ViewGroup).removeView(view)
        }
        // 设置窗口焦点监听
        view.viewTreeObserver.addOnWindowFocusChangeListener { hasFocus ->
            mUnityPlayer.windowFocusChanged(hasFocus)
        }
        return view
    }

    override fun onResume() {
        super.onResume()
        mUnityPlayer.resume()
    }

    override fun onPause() {
        super.onPause()
        mUnityPlayer.pause()
    }

    override fun onDestroy() {
        super.onDestroy()
        mUnityPlayer.quit()
    }


    fun send(msg: String?) {
        Log.d("UnityFragment", "我是unityFragment, 收到调用--->>> : $msg")
        UnityPlayer.UnitySendMessage("AutoCubeRotator", "OnMsg", msg)

        val a = 0.5;
        UnityPlayer.UnitySendMessage("AutoCubeRotator", "OnMsgToTransform", a.toString() )



        //-------------------------------->>>>> 动态加载测试
        val bundlePath = context?.getExternalFilesDir(null)?.absolutePath + "/spherebundle"
        Log.d("UnityFragment", "我是unityFragment, 尝试加载bundle路径--->>> : $bundlePath")
        UnityPlayer.UnitySendMessage("BundleLoader", "LoadSphereByPathBridge", bundlePath)
    }
}
相关推荐
石山岭10 小时前
自己动手写了一个 Android 虚拟定位 App:GPSSimulate 技术实
android·前端
杉氧12 小时前
副作用 (Side Effects) 全攻略:如何像大师一样掌控 Composable 的生命周期?
android·架构·android jetpack
Kapaseker17 小时前
Kotlin Toolchain 0.11 发布:主要是把 Amper 干没了
android·kotlin
三少爷的鞋18 小时前
Android 现代架构不需要事件总线进阶篇
android
杉氧1 天前
深入理解 Compose 重组机制:快照系统如何驱动 UI 精准刷新?
android·架构·android jetpack
召钱熏1 天前
状态枚举正确≠渲染正确:一个语音按钮的状态机边界修复实录
android·前端
杉氧1 天前
深度解析:Jetpack Compose 核心架构与底层原理 —— 十年安卓老兵的“破茧重生”
android·架构·android jetpack
通玄1 天前
Jetpack Compose 入门系列(七):ViewModel 与界面状态管理
android
落魄Android在线炒饭1 天前
Android Framework 开发技巧:android.jar 生成与系统快速编译验证
android
如此风景1 天前
Kotlin Flow操作符学习
android·kotlin