C# 使用Unity视频播放器无缝地背靠背播放不同的视频

C# 使用Unity视频播放器无缝地背靠背播放不同的视频,c#,unity3d,video,video-player,C#,Unity3d,Video,Video Player,关于Unity的视频播放器组件,有人有任何解决方案吗 基本上,我有一个半交互式的应用程序,当事情发生时,它可以背靠背地播放一系列视频。问题是,一旦第一个视频结束,就会出现3-5秒的空白,因为第二个视频需要时间加载,但是在我的应用程序中,这看起来不太好 我需要一种方法来预加载第二个视频(理想的)或一种相当简单的方法来隐藏间隙(如顶部的静止帧)。对于后一种想法,我应该提到视频是球形显示的 using UnityEngine; using UnityEngine.Video; public clas

关于Unity的视频播放器组件,有人有任何解决方案吗

基本上,我有一个半交互式的应用程序,当事情发生时,它可以背靠背地播放一系列视频。问题是,一旦第一个视频结束,就会出现3-5秒的空白,因为第二个视频需要时间加载,但是在我的应用程序中,这看起来不太好

我需要一种方法来预加载第二个视频(理想的)或一种相当简单的方法来隐藏间隙(如顶部的静止帧)。对于后一种想法,我应该提到视频是球形显示的

using UnityEngine;
using UnityEngine.Video;

public class selectAndPlay_video : MonoBehaviour {

    public VideoPlayer videoPlayer;
    public VideoClip NewClip;
    void OnEnable()
    {
        videoPlayer.loopPointReached += loopPointReached;
    }

    void OnDisable()
    {
        videoPlayer.loopPointReached -= loopPointReached;
    }

   void loopPointReached(VideoPlayer v)

    {
       videoPlayer.clip = NewClip;
       videoPlayer.Play();
     }
}

解决此问题的关键是
VideoPlayer.Prepare()
函数、
VideoPlayer.time
VideoPlayer.clip.length
属性。首先,我建议你忘记当前播放视频的方式。按照问题示例中的方法使用协程,因为下面答案中的所有内容都假设您处于协程函数中。以下是如何播放不同的视频,而无需长时间等待:

1。播放
视频剪辑的数组/列表

2。从#1中的
VideoClip
数组创建新的
VideoPlayer
列表。只需使用#1中的
VideoClips
设置
VideoPlayer.clip
属性即可

3调用
VideoPlayer.Prepare()
首先准备列表中的
VideoPlayer
,然后在
循环中等待,直到准备完成或
VideoPlayer.isPrepared
变为
true

4。调用
VideoPlayer.Play()
播放刚刚在#3中准备的视频

无缝地背靠背播放不同的视频

这是最重要的部分

播放视频时,检查正在播放的
视频播放器的当前时间是否为视频长度的一半。如果已播放到一半,请对阵列中的下一个视频调用
VideoPlayer.Prepare()
,然后等待来自#4的视频完成播放,然后再播放下一个视频

通过这样做,下一个视频将在当前视频仍在播放时开始自我准备,准备过程应在当前视频播放结束时完成。然后,您可以播放下一个视频,而无需长时间等待加载

5。等待来自#4的视频在
循环中完成播放,直到
视频播放器。isPlaying
变为
false

6。当在
中等待而
#5中循环时,检查视频是否已使用
if(videoPlayerList[videoIndex].time>=(videoPlayerList[videoIndex].clip.length/2)播放了一半。如果这是真的,请在列表中的下一个
VideoPlayer
上调用
VideoPlayer.Prepare()
,使其保持就绪

7。当
循环存在时,当前视频播放完毕。播放列表中的下一个
VideoPlayer
,然后从#5再次重复,以准备列表中的下一个
VideoPlayer

下面的脚本应该完成我上面描述的所有操作。只需创建一个
rawmimage
并将其插入图像插槽。您的所有视频也将被添加到
videoClipList
变量中。它应该一个接一个地播放视频,而不需要很长的加载时间。
Debug.Log
非常昂贵,因此在验证其工作正常后将其删除

//Raw Image to Show Video Images [Assign from the Editor]
public RawImage image;
//Set from the Editor
public List<VideoClip> videoClipList;

private List<VideoPlayer> videoPlayerList;
private int videoIndex = 0;


void Start()
{
    StartCoroutine(playVideo());
}

IEnumerator playVideo(bool firstRun = true)
{
    if (videoClipList == null || videoClipList.Count <= 0)
    {
        Debug.LogError("Assign VideoClips from the Editor");
        yield break;
    }

    //Init videoPlayerList first time this function is called
    if (firstRun)
    {
        videoPlayerList = new List<VideoPlayer>();
        for (int i = 0; i < videoClipList.Count; i++)
        {
            //Create new Object to hold the Video and the sound then make it a child of this object
            GameObject vidHolder = new GameObject("VP" + i);
            vidHolder.transform.SetParent(transform);

            //Add VideoPlayer to the GameObject
            VideoPlayer videoPlayer = vidHolder.AddComponent<VideoPlayer>();
            videoPlayerList.Add(videoPlayer);

            //Add AudioSource to  the GameObject
            AudioSource audioSource = vidHolder.AddComponent<AudioSource>();

            //Disable Play on Awake for both Video and Audio
            videoPlayer.playOnAwake = false;
            audioSource.playOnAwake = false;

            //We want to play from video clip not from url
            videoPlayer.source = VideoSource.VideoClip;

            //Set Audio Output to AudioSource
            videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;

            //Assign the Audio from Video to AudioSource to be played
            videoPlayer.EnableAudioTrack(0, true);
            videoPlayer.SetTargetAudioSource(0, audioSource);

            //Set video Clip To Play 
            videoPlayer.clip = videoClipList[i];
        }
    }

    //Make sure that the NEXT VideoPlayer index is valid
    if (videoIndex >= videoPlayerList.Count)
        yield break;

    //Prepare video
    videoPlayerList[videoIndex].Prepare();

    //Wait until this video is prepared
    while (!videoPlayerList[videoIndex].isPrepared)
    {
        Debug.Log("Preparing Index: " + videoIndex);
        yield return null;
    }
    Debug.LogWarning("Done Preparing current Video Index: " + videoIndex);

    //Assign the Texture from Video to RawImage to be displayed
    image.texture = videoPlayerList[videoIndex].texture;

    //Play first video
    videoPlayerList[videoIndex].Play();

    //Wait while the current video is playing
    bool reachedHalfWay = false;
    int nextIndex = (videoIndex + 1);
    while (videoPlayerList[videoIndex].isPlaying)
    {
        Debug.Log("Playing time: " + videoPlayerList[videoIndex].time + " INDEX: " + videoIndex);

        //(Check if we have reached half way)
        if (!reachedHalfWay && videoPlayerList[videoIndex].time >= (videoPlayerList[videoIndex].clip.length / 2))
        {
            reachedHalfWay = true; //Set to true so that we don't evaluate this again

            //Make sure that the NEXT VideoPlayer index is valid. Othereise Exit since this is the end
            if (nextIndex >= videoPlayerList.Count)
            {
                Debug.LogWarning("End of All Videos: " + videoIndex);
                yield break;
            }

            //Prepare the NEXT video
            Debug.LogWarning("Ready to Prepare NEXT Video Index: " + nextIndex);
            videoPlayerList[nextIndex].Prepare();
        }
        yield return null;
    }
    Debug.Log("Done Playing current Video Index: " + videoIndex);

    //Wait until NEXT video is prepared
    while (!videoPlayerList[nextIndex].isPrepared)
    {
        Debug.Log("Preparing NEXT Video Index: " + nextIndex);
        yield return null;
    }

    Debug.LogWarning("Done Preparing NEXT Video Index: " + videoIndex);

    //Increment Video index
    videoIndex++;

    //Play next prepared video. Pass false to it so that some codes are not executed at-all
    StartCoroutine(playVideo(false));
}
//显示视频图像的原始图像[从编辑器分配]
公众形象;
//从编辑器中设置
公共列表videoClipList;
私人列表视频播放列表;
私有int videoIndex=0;
void Start()
{
开始例行程序(播放视频());
}
IEnumerator播放视频(bool firstRun=true)
{
if(videoClipList==null | | videoClipList.Count=videoPlayerList.Count)
屈服断裂;
//准备视频
videoPlayerList[videoIndex].Prepare();
//请等待此视频准备就绪
而(!videoPlayerList[videoIndex].isPrepared)
{
Debug.Log(“准备索引:+videoIndex”);
收益返回空;
}
Debug.LogWarning(“完成当前视频索引的准备:“+videoIndex”);
//将纹理从视频指定给要显示的原始图像
image.texture=videoPlayerList[videoIndex]。纹理;
//播放第一个视频
videoPlayerList[videoIndex].Play();
//正在播放当前视频,请稍候
布尔到达一半=假;
int nextIndex=(视频索引+1);
while(videoPlayerList[videoIndex].isplay)
{
Log(“播放时间:+videoPlayerList[videoIndex]。时间+”索引:+videoIndex);
//(检查我们是否已到达一半)
如果(!reachedMiddle&&videoPlayerList[videoIndex]。时间>=(videoPlayerList[videoIndex]。clip.length/2))
{
reachedMiddle=true;//设置为true,这样我们就不会再次计算此值
//确保下一个VideoPlayer索引有效。其他索引将退出,因为这是结束
如果(nextIndex>=videoPlayerList.Count)
{
Debug.LogWarning(“所有视频结束:+videoIndex”);
屈服断裂;
}
//准备下一个视频
LogWarning(“准备好准备下一个视频索引:+nextIndex”);
videoPlayerList[nextIndex].Prepare();
}
收益返回空;
}
Log(“播放完当前视频索引:+videoIndex”);
//等待下一个视频准备好
而(!videoPlayerList[nextIndex].isPrepared)
{
Log(“准备下一个视频索引:+nextIndex”);
收益返回空;
}
Debug.LogWarning(“准备好下一个视频索引:”+vi