如何在使用VideoPlayer API播放RawImage视频时旋转并全屏显示 - Unity

10
作为Unity 5.6.0b1之后已经被弃用的MovieTexture,我正在使用VideoPlayer API通过参考这里在Android上播放视频,并在RawImage上显示。我试图添加一个开关来切换从最初的视频大小到全屏再返回原始大小。
我的视频可以完美播放,目前我能够使用以下代码将视频的变换改变为全屏。
void Update () {
    if (Input.GetButtonDown("Jump"))
    {
        image.rectTransform.offsetMax = Vector2.Lerp(Vector2.up, Vector2.down, 100);
        image.rectTransform.offsetMin = Vector2.Lerp(Vector2.left, Vector2.right, 100);
        image.rectTransform.rotation = Quaternion.AngleAxis(Mathf.Lerp(0f, 90f, 50), Vector3.forward);
    }
}

if代码块内的前两行可以使视频播放的效果全屏,如图像第2部分所示。这是Vector2的文档。

对于旋转的第三行代码,我参考了Unity论坛上的这个讨论, 但是我仍然没有得到我想要的效果,结果见第3部分。我想要旋转RawImage的内容,但是我正在旋转RawImage本身,这可能是因为参考未描述如何旋转内容。

有人能帮我找出如何解决它吗?如果有帮助,我正在使用的Unity版本是Unity 5.6.0b11 Beta,并且如果您想在设备上测试,请下载示例项目。Unity Video Player.zip 18.33MB 您还可以关注这个来自YouTube的新VideoPlayer视频教程

Full Screen and Rotate Video Played using Unity VideoPlayer on RawImage

更新1

到目前为止,我所做的唯一一件事就是,我仅尝试了旋转代码,并通过删除if块内的前两行,我能够旋转视频,但当我尝试拉伸RawImage时,它会超出屏幕。请点击此处查看图片

更新2

经过大量的研究和试验,我最终使用这段代码实现了RawImage的全屏和旋转,从而在Unity中播放全屏视频。

image.rectTransform.offsetMin = new Vector2(-560, 560);            
image.rectTransform.offsetMax = new Vector2(560, -560);

但是,正如您所看到的,我提供给向量的值是静态数字,并不能保证在多个屏幕尺寸上工作。旋转RawImage时会令人困惑,因为轴随着RawImage旋转,但某些组件未更改或旋转,并且在更改偏移值时,RawImage会根据旧矩形的参考值更改其值(我真的不知道这里发生了什么)输入图像描述

旋转RawImage会旋转附加到它上面的轴。在上面的图像中,您可以看到RawImage被旋转了,进而旋转了轴。但即使图像被旋转,您也可以看到有一些参考线。

enter image description here

我尝试如何解决这个问题?[失败] 我尝试以一种新的方式解决这个问题,我创建了一个适合画布并已经旋转的新RawImage,并将其附加到脚本StreamVideo.cs中,就像以前的RawImage一样。最初它处于非活动状态,并在用户命令全屏时切换为活动状态。当它进入全屏模式时,视频会在新的RawImage中播放。
public void playFullScreen() {
    isFullScreen = true;
    imageFullScreen.gameObject.SetActive(true);
    imageFullScreen.texture = videoPlayer.texture;
    image.gameObject.SetActive(false);
}

但是,我遇到了一个问题,就是当切换到全屏时,无法从相同的帧开始在新的RawImage上播放视频,并且切换回小屏幕时也存在同样的问题。

概述:

查看更新2,我能够播放、暂停、全屏和旋转视频,但是offsetMaxoffsetMin中只有纯数字值。 我正在尝试学习是否有一种通过脚本筛选这些值以适应多个屏幕尺寸的方法。我知道这听起来很简单,但棘手的部分是,对于我需要的屏幕,我提供的值的参考工作方式是这样的。请注意图片中的虚线矩形enter image description here


1
为什么不改变视频的目标?将其改为相机近平面,它将可以直接全屏播放。 - Antoine Eskaros
2个回答

4
我想要做相同的事情,但遇到了完全相同的问题。我认为这是一个错误,但成功找到了解决方案。
可以通过锚点、中心点和屏幕大小(Screen.width, Screen.height)或Canvas的大小来实现。在我的情况下,我将使用Canvas的大小。
当你按住Alt键并单击RawImage RectTransform的拉伸图标时,RawImage将以全屏显示。您可以通过以下代码完成相同的操作,同时更改编辑器中更改的值:
rectTrfm.anchoredPosition3D = new Vector3(0, 0, 0);
//Stretch the Image so that the whole screen is totally covered
rectTrfm.anchorMin = new Vector2(0, 0);
rectTrfm.anchorMax = new Vector2(1, 1);
rectTrfm.pivot = new Vector2(0.5f, 0.5f);
rectTrfm.offsetMin = Vector2.zero;
rectTrfm.offsetMax = Vector2.zero;

它可以正常工作并应该为您提供全屏的 RawImage。问题在于,当旋转角度为0180(或者也称为倒置)时,它可以运行。但是当旋转角度为-9090270时,它无法正常工作。这些角度通常是在将RawImage向右或向左旋转时得到的。我怀疑这是一个错误。
要解决此问题,您需要从Canvas的RectTransform大小计算出纵横比,然后使用它来创建anchorMinanchorMax。其余代码应保持不变。
RectTransform canvasRectTrfm = rawImage.canvas.GetComponent<RectTransform>();
float aspRatio = canvasRectTrfm.rect.size.x / canvasRectTrfm.rect.size.y;
float halfAspRatio = aspRatio / 2.0f;
float halfAspRatioInvert = (1.0f / aspRatio) / 2.0f;

rectTrfm.anchorMin = new Vector2(0.5f - halfAspRatioInvert, 0.5f - halfAspRatio);
rectTrfm.anchorMax = new Vector2(0.5f + halfAspRatioInvert, 0.5f + halfAspRatio);
rectTrfm.anchoredPosition3D = Vector3.zero;
rectTrfm.pivot = new Vector2(0.5f, 0.5f);
rectTrfm.offsetMin = Vector2.zero;
rectTrfm.offsetMax = Vector2.zero;

这应该适用于 -9090270 角度,但不适用于 0180。这不是问题,因为我们的第一个代码适用于 0180 角度。我们可以在运行时检测角度,并根据当前 RawImage 的角度执行代码。

您可以在下面的代码中看到将两个代码组合在一起的完整函数名为 StretchImageFullScreen。以下是一个示例代码,当按下 Space 键时,在全屏和 RawImage 的原始大小之间切换视频。要退出切换模式,请按下 R 键。使用 RawImageInfo 结构体在切换到全屏之前复制 RectTransform 信息,以便在再次使用 Space 键或按下 R 键时恢复默认位置/旋转。

将以下代码添加到其他回答中的代码中,您应该能够在全屏视频和默认的 RawImage 大小之间切换,并且应该能够使用 StretchImageFullScreen 函数中的第二个参数旋转它。

//Used to store RectTransform information so that original RawImage settings can be restored
public struct RawImageInfo
{
    public Vector3 anchorPos;
    public Vector2 widthAndHeight;
    public Vector2 anchorMin;
    public Vector2 anchorMax;
    public Vector2 pivot;

    public Vector2 offsetMin;
    public Vector2 offsetMax;

    public Quaternion rot;
    public Vector3 scale;
}

RawImageInfo originalImgInfo;
bool fullSclreen = false;

void Awake()
{
    //Get the default RawImage RectTransform settings
    originalImgInfo = GetImageSettings(image);
}

void Update()
{
    //Toggle fullscreen when Space key is pressed
    if (Input.GetKeyDown(KeyCode.Space))
    {
        //Toggle
        fullSclreen = !fullSclreen;
        if (fullSclreen)
            StretchImageFullScreen(image, 90);
        else
            ApplyImageSettings(image, originalImgInfo);
    }

    //Restore RawImage default settings when R key is pressed
    if (Input.GetKeyDown(KeyCode.R))
    {
        ApplyImageSettings(image, originalImgInfo);
        fullSclreen = false;
    }
}

private void StretchImageFullScreen(RawImage rawImage, int rotAngle = 0)
{
    RectTransform rectTrfm = rawImage.rectTransform;

    //Get angle and change z-axis
    Vector3 rot = rectTrfm.rotation.eulerAngles;
    rot.z = rotAngle; //Set Z rotation to rotAngle
    rectTrfm.rotation = Quaternion.Euler(rot);

    //Get current angle after changing it
    rot = rectTrfm.rotation.eulerAngles;

    if (Mathf.Approximately(rot.z, 0) || Mathf.Approximately(rot.z, 180))
    {
        rectTrfm.anchoredPosition3D = new Vector3(0, 0, 0);
        //Stretch the Image so that the whole screen is totally covered
        rectTrfm.anchorMin = new Vector2(0, 0);
        rectTrfm.anchorMax = new Vector2(1, 1);
        rectTrfm.pivot = new Vector2(0.5f, 0.5f);
        rectTrfm.offsetMin = Vector2.zero;
        rectTrfm.offsetMax = Vector2.zero;
    }

    else if (Mathf.Approximately(rot.z, -90) || Mathf.Approximately(rot.z, 90)
         || Mathf.Approximately(rot.z, 270))
    {

        //Get the Canvas RectTransform
        RectTransform canvasRectTrfm = rawImage.canvas.GetComponent<RectTransform>();
        float aspRatio = canvasRectTrfm.rect.size.x / canvasRectTrfm.rect.size.y;
        float halfAspRatio = aspRatio / 2.0f;
        float halfAspRatioInvert = (1.0f / aspRatio) / 2.0f;

        rectTrfm.anchorMin = new Vector2(0.5f - halfAspRatioInvert, 0.5f - halfAspRatio);
        rectTrfm.anchorMax = new Vector2(0.5f + halfAspRatioInvert, 0.5f + halfAspRatio);
        rectTrfm.anchoredPosition3D = Vector3.zero;
        rectTrfm.pivot = new Vector2(0.5f, 0.5f);
        rectTrfm.offsetMin = Vector2.zero;
        rectTrfm.offsetMax = Vector2.zero;
    }
}

RawImageInfo GetImageSettings(RawImage rawImage)
{
    RectTransform rectTrfm = rawImage.rectTransform;

    RawImageInfo rawImgInfo = new RawImageInfo();

    //Get settings from RawImage and store as RawImageInfo 
    rawImgInfo.anchorPos = rectTrfm.anchoredPosition3D;
    rawImgInfo.widthAndHeight = rectTrfm.sizeDelta;

    rawImgInfo.anchorMin = rectTrfm.anchorMin;
    rawImgInfo.anchorMax = rectTrfm.anchorMax;
    rawImgInfo.pivot = rectTrfm.pivot;

    rawImgInfo.offsetMin = rectTrfm.offsetMin;
    rawImgInfo.offsetMax = rectTrfm.offsetMax;

    rawImgInfo.rot = rectTrfm.rotation;
    rawImgInfo.scale = rectTrfm.localScale;

    return rawImgInfo;
}

private void ApplyImageSettings(RawImage rawImage, RawImageInfo rawImgInfo)
{
    RectTransform rectTrfm = rawImage.rectTransform;

    //Apply settings from RawImageInfo to RawImage RectTransform
    rectTrfm.anchoredPosition3D = rawImgInfo.anchorPos;
    rectTrfm.sizeDelta = rawImgInfo.widthAndHeight;

    rectTrfm.anchorMin = rawImgInfo.anchorMin;
    rectTrfm.anchorMax = rawImgInfo.anchorMax;
    rectTrfm.pivot = rawImgInfo.pivot;

    rectTrfm.offsetMin = rawImgInfo.offsetMin;
    rectTrfm.offsetMax = rawImgInfo.offsetMax;

    rectTrfm.rotation = rawImgInfo.rot;
    rectTrfm.localScale = rawImgInfo.scale;
}

谢谢 @程序员,感谢您的帮助。我一定会试试,并且如果有什么问题,我会告诉你的。 - Luzan Baral
没问题,如果你测试时遇到任何问题,请告诉我。 - Programmer
你有测试过它吗?有出现问题吗? - Programmer
1
@程序员 一直在寻找将视频RawImage设置为全屏的方法。刚刚尝试了这个方法,成功了。谢谢。 - PassetCronUs

1
我用以下代码,在 RectTransform 上将其绕 Z 轴旋转 90 度,成功实现了此要求。
    private void FixContainerSizeInstantly()
    {
        container.sizeDelta = new Vector2(parent.rect.height, parent.rect.width);
    }

其中container是旋转的RectTransform,而parent是一个具有锚点使其始终全屏的RectTransform

enter image description here

我将在代码中添加DOTween以实现缩放、旋转和位置动画,但你需要的值都在我分享的方法中。
以下是全屏画布的配置方式,我使用了一个不同的画布来使所有内容模块化。

enter image description here enter image description here

对于旋转部分,您可以从原始视频的位置和大小开始,并将其Tween到90度变化和我分享的方法给出的大小,位置在屏幕中心。
Tween应该是大小增量,锚点应该像这样。

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接