Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity - How to rotate and full screen video, played using VideoPlayer API on RawImage

As MovieTexture has been deprecated after Unity 5.6.0b1, I am using VideoPlayer Api to play video over RawImage for Android, by taking reference from here. I am trying to add a toggle to switch from initial size of video played over RawImage Texture to full screen and back to original after video stops.

I have a perfectly playing video, and so far I am able to change the transform of the video to stretch to full screen with this code.

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);
    }
}

First two line inside the if block is able to full screen the RawImage on which the video is played effect shown in section 2 of image. Here's the docs for Vector2.

For the third line code of rotation, I took reference from this discussion on Unity Forum, but still I am not getting the effect as I wanted, result in section 3. I wanted to rotate the content of the RawImage, but I am rotating the RawImage itself, it might be because the reference is not describing to rotate the content.

Can any one help me find out how can I solve it. If it helps version of Unity I am using is Unity 5.6.0b11 Beta, and download the sample project if you want to test in on your device. Unity Video Player.zip 18.33MB You can also follow this Video Tutorial on new VideoPlayer from YouTube.

Full Screen and Rotate Video Played using Unity VideoPlayer on RawImage

Update 1

So far, the only thing I got is, I tried only with the rotation code and by removing first two lines inside if block, I was able to rotate the video, but when I try to stretch the RawImage, it is streching outside of the screen. See here for the image

Update 2

After lots of research, hit and trials. I finally did the fullscreen and rotation of the RawImage to play full screen videos on Unity with this code.

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

But, as you see, values I provide to the vector are static numbers and has no guarantee to work on multiple screen sizes. Well, rotating the RawImage was confusing as the axis rotates along with the RawImage, but some components were not changed or rotated, and when changing offset values, the RawImage changed it value in reference to the older Rect (I really don't know what is happening here). enter image description here

Rotating RawImage rotates the axis attached to it. On the image above, you can see the RawImage is rotated, and that in turn rotates the Axis. But even when the image is rotated you can see there's some reference line.

enter image description here

How I tried to fix the problem? [Failed]

I tried to solve the problem in new way, I created a new RawImage that fits to the canvas and is already rotated and attached to the script StreamVideo.cs as the previous RawImage. Initially it is in inactive mode, and is switched to active when user commands to fullscreen. When it goes to full screen the video is played in new RawImage.

public void playFullScreen() {
    isFullScreen = true;
    imageFullScreen.gameObject.SetActive(true);
    imageFullScreen.texture = videoPlayer.texture;
    image.gameObject.SetActive(false);
}

But, with this I had problem of starting the video from the same frame on the new RawImage when it is switched to full screen, and same problem when toggling back to small screen.

Summary:

Looking at update 2, I am able to play, pause, full screen and rotate the video but, with the plain numeric values on offsetMax and offsetMin. I am trying to learn if there is a way to curate those value through script to fit to multiple screen sizes. I know it might sound simple but the tricky part is, for the screen of my need, the reference of the value I provided works like this. Notice the dashed rectangle in picture. enter image description here

like image 293
Luzan Baral Avatar asked Mar 20 '17 06:03

Luzan Baral


People also ask

How do I play video in Webgl unity?

You can either place your video under StreamingAssets path or external file server, then you can provide the video URL as the source. Even then you would need to take care of following: CORS in case of external file server.

How do I play a video on an object in unity?

Drag the VideoMaterial onto your 3D plane. Add a Video Player component to the 3D object, drag the VideoSample file into the Video Clip property, and the VideoTexture into the Target Texture property. Push play on the Unity Editor and your video will begin to play.

What is Video Player in unity?

Description. Plays video content onto a target. Content can be either a VideoClip imported asset or a URL such as file:// or http:// . Video content will be projected onto one of the supported targets, such as camera background or RenderTexture.


2 Answers

I achieved it rotating 90 degrees on Z on a RectTransform with this code.

    private void FixContainerSizeInstantly()
    {
        container.sizeDelta = new Vector2(parent.rect.height, parent.rect.width);
    }

Where the container is the rotated RectTransform and the parent is a RectTransform with anchors always making it full screen.

enter image description here

I will add DOTween to animate it in scale, rotation and position, but the values you need are in that method I shared.

Here is how the full screen canvas is configured, I used a different canvas to have everything modular.

enter image description here enter image description here

For the rotation part you can start with the position and size of the original video and tween it to the 90 degrees change and the size given by the method I shared, with position at center of screen.

The tween should be size delta and the anchor should be like this.

enter image description here

like image 135
Horothenic Avatar answered Sep 18 '22 15:09

Horothenic


I wanted to do the-same thing but ran into the-same exact issue. I do believe that this is a a bug but did manage to come out with a solution.

This can be done with anchors, pivot point and the size of the screen(Screen.width,Screen.height) or the size of the Canvas. In my case, I will use the size of the Canvas instead.

When you hold the Alt key and click on the stretch icon of the RawImage RectTransform, the RawImage will be displayed full screen. You can do the-same thing via code with the values that changed in the Editor when you do this like below:

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;

It works and should give you full screen RawImage. The problem is that it works when the rotation is at 0, and 180 only or also know as when rotation upside down. It doesn't work when the rotation is -90, 90 and 270. These angles are usually what you'll get if RawImage is rotated right or left. I suspect that this is a bug.

To fix that, you calculate the aspect ratio from the size of the Canvas RectTransform then use it to create anchorMin and anchorMax. The rest of the code should remain the-same.

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;

This should work for -90, 90 and 270 angles but not for 0, and 180. It is not a problem since our first code works with 0, and 180 angles. We can detect the angle during run-time and execute the code based on the current angle of the RawImage.

You can see the complete function that combines both code as StretchImageFullScreen in the code below. Below is an example code that toggles the video between full screen and the original size of the RawImage when the Space key is done. To exit the toggle mode, press the R key. The RawImageInfo struct is used to copy the RectTransform information before toggling to full screen so that the default position/rotation can be restored when toggled again with the Space key or when the R key is pressed.

Add the code below to the code from the other answer and you should be able to toggle between full screen video and the default RawImage size and should be able to rotate it with the second parameter in the StretchImageFullScreen function.

//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;
}
like image 36
Programmer Avatar answered Sep 19 '22 15:09

Programmer