You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
}

原因分析

  1. 移动端材质裁剪:Unity构建移动端包时,Shader Stripping机制可能移除了Plane默认材质依赖的Shader,导致运行时材质无效,显示洋红色
  2. MaterialOverride模式适配问题:默认Plane材质在移动端可能不具备VideoPlayer所需的可覆盖纹理属性,触发iOS的报错
  3. 实例化材质引用丢失:原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ý

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 23:00:09