Hey all,
I’ve been building out the UI for a game using the UI Toolkit. The current screen I’m creating has a video background. To achieve this, I use a video player component to record a video clip (.webm) to a render texture, and assign that to the BackgroundImage of the visual element. This is working fine.
For this “caught” screen, I have two videos. When the player gets caught, I play the first video. That video is supposed to blend seamlessly into the second video, which will run in a loop until the player presses continue. But I can’t figure out how to seamlessly transition from video A to video B. I have tried many approaches throughout the forums and documentation, but I can’t get rid of a single-frame flicker that happens between the two videos.
My general approach is to assign the two video clips to variables in the script. I assign video A to the VP and create a blank RT on awake, then assign this to the VP’s target texture. Using VP.loopPointReached, I’ve tried switching between the two a few ways:
- calling targetTexture.Release(), assigning video B to VP.Clip, and calling VP.Prepare() (keeping the same render texture)
- creating a second RT on Awake and calling Prepare, then reassigning the VP.targetTexture on loopPointReached to the second RT so it’s already “prepared” in advance;
- calling targetTexture.Release(), creating a new RT, and reassigning the VP’s clip and targetTexture to video 2 and RT 2, respectively;
- creating a second VP and RT for video B (both at runtime and in the editor), disabling VP 1 and enabling VP 2;
- various combinations of the above, with a bunch of random attempts from forums I’ve read online, putting some pieces in coroutines, etc.
I recreated the issue in a dummy project to share here. My main code is a bit of a mess from trying so many different things so the repro project doesn’t necessarily represent all of my efforts, but it shows the issue, and it’s as simple as I could make it.
I would be super grateful for some guidance on the “proper” way to implement this, avoiding the one (or more) frame flicker that happens between the two videos.
Tested using 2023 Macbook Pro M2 running Sonoma 14.4.1, as well as a Linux running the latest PopOS. The attached project was written on the macbook.
Unity version 2022.3.4f1 with latest versions of all relevant packages
The zip is a bit too large to upload (presumably because of the webms) so here’s a dropbox link: Dropbox
Here’s the relevant code (reminder this is just a dummy project I threw together in 10 mins to repro the issue, don’t judge my lazy code
(unless it’s actually causing the issue)):
public class UI : MonoBehaviour
{
// visual element variables...
private VisualElement _container;
public VideoPlayer videoPlayer;
public RenderTexture renderTexture => videoPlayer.targetTexture;
public VideoClip initialClip;
public VideoClip loopingClip;
private void Awake()
{
// set up root visual elements
PlayVideo();
}
private void PlayVideo()
{
videoPlayer.clip = initialClip;
videoPlayer.targetTexture =
new RenderTexture(1920, 1080, GraphicsFormat.R8G8B8A8_UNorm, GraphicsFormat.D32_SFloat_S8_UInt);
videoPlayer.targetTexture.Create();
videoPlayer.loopPointReached += InitiateLoop;
_container.style.backgroundImage = new StyleBackground(Background.FromRenderTexture(renderTexture));
}
private void InitiateLoop(VideoPlayer vp)
{
videoPlayer.targetTexture.Release();
videoPlayer.clip = loopingClip;
videoPlayer.Play();
videoPlayer.loopPointReached -= InitiateLoop;
}
}