<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bernard Masika</title>
    <description>The latest articles on DEV Community by Bernard Masika (@bernardmasika).</description>
    <link>https://dev.to/bernardmasika</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F859119%2F1556ce19-9174-4b09-86de-2e972ca77aa6.jpeg</url>
      <title>DEV Community: Bernard Masika</title>
      <link>https://dev.to/bernardmasika</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bernardmasika"/>
    <language>en</language>
    <item>
      <title>Unity Video Player: How to know if the video has finished playing</title>
      <dc:creator>Bernard Masika</dc:creator>
      <pubDate>Tue, 15 Oct 2024 09:43:33 +0000</pubDate>
      <link>https://dev.to/bernardmasika/unity-video-player-how-to-know-if-the-video-has-finished-playing-3fm0</link>
      <guid>https://dev.to/bernardmasika/unity-video-player-how-to-know-if-the-video-has-finished-playing-3fm0</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Unity Engine has a special component for playing a video file during runtime. It’s called &lt;strong&gt;&lt;em&gt;Video Player&lt;/em&gt;&lt;/strong&gt;. It works by attaching the Video file to the GameObjects and play them on that GameObject’s &lt;strong&gt;&lt;em&gt;Texture&lt;/em&gt;&lt;/strong&gt; at run time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsrw4gmuqe2y7quxu36zg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsrw4gmuqe2y7quxu36zg.jpg" alt="Screenshot of a Unity editor interface showing a scene with a selected plane object in the center. The hierarchy panel on the left lists " width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to use Video Player&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To achieve what’s shown on the screenshot above;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a GameObject on the hierarchy by right clicking on it and select the object you want ( I chose plane),&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then on the inspector column (at your far right, if you didn’t change the default editor layout) click &lt;em&gt;add component&lt;/em&gt; and search for Video Player.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;REMEMBER:&lt;/strong&gt; The GameObject you select must have a texture on it, as per our definition.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8f0k7z1q5xpxk37qfxqy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8f0k7z1q5xpxk37qfxqy.jpg" alt="A screenshot showing Video Playing in runtime" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Now, drag your video file to the Video clip property on the Video player component.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click play to watch your video, Easy right!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; The above example uses the default texture of the gameobject, there are more ways to specify the texture depending on your scenario, but I won’t cover them today!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why will you want to know the video has finished play
&lt;/h2&gt;

&lt;p&gt;In one or more scenarios, you may want part of your app to be aware when a certain video has finished playing. just to mention a few;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transition to Another Scene or Event&lt;/strong&gt;: You might want to transition to a new scene, trigger an animation, or load new content once the video is done. For example, after an intro video plays, you could switch to the main menu.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Display User Interface (UI)&lt;/strong&gt;: When a video ends, you could bring up buttons or menus, such as a "Replay" button, or options for the player to proceed to the next level or restart&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tutorials or Guides&lt;/strong&gt;: After a tutorial video finishes, you may want to unlock a new feature, prompt users with the next instruction, or trigger the next step in a learning sequence.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;and many more..&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the moment of writing, there’s no direct indicator in the Inspector to know when a video has finished, you will have to create a custom script for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to do it.
&lt;/h2&gt;

&lt;p&gt;There are a few quick ways to do it;&lt;/p&gt;

&lt;p&gt;1.By Using Video Player Event called &lt;code&gt;loopPointReached&lt;/code&gt;&lt;strong&gt;&lt;em&gt;.&lt;/em&gt;&lt;/strong&gt; An Event Invoked when the Video Player reaches the end of the content to play. &lt;strong&gt;(Recommended Way)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Code Snippet &lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine.Video&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VideoEndCheck&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;VideoPlayer&lt;/span&gt; &lt;span class="n"&gt;videoPlayer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;videoPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loopPointReached&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;OnVideoEnd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnVideoEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VideoPlayer&lt;/span&gt; &lt;span class="n"&gt;vp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Video has finished playing!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// You can add any action you want to take here.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Script Breakdown&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We created a public variable of type &lt;code&gt;VideoPlayer&lt;/code&gt; to allow us assign a &lt;code&gt;VideoPlayer&lt;/code&gt; component from the Unity Editor to the script.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the Start Method, we registered Our method &lt;code&gt;OnVideoEnd&lt;/code&gt; as an event handler for the &lt;code&gt;loopPointReached&lt;/code&gt; event of the &lt;code&gt;VideoPlayer&lt;/code&gt;. Basically it means,&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;“Hey unity when you trigger the event loopPointReached for this video player, please call our method OnVideoEnd()”&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;We then define our Method where you can do what you wanted when the video ends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Must I include the parameters in the method?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Absolutely YES, why?;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Event Structure&lt;/strong&gt;: The &lt;code&gt;loopPointReached&lt;/code&gt; event passes a 
&lt;code&gt;VideoPlayer&lt;/code&gt; parameter, so the event handler (&lt;code&gt;OnVideoEnd&lt;/code&gt;) must match that expected signature, meaning it should take a &lt;code&gt;VideoPlayer&lt;/code&gt; parameter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessing the VideoPlayer&lt;/strong&gt;: Inside the event handler, you might need to interact with the specific &lt;code&gt;VideoPlayer&lt;/code&gt; instance that finished playing, such as for pausing, restarting, or querying its state. The &lt;code&gt;vp&lt;/code&gt; argument provides a way to do that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: If you are handling multiple &lt;code&gt;VideoPlayer&lt;/code&gt; instances in a scene, you can differentiate which one triggered the event by referencing &lt;code&gt;vp&lt;/code&gt;. Without this parameter, the event would be less flexible for more complex scenarios.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;2.By comparing between &lt;code&gt;videoPlayer.frameCount&lt;/code&gt; and &lt;code&gt;videoPlayer.frame&lt;/code&gt; properties.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Code Snippet&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine.Video&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VideoFrameCheck&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;VideoPlayer&lt;/span&gt; &lt;span class="n"&gt;videoPlayer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Check if the current frame is the last frame of the video&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;videoPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;videoPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frameCount&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Video has finished playing!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// Add any other action you want to take here.&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;videoPlayer.frameCount&lt;/code&gt; gives the total number of frames in the video.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;videoPlayer.frame&lt;/code&gt; provides the current frame the video player is on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When &lt;code&gt;videoPlayer.frame&lt;/code&gt; reaches &lt;code&gt;videoPlayer.frameCount - 1&lt;/code&gt;, the video has finished.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We subtract 1 from &lt;code&gt;videoPlayer.frameCount&lt;/code&gt; because frames are &lt;strong&gt;zero-indexed&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3.Using &lt;code&gt;isPlaying&lt;/code&gt; Property to check if the video has stopped playing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;This means we need to check the video player if its still playing the video or not every time (every frame).&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine.Video&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VideoCheckIsPlaying&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;VideoPlayer&lt;/span&gt; &lt;span class="n"&gt;videoPlayer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;videoPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Video has finished playing!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// You can add any action you want to take here.&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
&lt;li&gt;We put our block of code for checking the status in the Update() method because it gets called every frame.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Which one is the best way then!?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The most recommended approach is using the &lt;strong&gt;event&lt;/strong&gt; (&lt;code&gt;loopPointReached&lt;/code&gt;). This is because it is event-driven, meaning it only triggers when the video ends, making it efficient and avoiding unnecessary checks every frame.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The second best option is &lt;strong&gt;checking the frame count&lt;/strong&gt;, which provides precise control by allowing you to directly compare the current frame with the total frame count of the video. However, this requires additional computation and frame checks in every &lt;code&gt;Update()&lt;/code&gt; cycle, which can be very expensive in terms of performance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lastly, &lt;strong&gt;using&lt;/strong&gt; &lt;code&gt;isPlaying&lt;/code&gt; is the least recommended as it only checks if the video is currently playing. It doesn't differentiate between the video ending or being paused, so it may require extra conditions to accurately detect the video's completion.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡&lt;br&gt;
I welcome any feedback in the comments, Let’s linkup on &lt;a rel="noopener noreferrer nofollow" href="https://www.linkedin.com/in/bernard-masika/"&gt;LinkedIn&lt;/a&gt;. Happy coding!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>unity3d</category>
    </item>
  </channel>
</rss>
