Unity安卓/iOS世界空间视频突然无法播放问题求助
Unity安卓/iOS平台世界空间视频播放功能失效问题解决
问题概述
原本在安卓、iOS平台正常运行的世界空间视频播放功能,新构建版本突然失效。旧构建版本仍可正常工作,即使复用旧版本代码生成新构建也无法恢复;Unity编辑器播放模式下功能正常,其他运行时下载加载模块在两个平台均无异常。
报错信息
- 安卓平台:
try-catch未捕获到任何错误或异常 - iOS平台:抛出错误
renderer "Video player", targeted by video player has no material with a texture property,Plane显示为洋红色
已尝试操作
- 更新并回退Unity版本,无效
- 改用网络URL替代本地下载视频,无效
- 手动添加VideoPlayer并设置URL,Plane仍显示洋红色,无法播放
涉事代码片段
try { string[] splitVidParams = { "0.0", "0.0", "0.1", "0.1" }; if (vidParams != "") { splitVidParams = vidParams.Split(';'); } Debug.Log("init video"); GameObject videoProjection = GameObject.CreatePrimitive(PrimitiveType.Plane); VideoPlayer videoPlayer = videoProjection.AddComponent<VideoPlayer>(); videoPlayer.playOnAwake = true; new Downloader().DownloadVideo(video, targetId); string videoSource = Application.persistentDataPath + "/importedModels/" + video; videoPlayer.url = videoSource; videoPlayer.source = VideoSource.Url; videoPlayer.isLooping = true; //Set render mode videoPlayer.renderMode = VideoRenderMode.MaterialOverride; GameObject instVideo = Instantiate(videoProjection, wrapper.transform); instVideo.transform.localScale = new Vector3(float.Parse(splitVidParams[2], CultureInfo.InvariantCulture) * 0.1f, 0.1f, float.Parse(splitVidParams[3], CultureInfo.InvariantCulture) * 0.1f); instVideo.transform.localPosition = new Vector3(float.Parse(splitVidParams[0], CultureInfo.InvariantCulture), 0f, float.Parse(splitVidParams[1], CultureInfo.InvariantCulture)); Destroy(videoProjection); instVideo.name = "Video Player"; instantiatedModels.Add(instVideo); MeshRenderer videoRenderer = instVideo.GetComponent<MeshRenderer>(); instVideo.transform.localEulerAngles = new Vector3(instVideo.transform.localEulerAngles.x, instVideo.transform.localEulerAngles.y + 180, instVideo.transform.localEulerAngles.z); } catch (Exception e) { Debug.LogError(e.Message); }
原因分析
- 移动端材质裁剪:Unity构建移动端包时,Shader Stripping机制可能移除了Plane默认材质依赖的Shader,导致运行时材质无效,显示洋红色
- MaterialOverride模式适配问题:默认Plane材质在移动端可能不具备VideoPlayer所需的可覆盖纹理属性,触发iOS的报错
- 实例化材质引用丢失:原
videoProjection被销毁后,实例化的instVideo可能无法正确保留材质引用,导致材质失效
解决方案
方案1:使用自定义材质替代默认材质
创建一个基于Unlit/Texture Shader的材质,提前放置在Resources目录或打包进AssetBundle,在创建Plane后替换默认材质:
GameObject videoProjection = GameObject.CreatePrimitive(PrimitiveType.Plane); MeshRenderer renderer = videoProjection.GetComponent<MeshRenderer>(); // 加载自定义材质 renderer.material = Resources.Load<Material>("VideoPlayerMaterial");
方案2:切换RenderTexture渲染模式
改用RenderTexture模式,手动创建渲染纹理并绑定到Plane材质:
// 创建RenderTexture RenderTexture videoRT = new RenderTexture(1920, 1080, 0, RenderTextureFormat.ARGB32); videoRT.Create(); VideoPlayer videoPlayer = videoProjection.AddComponent<VideoPlayer>(); // 设置渲染模式为RenderTexture videoPlayer.renderMode = VideoRenderMode.RenderTexture; videoPlayer.targetTexture = videoRT; // 将RenderTexture赋值给Plane材质 videoProjection.GetComponent<MeshRenderer>().material.mainTexture = videoRT;
方案3:调整Shader Stripping设置
- 打开
Edit > Project Settings > Graphics,找到Shader Stripping选项 - 禁用
Strip unused Shaders,或在Preloaded Shaders中添加Plane默认材质使用的Shader(如Standard Shader) - 进入
Edit > Project Settings > Player > Optimization,禁用Optimize Shaders for Mobile
方案4:修正实例化与销毁逻辑
确保实例化对象的材质引用正确,避免原对象销毁导致材质丢失:
GameObject videoProjection = GameObject.CreatePrimitive(PrimitiveType.Plane); // 复制材质到临时变量 Material tempMaterial = videoProjection.GetComponent<MeshRenderer>().material; GameObject instVideo = Instantiate(videoProjection, wrapper.transform); // 重新赋值材质 instVideo.GetComponent<MeshRenderer>().material = tempMaterial; // 销毁原对象 Destroy(videoProjection);
内容的提问来源于stack exchange,提问作者Jan Židlický
相关产品推荐
相关产品推荐

