如何在多个GameObject上复用同一张WebCamTexture?
解决Unity中WebCamTexture无法在多个GameObject上渲染的问题
首先,先指出你代码里的一个小疏漏:你定义了cameraNumber变量,但实际创建WebCamTexture时用的是devices[0],没有用到这个参数,先把这个小问题修正,避免后续混淆。
回到核心问题:你遇到的并不是“单个WebCamTexture只能被一个GameObject渲染”的限制——Unity的WebCamTexture是可以被多个材质共享的,问题出在材质实例化和纹理赋值的方式上。当你直接给Renderer.material.mainTexture赋值时,Unity会自动为该GameObject创建一个材质实例(防止修改原始材质资源),但如果多个物体没有正确关联到同一个纹理实例,或者Shader没有正确采样纹理,就会出现只有一个物体显示的情况。
下面提供两种可行的解决方案:
方案一:使用全局管理类统一控制纹理和渲染目标
创建一个专门的管理脚本,负责初始化WebCamTexture,并将其赋值给所有需要显示的物体。这种方式更易于维护,尤其适合多个物体需要共享同一相机画面的场景。
using UnityEngine; public class CameraFeedManager : MonoBehaviour { public int cameraNumber = 0; public Renderer[] targetRenderers; // 在Inspector中拖入所有需要显示相机画面的物体的Renderer组件 private WebCamTexture _webcamTexture; void Start() { WebCamDevice[] devices = WebCamTexture.devices; if (devices.Length <= cameraNumber) { Debug.LogError($"No camera found with index {cameraNumber}"); return; } // 初始化WebCamTexture _webcamTexture = new WebCamTexture(devices[cameraNumber].name, 1280, 720); // 为每个目标Renderer创建独立的材质实例并赋值纹理 foreach (Renderer renderer in targetRenderers) { // 复制原有材质的属性,避免修改原始材质资源 Material materialInstance = new Material(renderer.material); materialInstance.mainTexture = _webcamTexture; renderer.material = materialInstance; } _webcamTexture.Play(); } void OnDestroy() { // 销毁纹理,释放相机资源 if (_webcamTexture != null) { _webcamTexture.Stop(); Destroy(_webcamTexture); } } }
使用步骤:
- 创建一个空GameObject,将这个脚本挂载上去。
- 在Inspector面板中,把你的两个半球和测试平面的Renderer组件拖入
targetRenderers数组。 - 设置正确的
cameraNumber,运行测试。
方案二:在每个显示物体的脚本中复用全局WebCamTexture
如果你不想用管理类,可以将WebCamTexture设为静态变量,让所有挂载该脚本的物体共享同一个纹理实例,同时为每个物体创建独立的材质实例。
using UnityEngine; public class CameraDisplay : MonoBehaviour { public int cameraNumber = 0; private static WebCamTexture _sharedWebcamTexture; void Start() { // 仅在第一次初始化时创建纹理 if (_sharedWebcamTexture == null) { WebCamDevice[] devices = WebCamTexture.devices; if (devices.Length <= cameraNumber) { Debug.LogError($"No camera found with index {cameraNumber}"); return; } _sharedWebcamTexture = new WebCamTexture(devices[cameraNumber].name, 1280, 720); _sharedWebcamTexture.Play(); } // 为当前物体创建材质实例并赋值共享纹理 Material materialInstance = new Material(GetComponent<Renderer>().material); materialInstance.mainTexture = _sharedWebcamTexture; GetComponent<Renderer>().material = materialInstance; } void OnDestroy() { // 确保只有最后一个销毁的物体释放相机资源 if (_sharedWebcamTexture != null && FindObjectsOfType<CameraDisplay>().Length == 1) { _sharedWebcamTexture.Stop(); Destroy(_sharedWebcamTexture); } } }
额外排查点
如果以上方案仍未解决问题,需要检查你的自定义Shader:
- 确保Shader中使用了正确的纹理属性名(默认是
_MainTex,对应mainTexture)。 - 切换到Unity内置的Standard Shader测试,如果Standard Shader能正常显示,说明你的自定义Shader在纹理采样上存在问题,需要检查采样逻辑。
内容的提问来源于stack exchange,提问作者MyBug18
相关产品推荐
相关产品推荐

