Skip to main content

Command Palette

Search for a command to run...

Create stylish and modern tutorials in Unity games using video tips in Pop-Up windows

Simple Video-Based Tutorials for your Unity Game

Updated
5 min read
Create stylish and modern tutorials in Unity games using video tips in Pop-Up windows
E

🤔 My name is Elijah, I've been working in the game development industry for more than 10 years and I love to solve various problems related to my field.

🔭 My main tool as a person working with both mobile and console games is of course Unity.

⚡I also worked with WebGL and used mostly C# or NodeJS as a server language. I would be glad to share my experience - you can always write to me in Discord (SodaBoom).

Hi everyone, in today's tutorial I'm going to talk about creating stylish tutorial windows for your games using video. Usually such inserts are used to show the player what is required of him in a particular training segment, or to show a new discovered ability in the game.

Creating Tutorial Database

First, let's set the data about the tutorials. I set up a small model that stores a value with tutorial skip, text data, video reference and tutorial type:

// Tutorial Model
[System.Serializable]
public class TutorialData
{
    public bool CanSkip = false;
    public string TitleCode;
    public string TextCode;
    public TutorialType Type;
    public VideoClip Clip;
}

// Simple tutorial types
public enum TutorialType
{
    Movement,
    Collectables,
    Jumping,
    Breaking,
    Backflip,
    Enemies,
    Checkpoints,
    Sellers,
    Skills
}

Next, I create a payload for my event that I will work with to call the tutorial interface:

public class TutorialPayload : IPayload
{
    public bool Skipable = false;
    public bool IsShown = false;
    public TutorialType Type;
}

Tutorial Requests / Areas

Now let's deal with the call and execution of the tutorial. Basically, I use the Pub/Sub pattern-based event system for this (you can read more about it in my other tutorial), and here I will show how a simple interaction based on the tutorial areas is implemented.

public class TutorialArea : MonoBehaviour
{
    // Fields for setup Tutorial Requests
    [Header("Tutorial Data")] 
    [SerializeField] private TutorialType tutorialType;
    [SerializeField] private bool showOnStart = false;
    [SerializeField] private bool showOnce = true;

    private TutorialData tutorialData;
    private bool isShown = false;
    private bool onceShown = false;

    // Area Start
    private void Start() {
        FindData();

        // If we need to show tutorial at startup (player in area at start)
        if (showOnStart && tutorialData != null && !isShown) {
            if(showOnce && onceShown) return;
            isShown = true;
            // Show Tutorial
            Messenger.Instance.Publish(new TutorialPayload
                { IsShown = true, Skipable = tutorialData.CanSkip, Type = tutorialType });
        }
    }

    // Find Tutorial data in Game Configs
    private void FindData() {
        foreach (var tut in GameBootstrap.Instance.Config.TutorialData) {
            if (tut.Type == tutorialType)
                 tutorialData = tut;
        }

        if(tutorialData == null)
            Debug.LogWarning($"Failed to found tutorial with type: {tutorialType}");
    }

    // Stop Tutorial Outside
    public void StopTutorial() {
        isShown = false;
        Messenger.Instance.Publish(new TutorialPayload
            { IsShown = false, Skipable = tutorialData.CanSkip, Type = tutorialType });
    }

    // When our player Enter tutorial area
    private void OnTriggerEnter(Collider col) {
        // Is Really Player?
        Player player = col.GetComponent<Player>();
        if (player != null && tutorialData != null && !showOnStart && !isShown) {
            if(showOnce && onceShown) return;
            onceShown = true;
            isShown = true;
            // Show our tutorial
            Messenger.Instance.Publish(new TutorialPayload
                { IsShown = true, Skipable = tutorialData.CanSkip, Type = tutorialType });
        }
    }

    // When our player leaves tutorial area
    private void OnTriggerExit(Collider col) {
        // Is Really Player?
        Player player = col.GetComponent<Player>();
        if (player != null && tutorialData != null && isShown) {
            isShown = false;
            // Send Our Event to hide tutorial
            Messenger.Instance.Publish(new TutorialPayload
                { IsShown = false, Skipable = tutorialData.CanSkip, Type = tutorialType });
        }
    }
}

And after that, I just create a Trigger Collider for my Tutorial zone and customize its settings:

Tutorial UI

Now let's move on to the example of creating a UI and the video in it. To work with UI I use Views - each View for a separate screen and functionality. However, you will be able to grasp the essence:

To play Video I use Video Player which passes our video to Render Texture, and from there it goes to Image on our UI.

So, let's look at the code of our UI for a rough understanding of how it works*(Ignore the inheritance from BaseView - this class just simplifies showing/hiding UIs and Binding for the overall UI system)*:

public class TutorialView : BaseView
{
    // UI References
    [Header("References")] 
    public VideoPlayer player;
    public RawImage uiPlayer;
    public TextMeshProUGUI headline;
    public TextMeshProUGUI description;
    public Button skipButton;

    // Current Tutorial Data from Event
    private TutorialPayload currentTutorial;

    // Awake analog for BaseView Childs
    public override void OnViewAwaked() {
        // Force Hide our view at Awake() and Bind events
        HideView(new ViewAnimationOptions { IsAnimated = false });
        BindEvents();
    }

    // OnDestroy() analog for BaseView Childs
    public override void OnBeforeDestroy() {
        // Unbind Events
        UnbindEvents();
    }

    // Bind UI Events
    private void BindEvents() {
        // Subscribe to our Tutorial Event
        Messenger.Instance.Subscribe<TutorialPayload>(OnTutorialRequest);

        // Subscribe for Skippable Tutorial Button
        skipButton.onClick.RemoveAllListeners();
        skipButton.onClick.AddListener(() => {
            AudioSystem.PlaySFX(SFXType.UIClick);
             CompleteTutorial();
        });
    }

    // Unbind Events
    private void UnbindEvents() {
        // Unsubscribe for all events
        skipButton.onClick.RemoveAllListeners();
        Messenger.Instance.Unsubscribe<TutorialPayload>(OnTutorialRequest);
    }

    // Complete Tutorial
    private void CompleteTutorial() {
        if (currentTutorial != null) {
            Messenger.Instance.Publish(new TutorialPayload
                { Type = currentTutorial.Type, Skipable = currentTutorial.Skipable, IsShown = false });
            currentTutorial = null;
        }
    }

    // Work with Tutorial Requests Events
    private void OnTutorialRequest(TutorialPayload payload) {
        currentTutorial = payload;
        if (currentTutorial.IsShown) {
           skipButton.gameObject.SetActive(currentTutorial.Skipable);
           UpdateTutorData();
           ShowView();
        }
        else {
           if(player.isPlaying) player.Stop();
           HideView();
        }
    }

    // Update Tutorial UI
    private void UpdateTutorData() {
        TutorialData currentTutorialData =
            GameBootstrap.Instance.Config.TutorialData.Find(td => td.Type == currentTutorial.Type);
        if(currentTutorialData == null) return;

        player.clip = currentTutorialData.Clip;
        uiPlayer.texture = player.targetTexture;
        player.Stop();
        player.Play();
        headline.SetText(LocalizationSystem.GetLocale($"{GameConstants.TutorialsLocaleTable}/{currentTutorialData.TitleCode}"));
        description.SetText(LocalizationSystem.GetLocale($"{GameConstants.TutorialsLocaleTable}/{currentTutorialData.TextCode}"));
    }

Video recordings in my case are small 512x512 clips in MP4 format showing certain aspects of the game:

And my TutorialData settings stored in the overall game config, where I can change localization or video without affecting any code or UI:

In conclusion

This way you can create a training system with videos, for example, showing what kind of punch your character will make when you press a key combination (like in Ubisoft games). You can also make it full-screen or with additional conditions (that you have to perform some action to hide the tutorial).

I hope I've helped you a little. But if anything, you can always ask me any questions you may have.

Z
zgd1y ago

We are willing to pay a high price to acquire the source code of a mobile game that is compatible with both Android and iOS platforms, for the purpose of learning and research. The game must meet the following criteria: it should be developed by a top-tier gaming company within the past 5 years, fully completed and matured, and preferably of the multiplayer online MMORPG or ARPG genre. If your game meets our interest, we will proceed with the transaction promptly and offer an upfront payment as a gesture of goodwill. Contact me q791864008q@gmail.com

Z
zgd1y ago

Who has access to the source code for a completed, large-scale multiplayer online Android and iOS game developed by a major gaming company? The game must have top-notch graphics. I will not accept games developed by individuals. We are located in Vietnam, and I am willing to pay a high fee to purchase it for learning and research purposes. I am sincere in my intention to buy, If I like your game,I can make a deposit first. Contact me q791864008q@gmail.com

Z
zgd1y ago

Who has the source code of a mature and large-scale multiplayer online mobile game from a major game company? It is required that the game must have mature commercialization and in-app purchases. Players can directly become stronger by purchasing in-app purchases. We are in Vietnam and I am willing to pay super high fees to buy. Contact me q791864008q@gmail.com

Z
zgd1y ago

Who has the source code of a mature and large-scale multiplayer online mobile game from a major game company? It is required that there should be mature commercialization and in-app purchases in the game, such as: card drawing, opening boxes, etc. We are in Vietnam and I am willing to pay super high fees to buy. Contact me q791864008q@gmail.com

Z
zgd1y ago

Who has the source code for mature large-scale mobile multiplayer online games from major gaming companies? I am willing to pay a reasonable fee for high-quality source code You can contact me q791864008q@gmail.com

Text Tutorials

Part 12 of 17

Detailed text-based tutorials for learning various aspects of game development on Unity. Basic and professional articles on the most important topics that no one else will tell you.

Up next

How AI can help you in game development - useful resources on using neural networks in game development on Unity

Creating games with AI and Unity is now even easier than you think