Unity+Vuforia运行时创建Image Target后Android端VideoPlayer异常排查
问题描述
我使用Unity 2022.3.15f搭配Vuforia 10.22.5,通过API在运行时创建Image Target,并为每个目标绑定带有VideoPlayer的Quad。该功能在Unity编辑器中运行完全正常,但打包为Android版本后,VideoPlayer的表现极差(卡顿、无法播放等)。我曾在Unity 2019.4.0f中开发过同类应用,当时是通过Vuforia Target Manager下载的数据库创建目标,未出现此问题,请问问题可能出在哪里?
相关代码
using System.Collections; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Video; using Vuforia; public class GetJson : MonoBehaviour { [SerializeField] private string url = "https://api.arstudio.kz/api/ar?groupId=82"; [SerializeField] private RootObject loadinfolist = new RootObject(); public GameObject Model; public UnityEngine.UI.Image LoadingLogo; private string path; private float loadProgress = 0.0f; private void Start() { path = Application.persistentDataPath; // Установка пути один раз VuforiaApplication.Instance.OnVuforiaInitialized += OnVuforiaInitialized; } void OnVuforiaInitialized(VuforiaInitError error) { StartCoroutine(SendReq()); } private IEnumerator SendReq() { using (UnityWebRequest request = UnityWebRequest.Get(url)) { yield return request.SendWebRequest(); if (request.result != UnityWebRequest.Result.Success) { Debug.Log(request.error); } else { loadinfolist = JsonUtility.FromJson<RootObject>(request.downloadHandler.text); StartCoroutine(WebAR()); } } } private IEnumerator WebAR() { foreach (Datum data in loadinfolist.data) { yield return StartCoroutine(DownloadAndSetupContent(data)); } } private IEnumerator DownloadAndSetupContent(Datum data) { yield return StartCoroutine(DownloadVideo(data.video_path, data.id, data.group_id)); yield return StartCoroutine(DownloadImageAndCreateTarget(data.file_path, data.id, data.group_id)); } private IEnumerator DownloadVideo(string videoPath, int id, int groupId) { string savePath = $"{path}/{id}_{groupId}.mp4"; using (UnityWebRequest uwr = UnityWebRequest.Get(videoPath)) { yield return uwr.SendWebRequest(); if (uwr.result == UnityWebRequest.Result.Success) { System.IO.File.WriteAllBytes(savePath, uwr.downloadHandler.data); loadProgress += 1.0f / loadinfolist.data.Length; LoadingLogo.fillAmount = loadProgress; Debug.Log("Video downloaded to: " + savePath); } else { Debug.Log(uwr.error); } } } private IEnumerator DownloadImageAndCreateTarget(string imagePath, int id, int groupId) { using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(imagePath)) { yield return uwr.SendWebRequest(); if (uwr.result == UnityWebRequest.Result.Success) { Texture2D texture = DownloadHandlerTexture.GetContent(uwr); CreateImageTargetFromDownloadedTexture(id, $"{path}/{id}_{groupId}.mp4", texture); } else { Debug.Log(uwr.error); } } } void CreateImageTargetFromDownloadedTexture(int id, string videoUrl, Texture2D img) { var mTarget = VuforiaBehaviour.Instance.ObserverFactory.CreateImageTarget(img, 1.0f, id.ToString()); mTarget.gameObject.AddComponent<DefaultObserverEventHandler>(); GameObject cube = Instantiate(Model, mTarget.transform); cube.transform.localScale = new Vector3(mTarget.GetSize().x, mTarget.GetSize().y, 1.0f); VideoPlayer player = cube.GetComponent<VideoPlayer>(); player.url = videoUrl; EventHandler eventHandler = mTarget.gameObject.AddComponent<EventHandler>(); Debug.Log("Target with video player created for: " + id); } } [System.Serializable] public class Group { [SerializeField] public int id; [SerializeField] public string name; [SerializeField] public string created_at; [SerializeField] public string updated_at; [SerializeField] public int user_id; } [System.Serializable] public class Datum { [SerializeField] public int id ; [SerializeField] public int group_id ; [SerializeField] public int user_id ; [SerializeField] public string file_path ; [SerializeField] public string video_path ; [SerializeField] public string mind_file_path ; [SerializeField] public string status ; [SerializeField] public int is_deleted ; [SerializeField] public string created_at ; [SerializeField] public string updated_at ; [SerializeField] public int width ; [SerializeField] public int height ; }
可能的问题排查方向
VideoPlayer平台配置与编码兼容性
- Unity 2022的VideoPlayer在Android平台的默认渲染模式可能不适合AR场景,建议将Render Mode切换为Material Override(编辑器里用Overlay能正常运行,但Android 3D空间中的Quad需要Material模式)。
- 检查视频编码:Android设备对H.265的支持不如H.264广泛,确保下载的MP4采用H.264 Baseline Profile编码,同时控制码率和分辨率匹配设备性能。
运行时资源加载与性能优化
- Vuforia 10运行时动态创建Image Target的性能开销比旧版本更高,同时未压缩的纹理会占用大量内存。在下载纹理后,添加
texture.Compress(true)将其转换为Android兼容的压缩格式(如ETC2),减少内存占用。 - 视频下载完成后,建议添加文件完整性校验(对比服务器返回的文件大小与本地文件大小),避免因文件损坏导致播放异常。
- Vuforia 10运行时动态创建Image Target的性能开销比旧版本更高,同时未压缩的纹理会占用大量内存。在下载纹理后,添加
Android存储路径与权限
- Android 10及以上的存储权限变更可能影响VideoPlayer读取本地文件,尝试给视频路径添加
file://前缀:player.url = "file://" + videoUrl;。 - 确保在AndroidManifest中添加了
READ_EXTERNAL_STORAGE权限(针对旧设备),或者使用Unity的Persistent Data Path的正确访问方式。
- Android 10及以上的存储权限变更可能影响VideoPlayer读取本地文件,尝试给视频路径添加
Vuforia与Unity版本适配
- Vuforia 10.22.5与Unity 2022.3.15f可能存在兼容性bug,尝试升级Vuforia到适配Unity 2022的最新版本,或降级Unity到2022.3的更早小版本测试。
事件处理组件冲突
- 创建Image Target时同时添加了
DefaultObserverEventHandler和自定义EventHandler,两者可能在目标识别/丢失时重复触发视频控制逻辑,导致播放混乱。建议只保留一个事件处理组件,或检查自定义EventHandler的逻辑是否与Default组件冲突。
- 创建Image Target时同时添加了
内容的提问来源于stack exchange,提问作者Сакен Карленов
相关产品推荐
相关产品推荐

