Unity图片视频混播

这个功能做了好久了,今天总结下,也不是复杂的功能,记录一下以后有需要就不用再写一遍了,还有很多可以优化的地方。

需要Dotween插件。

注意:父级不要有布局组开启,可能会影响视频播放

层次结构:和每个组件,下面这个不是全屏,所以加了Mask。
RawImage1和RawImage2放在你想展示的位置的左边(往右滑)或右边(往左滑)
在这里插入图片描述
下面的两个图片元素,添加VideoPlayer,如果确定是图片和视频混播两个VP上放同一个RenderTexture即可,如果有可能全是视频,则每一个上添加一个RenderTexture.
在这里插入图片描述
最后添加这个脚本:ImageAndVideoLoopPlay,放在哪都行,只需把暴露的Fist、Second图设置了,还有RenderTexture,其他参数代码里会说明。
在这里插入图片描述
更新:增加了轮播模式

using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;
using System.Collections;
using System.IO;

public enum PlayMode
{
    OnePictureByOneVideo = 1,				//一张图片一个视频
    OnePictureClassByOneVideoClass = 2,		//先图片再视频,顺序也可以改
    FileOrder = 3,							//文件顺序
}

/// <summary>
/// 图片视频轮播
/// 注:全屏显示图片和视频
/// </summary>
public class ImgAndVideoLoopPlay : MonoBehaviour
{
    public Transform first;
    public Transform second;
    public float duration = 0.5f;
    public Ease ease = Ease.Linear;
    public double imageIntervalTime = 5;
    public double videoIntervalTime = 10;
    public bool isOpenScreen;
    public bool isMoveLeft = true;    
    public PlayMode mode = PlayMode.FileOrder;

    [HideInInspector]
    public float originalPos;

    private double intervalTime = 1;
    private Transform currentMoveTF;
    private Transform willResetTF;
    private int pictureCurrentIndex;
    private int videoCurrentIndex;
    private int fileCurrentIndex;
    private float maxWidth;
    private float maxHeight;

    /// <summary>
    /// 下一个是否显示视频屏保
    /// </summary>
    private bool nextIsVideo;

    private LoadResource loadResource;

    private void Awake()
    {
        loadResource = GetComponent<LoadResource>();
    }

    void Start()
    {
        mode = ConfigMode.mode;
        currentMoveTF = second;
        willResetTF = first;

        RectTransform rect = first as RectTransform;
        maxHeight = rect.rect.height;
        maxWidth = rect.rect.width;

        originalPos = second.localPosition.x;

        switch (mode)
        {
            case PlayMode.OnePictureByOneVideo:
            case PlayMode.OnePictureClassByOneVideoClass:
                nextIsVideo = false;			//改这里:控制先播放哪种类型,默认图片
                break;
            case PlayMode.FileOrder:
                if (loadResource.IsVideo(fileCurrentIndex))
                    nextIsVideo = true;
                else
                    nextIsVideo = false;
                break;
        }
    }

    float time;

    void Update()
    {
        if (loadResource.videoNum > 0 || loadResource.loadedPictureNum > 0 && loadResource.IsAllPictureLoadCompleted)
        {
            if (isOpenScreen)
            {
                time += Time.deltaTime;

                if (time > intervalTime)
                {
                    time = 0;

                    //图片视频轮播
                    PlayPicturesAndVideos();
                }
            }
        }
    }

    /// <summary>
    /// 图片视频轮播,默认往左,一张图片,一个视频
    /// </summary>
    /// <param name="isMoveLeft">默认往左移动</param>
    private void PlayPicturesAndVideos()
    {
        if (loadResource.videosPathList.Count == 0 && loadResource.totalImgFiles.Count == 0)
        {
            Debug.LogError("没有图片和视频资源,屏保显示默认");
            return;
        }

        if (loadResource.totalImgFiles.Count != 0 && loadResource.picturesList.Count == 0)
        {
            Debug.Log("图片正则加载,请稍等!");
            return;
        }

        if (loadResource.videosPathList.Count == 0)
        {
            nextIsVideo = false;
        }
        else if (loadResource.totalImgFiles.Count == 0)
        {
            nextIsVideo = true;
        }

        if (isMoveLeft)//左移
        {
            currentMoveTF.localPosition = new Vector3(originalPos, currentMoveTF.localPosition.y, currentMoveTF.localPosition.z);

            //图片视频轮播
            if (nextIsVideo)
            {
                switch (mode)
                {
                    case PlayMode.OnePictureByOneVideo:
                        nextIsVideo = false;
                        break;
                    case PlayMode.OnePictureClassByOneVideoClass:
                        JudgeVideo();
                        break;
                    case PlayMode.FileOrder:
                        JudgeIsVideo();
                        break;
                }
                //设置视频
                SetVideo();
            }
            else
            {
                switch (mode)
                {
                    case PlayMode.OnePictureByOneVideo:
                        nextIsVideo = true;
                        break;
                    case PlayMode.OnePictureClassByOneVideoClass:
                        JudgePicture();
                        break;
                    case PlayMode.FileOrder:
                        JudgeIsVideo();
                        break;
                }
                //设置图片
                SetPicture();
            }
        }
        else//右移
        {
            currentMoveTF.localPosition = new Vector3(-originalPos, currentMoveTF.localPosition.y, currentMoveTF.localPosition.z);

            if (nextIsVideo)
            {
                switch (mode)
                {
                    case PlayMode.OnePictureByOneVideo:
                        nextIsVideo = false;
                        break;
                    case PlayMode.OnePictureClassByOneVideoClass:
                        JudgeVideo();
                        break;
                    case PlayMode.FileOrder:
                        JudgeIsVideo();
                        break;
                }
                //设置视频
                SetVideo();

            }
            else
            {
                switch (mode)
                {
                    case PlayMode.OnePictureByOneVideo:
                        nextIsVideo = true;
                        break;
                    case PlayMode.OnePictureClassByOneVideoClass:
                        JudgePicture();
                        break;
                    case PlayMode.FileOrder:
                        JudgeIsVideo();
                        break;
                }

                //设置图片
                SetPicture();
            }
        }

        currentMoveTF.DOLocalMoveX(0, duration).SetEase(ease).OnComplete(() =>
        {
            willResetTF.localPosition = new Vector3(originalPos, willResetTF.localPosition.y, willResetTF.localPosition.z);
            willResetTF.SetAsLastSibling();

            Transform temp = currentMoveTF;
            currentMoveTF = willResetTF;
            willResetTF = temp;
        });
    }

    //Judge Picture
    private void JudgePicture()
    {
        if (loadResource.picturesList.Count != 0 && loadResource.videosPathList.Count != 0)
        {
            if (pictureCurrentIndex == loadResource.picturesList.Count - 1)
                nextIsVideo = true;
            else
                nextIsVideo = false;
        }
    }

    //Judge Video
    private void JudgeVideo()
    {
        if (loadResource.picturesList.Count != 0 && loadResource.videosPathList.Count != 0)
        {
            if (videoCurrentIndex == loadResource.videosPathList.Count - 1)
                nextIsVideo = false;
            else
                nextIsVideo = true;
        }
    }

    //Judge Is Video
    private void JudgeIsVideo()
    {
        fileCurrentIndex = (fileCurrentIndex + 1) % loadResource.allFile.Count;
        if (loadResource.IsVideo(fileCurrentIndex))
            nextIsVideo = true;
        else
            nextIsVideo = false;
    }

    /// <summary>
    /// 设置图片
    /// </summary>
    private void SetPicture()
    {        
        Texture2D tex = loadResource.picturesList[pictureCurrentIndex].tex;
        RawImage raw = currentMoveTF.GetComponentInChildren<RawImage>();
        raw.texture = tex;
        intervalTime = imageIntervalTime;
        pictureCurrentIndex = (pictureCurrentIndex + 1) % loadResource.picturesList.Count;
    }

    /// <summary>
    /// 设置视频
    /// </summary>
    private void SetVideo()
    {
        VideoPlayer vp = currentMoveTF.GetComponentInChildren<VideoPlayer>();
        currentMoveTF.GetComponentInChildren<RawImage>().texture = vp.targetTexture;
        vp.url = loadResource.videosPathList[videoCurrentIndex];
        vp.SetDirectAudioMute(0, false);
        vp.Play();

        RectTransform rect = vp.transform as RectTransform;
        rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, maxWidth);
        rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, maxHeight);

        intervalTime = videoIntervalTime;
        StartCoroutine(SetVideoIntervalTime(vp));

        videoCurrentIndex = (videoCurrentIndex + 1) % loadResource.videosPathList.Count;
    }

    /// <summary>
    /// 设置视频间隔:播放URL视频,不能立刻获取到视频时长,需要播放一段时间
    /// </summary>
    /// <param name="vp">视频</param>
    /// <returns></returns>
    private IEnumerator SetVideoIntervalTime(VideoPlayer vp)
    {
        for (int i = 0; i < 10; i++)
        {
            yield return new WaitForSeconds(0.5f);
            if (vp.length > 0)
            {
                intervalTime = vp.length;
                yield break;
            }
        }
    }

    public void MuteVideo(bool isMute)
    {
        VideoPlayer vp = currentMoveTF.GetComponentInChildren<VideoPlayer>();
        vp.SetDirectAudioMute(0, isMute);
        vp = willResetTF.GetComponentInChildren<VideoPlayer>();
        vp.SetDirectAudioMute(0, isMute);
    }

    public void CancelMuteCurrent()
    {
        VideoPlayer vp = currentMoveTF.GetComponentInChildren<VideoPlayer>();
        vp.SetDirectAudioMute(0, true);

        vp = willResetTF.GetComponentInChildren<VideoPlayer>();
        var raw = willResetTF.GetComponent<RawImage>();
        if (raw.texture == vp.targetTexture)
        {
            vp.SetDirectAudioMute(0, false);
        }
        else
        {
            vp.SetDirectAudioMute(0, true);
        }
    }
}

class ConfigMode
{
    public static PlayMode mode = PlayMode.FileOrder;

    static ConfigMode()
    {
        string path = Application.streamingAssetsPath + "/ModeConfig.txt";
        if (File.Exists(path))
        {
            var str = File.ReadAllText(path).Trim();
            mode = (PlayMode)int.Parse(str.Split('=')[1]);
        }
        else
        {
            File.WriteAllText(path, $"轮播模式={(int)mode}");
        }
    }
}

还需要一个资源加载的脚本:如果不是加载的外部图片,可以不用,代码自己修改。
这个脚本挂哪都行,可以和上面的放一块。

using System;
using System.IO;
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
using System.Collections.Generic;
using System.Text.RegularExpressions;

/// <summary>
/// 图片数据
/// </summary>
public class PictureData
{
    public string name;
    public Texture2D tex;
}

/// <summary>
/// 加载资源
/// </summary>
public class LoadResource : MonoBehaviour
{
    public string resourcePath = "/ImagesAndVideos/";
    public List<PictureData> picturesList;
    public List<string> totalImgFiles;
    public int loadedPictureNum
    {
        get
        {
            return picturesList.Count;
        }
    }
    public List<string> videosPathList;
    public int videoNum
    {
        get
        {
            return videosPathList.Count;
        }
    }
    public List<string> allFile;
    public Action FirstPictureLoadCompleted;
    Regex reg = new Regex("^[0-9]+");

    private void Awake()
    {
        resourcePath = Application.streamingAssetsPath + resourcePath;

        if (!Directory.Exists(resourcePath))
            Directory.CreateDirectory(resourcePath);
        allFile = new List<string>();
        totalImgFiles = new List<string>();
        picturesList = new List<PictureData>();
        videosPathList = new List<string>();

        //获取图片并加载
        StartCoroutine(GetPictures());

        //获取视频路径
        GetVideoPath();
    }

    /// <summary>
    /// 获取视频路径
    /// </summary>
    private void GetVideoPath()
    {
        string[] videos = Directory.GetFiles(resourcePath, "*.mp4");

        Debug.Log("本地视频数量:" + videos.Length);
        videosPathList.AddRange(videos);
        SortList(videosPathList);
        allFile.AddRange(videosPathList);
        SortList(allFile);
    }

    /// <summary>
    /// 获取图片
    /// </summary>
    /// <returns></returns>
    private IEnumerator GetPictures()
    {
        string[] jpgs = Directory.GetFiles(resourcePath, "*.jpg");
        string[] pngs = Directory.GetFiles(resourcePath, "*.png");

        totalImgFiles.AddRange(pngs);
        totalImgFiles.AddRange(jpgs);
        SortList(totalImgFiles);
        allFile.AddRange(totalImgFiles);

        Debug.Log("本地图片数量:" + totalImgFiles.Count);

        for (int i = 0; i < totalImgFiles.Count; i++)
        {
            yield return StartCoroutine(LoadPicuture(totalImgFiles[i]));

            FirstPictureLoadCompleted?.Invoke();
            FirstPictureLoadCompleted = null;
        }
    }    

    /// <summary>
    /// 加载图片
    /// </summary>
    /// <param name="filePath">图片路径</param>
    /// <returns></returns>
    private IEnumerator LoadPicuture(string filePath)
    {
        UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(filePath);

        yield return uwr.SendWebRequest();

        if (uwr.downloadHandler.isDone)
        {
            string fileName = Path.GetFileNameWithoutExtension(filePath);
            var temp = reg.Replace(fileName, "");
            Texture2D fileTex = DownloadHandlerTexture.GetContent(uwr);
            picturesList.Add(new PictureData() { name = temp, tex = fileTex });
        }
    }

    public bool IsAllPictureLoadCompleted
    {
        get
        {
            return loadedPictureNum > 0 && loadedPictureNum == picturesList.Count;
        }
    }

    /// <summary>
    /// is video
    /// </summary>
    /// <param name="index">索引</param>
    /// <returns></returns>
    public bool IsVideo(int index)
    {
        if (index >= allFile.Count)
        {
            Debug.LogError("索引超出!");
            return false;
        }

        return Path.GetExtension(allFile[index]) == ".mp4";
    }

    private void SortList(List<string> list)
    {
        list.Sort((f1, f2) =>
        {
            var fileName1 = Path.GetFileNameWithoutExtension(f1);
            var fileName2 = Path.GetFileNameWithoutExtension(f2);
            var temp1 = reg.Match(fileName1).Value;
            var temp2 = reg.Match(fileName2).Value;

            if (string.IsNullOrEmpty(temp1) || string.IsNullOrEmpty(temp2))
            {
                return fileName1.CompareTo(fileName2);
            }

            var num1 = int.Parse(temp1);
            var num2 = int.Parse(temp2);
            return num1.CompareTo(num2);
        });
    }
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值