Unity 3D:实现物体VideoPlayer在主相机播放并关闭/销毁
Unity交互播放视频问题求助
我是Unity编程新手,正在开发一款游戏,需求是:玩家按下F键与物体交互,触发该物体上VideoPlayer组件加载的视频在主相机播放,播放完成后自动关闭。目前实现遇到困难,附上两个C#脚本,恳请帮助。
我的设想是每个交互物体都自带VideoPlayer组件和对应视频,玩家点击不同物体播放不同视频。
Interactable(物体脚本)
public GameObject otherGameObject; public VideoPlayer videoPlayer; Outline outline; public string message; public UnityEvent onInteractable; // Start is called before the first frame update void Start() { //videoPlayer = otherGameObject.GetComponent<VideoPlayer>(); //var videoPlayer = GetComponent<Camera>().AddComponent<UnityEngine.Video.VideoPlayer>(); //videoPlayer = GameObject.Find("Cube").GetComponent<VideoPlayer>(); outline = GetComponent<Outline>(); DisableOutline(); } public void Interact() { videoPlayer.Play(); onInteractable.Invoke(); } public void DisableOutline() { outline.enabled = false; } public void EnableOutline() { outline.enabled = true; }
PlayerInteraction(玩家脚本)
public class PlayerInteraction : MonoBehaviour { public float playerReach = 3f; Interactable currentInteractable; // Update is called once per frame public void Update() { CheckInteraction(); if(Input.GetKeyDown(KeyCode.F) && currentInteractable != null) { currentInteractable.Interact(); } } void CheckInteraction() { RaycastHit hit; Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward); //if colliders with anything within player reach if(Physics.Raycast(ray, out hit, playerReach)) { if(hit.collider.tag == "Interactable") //if looking at an interactable object { Interactable newInteractable = hit.collider.GetComponent<Interactable>(); newInteractable.videoPlayer.Play(); //if there is a currentInteractable and it is not the newInteractable if(currentInteractable && newInteractable != currentInteractable) { currentInteractable.DisableOutline(); } if(newInteractable.enabled) { SetNewCurrentInteractable(newInteractable); } else //if new interactable is not enabled { DisableCurrentInteractable(); } } else //if not an interactable { DisableCurrentInteractable(); } } else //if nothing in reach { DisableCurrentInteractable(); } } void SetNewCurrentInteractable(Interactable newInteractable) { currentInteractable = newInteractable; currentInteractable.EnableOutline(); } void DisableCurrentInteractable() { if(currentInteractable) { currentInteractable.DisableOutline(); currentInteractable = null; } } }
问题排查与修复方案
1. 核心逻辑错误修复
你的PlayerInteraction脚本中,CheckInteraction方法里直接调用了newInteractable.videoPlayer.Play();——这会导致玩家视线一碰到物体就自动播放,完全跳过了按F键交互的逻辑,直接删除这行代码即可。
2. 视频渲染到主相机的配置
每个交互物体的VideoPlayer组件需要正确设置渲染目标:
- 选中交互物体的VideoPlayer,将
Render Mode设为Camera Far Plane或Camera Near Plane - 在
Camera选项中拖入主相机对象 - 勾选
Wait For First Frame,避免视频加载前显示黑屏
3. 播放完成自动关闭的实现
修改Interactable脚本,添加视频结束监听:
void Start() { outline = GetComponent<Outline>(); DisableOutline(); // 绑定视频结束事件 if(videoPlayer != null) { videoPlayer.loopPointReached += OnVideoEnd; // 默认禁用VideoPlayer,避免初始状态显示 videoPlayer.enabled = false; } } void OnVideoEnd(VideoPlayer vp) { vp.enabled = false; // 如需恢复操作或隐藏相关UI,可在此添加逻辑 } public void Interact() { if(videoPlayer != null) { videoPlayer.enabled = true; videoPlayer.Play(); } onInteractable.Invoke(); } // 销毁时移除监听,防止内存泄漏 void OnDestroy() { if(videoPlayer != null) { videoPlayer.loopPointReached -= OnVideoEnd; } }
4. VideoPlayer引用的正确赋值
- 每个交互物体必须挂载VideoPlayer组件,并将对应视频拖入
Clip字段 - 在
Interactable脚本的Inspector面板中,直接把物体自身的VideoPlayer拖到videoPlayer变量上,不要用注释里的Find或GetComponent(除非有特殊需求)
5. 额外优化
- 交互时停止其他正在播放的视频:在
PlayerInteraction的F键触发逻辑中,先停止所有播放中的视频,避免多视频重叠if(Input.GetKeyDown(KeyCode.F) && currentInteractable != null) { // 停止所有正在播放的视频 var allPlayers = FindObjectsOfType<VideoPlayer>(); foreach(var player in allPlayers) { if(player.isPlaying) { player.Stop(); player.enabled = false; } } currentInteractable.Interact(); } - 给主相机添加黑色UI面板作为视频背景,防止场景内容透过视频显示
内容的提问来源于stack exchange,提问作者dan_udnas
相关产品推荐
相关产品推荐

