---
title: "Working with the StreamingAssets Folder - 2019.2"
content_type: tutorial
url: "https://learn.unity.com/tutorial/working-with-the-streamingassets-folder-2019-2?language=en"
language: en
difficulty: intermediate
duration_minutes: 25
unity_version:
  - "2019.4"
supported_unity_versions:
  - name: "2019.4"
    url: "https://learn.unity.com/tutorial/working-with-the-streamingassets-folder-2019-2.md?language=en&version=2019.4"
  - name: "2019.2"
    url: "https://learn.unity.com/tutorial/working-with-the-streamingassets-folder-2019-2.md?language=en&version=2019.2"
last_updated: "2026-08-04T14:22:06.000Z"
---

# Working with the StreamingAssets Folder - 2019.2

Discover how to use the StreamingAssets folder so users can load custom images, audio, and levels into your project.

In this tutorial, you’ll learn how to use the _StreamingAssets_ folder to allow users to load their own images, songs, and even game levels into a project.

## 1. Working with the StreamingAssets Folder

This tutorial has been verified using Unity 2019.4.14f1 LTS - [https://learn.unity.com/tutorial/working-with-the-streaming-assets-folder-2019-3](https://learn.unity.com/tutorial/working-with-the-streaming-assets-folder-2019-3)

In this tutorial, you’ll learn how to use the _StreamingAssets_ folder to allow users to load their own images, songs, and even game levels into a project.

## 2. Loading Assets Stored in the StreamingAssets Folder

The process for loading Assets from the _StreamingAssets_ folder is the same as for loading a web-based resource, as we’ll see in the following exercise.

## 3. Loading Images for Display

For this first exercise, we’ll use a button loaded from _StreamingAssets_ to replace an image.

1\. Inside the Assets folder, create two new folders and name them: _Images_ and _StreamingAssets_.

2\. Inside the _Images_ folder, place an image file, making note of the file name.  This will be the image first loaded during runtime. (Example: ‘_Image1.png_)

3\. Inside the _StreamingAssets folder_, place another image file, again making note of the file name. (Example: ‘_Image2.png’._)

4\. From the GameObject drop-down menu, select **UI** > **Raw Image**.  Name this image _ImageDisplay_. You can assign the first image to load ‘_Image1.png’_ to the ImageDisplay by selecting the circle button, next to the Texture field in the Inspector window (**Figure 01**).

![Figure 01: Selecting the first image for the ImageDisplay in the Inspector Window](https://connect-mediagw.unity.com/h1/20210104/learn/images/bb3614ca-42f0-42c5-bbfa-69b9b9173857_image6.png)

Note that any images in your project are visible for selection, **_except_** for any saved images inside the StreamingAssets folder.  Images saved to the StreamingAssets folder remain hidden.

5\. From the GameObject drop-down menu, select **UI** > **Button**. Name this button _ChangeImage_.  We will use a script in an upcoming step to set the second image to ‘_Image2.png’._

6\. With the ImageDisplay object selected in the Hierarchy Window, Create a new C# script by selecting the button: **Add Component** > **New script**.  Rename it to _ImageLoader_.

7\. Double-click the script to open in your script editor.

8\. On line 4, type:

```csharp
using UnityEngine.UI;
using System.IO;
using UnityEngine.Networking;
```

9\. We use a helper function to return the path to the file we want to load because the _StreamingAssets_ folder location varies by platform. We’ll use this in all of our examples. Inside the class definition, beginning on line 9, type In the following code, replacing “Image2.png” with the name of your image file saved to the StreamingAssets folder.

```csharp
public string customTextureFilename = "Image2.png";

private UnityWebRequest uwr;

public static string GetFileLocation(string relativePath)
{
    return "file://" + 
Path.Combine(Application.streamingAssetsPath, relativePath);
}

public void ChangeImage()
{
    StartCoroutine(ChangeImageCo());
}

System.Collections.IEnumerator ChangeImageCo()
{
    using (uwr = UnityWebRequestTexture.GetTexture(GetFileLocation(customTextureFilename)))
    {
        yield return uwr.SendWebRequest();
        if (uwr.isNetworkError || uwr.isHttpError)
        {
            Debug.Log(uwr.error);
        }
        else
        {
            gameObject.GetComponent<RawImage>().texture = DownloadHandlerTexture.GetContent(uwr);
        }
    }
}
```

10\. You can also load images from any _StreamingAssets_ subfolder. Let’s say your image file is named “logo.png” and is in a subfolder called “LogoImages.” In this case, you’d specify “LogoImages\\\\logo.png” for customTextureFilename if referencing this file in the script. We will use the double-slash \\\\ to reference the folder location and image name. (A single slash \\ is used as an escape sequence for including special characters in the code, and wouldn’t work in this case) You don’t need to use \\\\ if you’re just typing the file name in the Unity Inspector.  In that case, you’d just enter _LogoImages/logo.png_ (**Figure 02**).

![Figure 02: Specifying a file stored in a StreamingAssets subfolder, using the Inspector](https://connect-mediagw.unity.com/h1/20210104/learn/images/8121397d-57c1-4452-8577-f26cb8045937_image7.png)

11\. Save changes and return to the Unity Editor.

12\. With the ImageDisplay button selected in the Hierarchy window, select the Inspector window, and on the Button properties, select **+** to add an action to its OnClick event listener (**Figure 03**).

![Figure 03: Adding an action to a button’s OnClick event listener](https://connect-mediagw.unity.com/h1/20210104/learn/images/64f00c7b-ae85-4fea-b404-cf6aaea8c24d_image1.png)

13\. Drag ImageDisplay into the slot labeled None (Object).

14\. Select the drop-down currently labeled No Function and select **ImageLoader** > **ChangeImage()** (**Figure 04**).

![Figure 04: Setting the action](https://connect-mediagw.unity.com/h1/20210104/learn/images/e8ae00fd-fe86-40f5-a521-b4b570a3a61f_image5.png)

15\. Enter Play Mode. When you select the UI Button, the Raw Image changes from ‘Image1.png’ from the Images folder to ‘Image2.png’ loaded from the StreamingAssets folder.

16\. Exit Play Mode.

## 4. Custom Soundtracks

For our next example, we’ll load a song from the _StreamingAssets_ folder at the start of the Scene, set it to loop, and start it playing. This could serve as the basis for allowing a user to load their own background music in a game editor.

1\. Inside _StreamingAssets_, create a folder called _Music_ and place your song in there. The song needs to be in a Unity-supported format.

2\. Select **Create Empty** from the GameObject drop-down and name it _BGMPlayer_.

3\. Attach a new C# script to BGMPlayer called _BGMLoader_.

4\. Double-click _BGMLoader_ to open your script editor.

5\. On line 4, type:

```csharp
using System.IO;
using UnityEngine.Networking;
```

6\.  Inside the class definition, type:

```csharp
 private string musicFile = "Music\\BGM.wav"; // replace with the filename of your song
	private AudioSource audioSource;

	private void Start()
	{
    	StartCoroutine(MusicPlayer());
	}

	public static string GetFileLocation(string relativePath)
	{
    	return "file://" + Path.Combine(Application.streamingAssetsPath, relativePath);
	}
```

7\. Now we’ll load our song. If the GameObject to which this script is attached already has an AudioClip, we need to clear that out. If there’s no AudioSource, a new one will be created. Volume and looping settings are applied to the Audio Source, and the song is loaded and assigned. Once ready to play, the song starts and the Coroutine exits.

After the code from Step 6, type

```csharp
IEnumerator MusicPlayer()
	{
    	//Ensure the AudioType matches your file extension type
    	using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(GetFileLocation(musicFile), AudioType.WAV))
    	{
        	yield return uwr.SendWebRequest();

        	if (uwr.isNetworkError || uwr.isHttpError)
        	{
            	Debug.Log(uwr.error);
        	}
        	else
        	{
            	audioSource = gameObject.GetComponent<AudioSource>();
            	if (audioSource == null)
                	audioSource = gameObject.AddComponent<AudioSource>();
            	else if (audioSource.clip != null)
            	{
                	//Unload the existing clip
                	audioSource.Stop();
                	AudioClip currentClip = audioSource.clip;
                	audioSource.clip = null;
                	currentClip.UnloadAudioData();
                	DestroyImmediate(currentClip, false);
            	}

            	audioSource.loop = true;
            	audioSource.volume = .2f;
            	audioSource.clip = DownloadHandlerAudioClip.GetContent(uwr);
            	audioSource.Play();
            	yield return null;

        	}
    	}
}
```

8\. Save changes and return to Unity.

9\. Enter Play Mode. Your song should load and begin playing.

10\. Exit Play Mode.

## 5. Custom Game Levels

For our final example, we’ll revisit loading a Texture from _StreamingAssets_. This time, we’ll use it as the legend for building a level, with each pixel representing a cell in the Unity world, and each unique color representing some Prefab. This exercise can be done in the same Scene as our previous example to load not just custom music, but also a custom level for it to accompany.

1\. Inside _StreamingAssets_, create a folder called _Levels_.

2\. Outside of Unity, create a 64x64 bitmap. Fill it with white and, using the hard pixel brush/pencil tool, draw some assortment of dots, lines, and shapes in two or three  colors, making note of each color. Be sure that you’re not using anti-aliasing, but rather hard pixels (**Figure 05**).

![Figure 05: The beginnings of our level](https://connect-mediagw.unity.com/h1/20210104/learn/images/b7e8da96-7858-467c-b43f-489559440900_image4.png)

3\. Save the image, and drop it into the _Levels_ folder. Make note of the file name.

4\. If you don’t already have a subfolder named _Prefabs_ in your _Assets_ folder, create one.

5\. From the GameObject drop-down, select **3D Object** > **Cube**. Drag this cube into _Prefabs_.

6\. Repeat this with as many colored shapes as you used in your image, or create whatever Prefab you like. Ideally, your Prefabs should be exactly 1 Unity unit in each dimension. The reason why will become clear once we load our level.

7\. Select **Create Empty** from the GameObject drop-down and name it _LevelLoaderObject_.

8\. Attach a new C# script to _LevelLoaderObject_ called _LevelLoader_.

9\. Double-click _LevelLoader_ to open in your script editor.

10\. Before we define our class, we’ll create a data structure for our level editor. This structure will hold a color and an assigned Prefab. We’ll make it Serializable so that we can edit it in the Inspector. Outside the class definition, type:

```csharp
using System;
using System.IO;
using UnityEngine.Networking;

[Serializable]
public struct LevelPiece
{
    public Color color;
    public GameObject prefab;
}
```

11\. We’ll now declare our custom level file name, our list of possible level pieces, and our helper function to find our files in _StreamingAssets_ before defining our method to actually load the level in the next step. Inside the class definition, type:

```csharp
public string levelmap = "Levels\\1.png";
public LevelPiece[] pieces;

public static string GetFileLocation(string relativePath)
{
    return “File://” + Path.Combine(Application.streamingAssetsPath, relativePath);
}
```

12\. Our level loader loads the map from _StreamingAssets_ and iterates through each pixel. If the pixel’s color matches that of any of the defined level pieces, that piece is instantiated in the matching location of the game world.

Type:

```csharp
public IEnumerator LoadLevel()
{
    using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(GetFileLocation(levelmap)))
    {

        yield return uwr.SendWebRequest();
        if (uwr.isNetworkError || uwr.isHttpError)
        {
            Debug.Log(uwr.error);
        }
        else
        {
            var loadedTexture = DownloadHandlerTexture.GetContent(uwr);
            Vector2 mapsize = new Vector2(loadedTexture.width, loadedTexture.height);
            Texture2D maptex = loadedTexture;
            for (int x = 0; x < mapsize.x; x++)
            {
                for (int y = 0; y < mapsize.y; y++)
                {
                    Color col = maptex.GetPixel(x, y);
                    foreach (LevelPiece piece in pieces)
                    {
                        if (col == piece.color)
                        {
                            Instantiate(piece.prefab, transform.position + Vector3.right * x + Vector3.up * y, Quaternion.identity);
                        }
                    }
                }
            }
        }
    }
}
```

13\. We’ll invoke LoadLevel as soon as the Scene starts. In **Start**, type:

```csharp
StartCoroutine(LoadLevel());
```

14\. Save changes and return to Unity.

15\. Select the **LevelLoaderObject**. Select the triangle next to Pieces in its Inspector. Set **Size** to the number of colors you used (aside from the background color).

16\. For each piece, assign the color you used to represent it in the bitmap, making sure to set alpha to **255**. This is necessary because Unity considers the alpha value as well as rgb when looking for a match.

17\. After each color, assign the matching Prefab (**Figure 06**).

![Figure 06: Our level setup](https://connect-mediagw.unity.com/h1/20210104/learn/images/751d1e4a-3b21-4e8d-96fc-fcc31893e63a_image2.png)

18\. Enter Play Mode. The level should load instantly (**Figure 07**).

![Figure 07: Our level loaded](https://connect-mediagw.unity.com/h1/20210104/learn/images/0994c2c5-470b-42ca-b601-d09b41bad932_image3.png)

19\. Exit Play Mode. This script can be used for 2D as well, by replacing Prefabs with Sprites and instantiating a 1x1 unit (not pixel) Sprite Prefab at each cell location.


## 6. Conclusion

The _StreamingAssets_ folder is an easy way to allow users to save, load, and work with their own files in your Unity Project.
