> ## Content Index
> Fetch the complete content index at: https://blog.febucci.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Unity Skip Cutscene Button: Timeline Implementation
- URL: https://blog.febucci.com/2019/02/skip-cutscenes-button/
- Published: 2019-02-01T14:00:00.000Z
- Updated: 2026-04-06T07:25:43.000Z
- Description: Implement a skip cutscene button in Unity using a hold-to-confirm pattern with Image.fillAmount, with working C# code you can drop into your project.
- Author: Federico Bellucci
- Tags: Tutorials, Unity

Need a hold-to-skip button for your cutscenes in Unity? This tutorial covers the full implementation: a radial fill UI that tracks how long the player holds the button, with separate fill and drain speeds so accidental skips don't happen. About 30 lines of C# total, and the logic works in any engine.

## How do I implement a skip cutscene button in Unity?

Here's my simple tutorial about how to create a **"Skip Cutscenes button"** in Unity (the logic applies to any other engine too). You can find below the code and the download links.

0:00 

/0:05 

1× 

## How it works

The script uses Unity's `Image.fillAmount` (which is already clamped to \[0, 1\] by the engine) as the progress value. Each Update frame, it increases `fillAmount` by `activeSpeed * Time.deltaTime` while the key is held, or decreases it by `cooldownSpeed * Time.deltaTime` when it isn't. Once `fillAmount` reaches exactly 1, the skip function fires once (guarded by a bool flag so it only runs once). The button also scales from its start size to `targetHolderScale` using an EaseIn curve (`fillAmount * fillAmount`) so it feels snappier at the end.

The whole thing is about 30 lines of C#. The `activeSpeed` and `cooldownSpeed` are separate values so you can tune how fast the button fills vs. drains - a common pattern is to make cooldown slightly faster than fill (here it's 0.5 fill vs. 0.6 drain) to add a bit of urgency. The `fillAmount * fillAmount` scaling is a basic EaseIn curve; if you want smoother curves, check out my [easing functions](https://blog.febucci.com/2018/08/easing-functions/) tutorial. And if you need to set up the UI canvas properly, here's our [Unity UI for all resolutions](https://blog.febucci.com/2018/10/unity-ui-tutorial/) guide.

## Download

You can download the free UI "Prompts Pack" [clicking here](https://thoseawesomeguys.com/prompts/?ref=blog.febucci.com), created by [@Xelu](https://twitter.com/xelubest?ref=blog.febucci.com). If you're using Timeline for your cutscenes, the [Unity Timeline documentation](https://docs.unity3d.com/Packages/com.unity.timeline@1.8/manual/index.html?ref=blog.febucci.com) covers how to control playback via `PlayableDirector`.

## Code

```csharp
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Assertions;

public class HandlerScript : MonoBehaviour
{

    //The circle that shows us the overall progress
    public Image fillImage;
    //Holder of the entire button, used to change its scale
    public RectTransform holderRect;

    //Start scale of the holder
    Vector2 startHolderScale;
    //The desired scale we want when we complete the input, i.e. the input percentage is 1
    public Vector2 targetHoldercale = new Vector2(1.2f, 1.2f);

    private void Awake()
    {
        //Assures we don't have null references
        Assert.IsNotNull(fillImage);
        Assert.IsNotNull(holderRect);

        startHolderScale = holderRect.localScale;
        fillImage.fillAmount=0;
    }

    //The key we want to press
    public KeyCode keyCode = KeyCode.X;

    //Speed that increases the progress if we press
    public float activeSpeed = .5f;

    //How fast the progress decreases if we don't press the desired key
    float cooldownSpeed = .6f;

    //Prevents the function to be executed more than once
    bool functionTriggered = false;

    void Update()
    {
        //Increases or decreases our progress based on our input (and if we didn't already trigger the function)
        //No need to clamp, since fillAmount is already clamped by Unity in the [0,1] range
         fillImage.fillAmount +=
         ((Input.GetKey(keyCode) && !functionTriggered) ?
                activeSpeed :
                 -cooldownSpeed) * Time.deltaTime;

        //Changes the size of the button based on our progress
        holderRect.localScale = Vector2.Lerp(
            startHolderScale,
            targetHoldercale,
            fillImage.fillAmount * fillImage.fillAmount //you can apply an interpolation there, I applied EaseIn
            );

        //Triggers the function if we didn't already, and the progress/percentage is 1
        if (!functionTriggered && fillImage.fillAmount == 1)
        {
            functionTriggered = true;

            Debug.Log("Button pressed completely");

            //Do something here
            //Skip cutscene or similar
            //[...]
        }

    }
}

```

## Frequently asked questions

### Can I use a gamepad button instead of a keyboard key?

Yes, swap `Input.GetKey(keyCode)` for the equivalent gamepad input via the Input System's `Gamepad.current` API, or assign a gamepad button to a KeyCode in the old input manager.

### Why does the cooldown use a different speed than the fill?

It's a design choice. Having the drain slightly faster than the fill (0.6 vs 0.5 here) means the player needs to hold the button fairly consistently, which avoids accidental skips and gives a better feel.

### How do I prevent the button from triggering twice?

The `functionTriggered` bool guards against that. Once set to true, neither the fill check nor the scale update can fire the action again until you reset it manually.

### Can I reuse this for anything other than cutscene skipping?

Yes, the "hold to confirm" pattern works for any action you want to require deliberate input: deleting a save file, reviving a teammate, opening a chest. Just put whatever you want in the `//Do something here` block.