Skip to content

Instantly share code, notes, and snippets.

@Fenikkel
Last active July 13, 2024 14:47
Show Gist options
  • Save Fenikkel/b9a6a4ecbd9725bf203a9a4cd537ddda to your computer and use it in GitHub Desktop.
Save Fenikkel/b9a6a4ecbd9725bf203a9a4cd537ddda to your computer and use it in GitHub Desktop.
Streaming Assets Loaders

Streaming Assets Loaders

 

Notes

Loaders to get assets from StreamingAssets folder. Foolproof.

 

Usage

StreamingAssetsImageLoader is static, so you can call his functions from anywhere without any references.

  • LoadTexture2dFromPath:
  Texture2D texture2D = StreamingAssetsImageLoader.LoadTexture2dFromPath("Gallery/Projects/Photo.png");
  • LoadSpriteFromPath:
  Sprite sprite = StreamingAssetsImageLoader.LoadSpriteFromPath("Photo2.jpeg")
  • LoadTextures2dFromFolder:
  List<Texture2D> allTextures2D = StreamingAssetsImageLoader.LoadTextures2dFromFolder();
  List<Texture2D> texture2dList = StreamingAssetsImageLoader.LoadTextures2dFromFolder("Gallery/Projects", SearchOption.TopDirectoryOnly);
  • LoadSpritesFromFolder:
  List<Sprite> allSprites = StreamingAssetsImageLoader.LoadSpritesFromFolder();
  List<Sprite> spriteList = StreamingAssetsImageLoader.LoadSpritesFromFolder("Gallery", SearchOption.AllDirectories);

 

Project configuration

Create a folder called "StreamingAssets" anywhere inside the project's "Assets" folder and save any images inside.

 

Compatibility

  • Unity Version: 2019.4 (LTS) or higher
  • Any pipeline (Build-in, URP, HDRP, etc)

 

Image formats:

  • Valid: png • jpg • jpeg
  • Invalid: tga • exr

 

Support

⭐ Star if you like it
❤️️ Follow me for more

using System.Collections.Generic;
using System.IO;
using UnityEngine;
/*
TODO: If we are in WebGL or in android, we must do a WebRequest to get the data.
TODO: Make it Async for the loading.
*/
public static class StreamingAssetsImageLoader
{
const float PIXELS_PER_UNIT = 100f; // By default, 1 unit in Unity means 100 pixels
static readonly Vector2 PIVOT = new Vector2(0.5f, 0.5f); // const wont work on struct like Vector2, so we use static readonly
public static List<Texture2D> LoadTextures2dFromFolder(string relativeFolderPath = "", SearchOption searchOption = SearchOption.AllDirectories)
{
if (relativeFolderPath != "" && !StreamingAssetsPathHelper.IsStreamingAssetsPath(relativeFolderPath))
{
return null;
}
string absoluteFolderPath = Path.Combine(Application.streamingAssetsPath, relativeFolderPath);
List<Texture2D> texture2dList = new List<Texture2D>();
string[] filePaths = Directory.GetFiles(absoluteFolderPath, "*.*", searchOption); // It doesn't detect the folders path
string pathExtension;
string relativeFilePath;
// Get and convert the image files
foreach (string filePath in filePaths)
{
pathExtension = Path.GetExtension(filePath);
if (StreamingAssetsPathHelper.IsImageExtension(pathExtension))
{
relativeFilePath = filePath.Replace(Application.streamingAssetsPath, ""); // Convert to relative path
relativeFilePath = relativeFilePath.Remove(0, 1); // Remove the root
texture2dList.Add(LoadTexture2dFromPath(relativeFilePath));
}
}
return texture2dList;
}
public static Texture2D LoadTexture2dFromPath(string relativeFolderPath)
{
if (!StreamingAssetsPathHelper.IsStreamingAssetsPath(relativeFolderPath))
{
return null;
}
string absoluteFolderPath = Path.Combine(Application.streamingAssetsPath, relativeFolderPath);
//Converts desired path into byte array
byte[] pngBytes = File.ReadAllBytes(absoluteFolderPath);
//Creates texture and loads byte array data to create image
Texture2D texture2D = new Texture2D(2, 2);
texture2D.LoadImage(pngBytes);
texture2D.name = Path.GetFileNameWithoutExtension(absoluteFolderPath);
return texture2D;
}
public static Sprite LoadSpriteFromPath(string relativeFolderPath)
{
Texture2D texture2d = LoadTexture2dFromPath(relativeFolderPath);
return ConvertTexture2dToSprite(texture2d, PIVOT, PIXELS_PER_UNIT);
}
public static List<Sprite> LoadSpritesFromFolder(string relativeFolderPath = "", SearchOption searchOption = SearchOption.AllDirectories)
{
List<Texture2D> texture2dList = LoadTextures2dFromFolder(relativeFolderPath, searchOption);
List<Sprite> spriteList = new List<Sprite>();
foreach (Texture2D texture2d in texture2dList)
{
spriteList.Add(ConvertTexture2dToSprite(texture2d, PIVOT, PIXELS_PER_UNIT));
}
return spriteList;
}
private static Sprite ConvertTexture2dToSprite(Texture2D texture2D, Vector2 pivot, float pixelsPerUnit = 100f)
{
if (texture2D == null)
{
return null;
};
Sprite fromTex = Sprite.Create(texture2D, new Rect(0.0f, 0.0f, texture2D.width, texture2D.height), pivot, pixelsPerUnit);
fromTex.name = texture2D.name;
return fromTex;
}
}
using System;
using System.IO;
using UnityEngine;
public static class StreamingAssetsPathHelper
{
static readonly string[] IMAGE_EXTENSIONS = { ".png", ".jpg", ".jpeg" }; //".exr" and ".tga" not working
public static bool IsImageExtension(string extension)
{
if (extension.ToLower() == ".meta") // We hate Facebook :)
{
return false;
}
foreach (string imgExtension in IMAGE_EXTENSIONS)
{
if (extension.ToLower() == imgExtension.ToLower()) //Lowercase to evade errors
{
return true;
}
}
return false;
}
public static bool IsValidRelativePath(string relativePath)
{
if (string.IsNullOrEmpty(relativePath))
{
Debug.LogWarning($"Null or empty path.");
return false;
}
// Check for invalid path characters
try
{
if (0 <= relativePath.IndexOfAny(Path.GetInvalidPathChars()))
{
Debug.LogWarning($"Invalid path characters: <i>{relativePath}</i>");
return false;
}
}
catch (ArgumentException)
{
Debug.LogWarning($"Illegal path: <i>{relativePath}</i>");
return false;
}
// Check if the path is rooted. That means that start with "\", "/", "C:" or "C:/"
if (Path.IsPathRooted(relativePath))
{
Debug.LogWarning($"The path is rooted: <i>{relativePath}</i>\nIt must NOT start with <b>\"\\\", \"/\", \"C:\" or \"C:/\"</b>");
return false;
}
return true;
}
public static bool IsValidAbsolutePath(string absolutePath)
{
if (string.IsNullOrEmpty(absolutePath))
{
Debug.LogWarning($"Null or empty path.");
return false;
}
// Check for invalid path characters
try
{
if (0 <= absolutePath.IndexOfAny(Path.GetInvalidPathChars()))
{
Debug.LogWarning($"Invalid path characters: <i>{absolutePath}</i>");
return false;
}
}
catch (ArgumentException)
{
Debug.LogWarning($"Illegal path: <i>{absolutePath}</i>");
return false;
}
// Check if the path is rooted. That means that start with "\", "/", "C:" or "C:/"
if (!Path.IsPathRooted(absolutePath))
{
Debug.LogWarning($"The path is not rooted: <i>{absolutePath}</i>\nIt must start with <b>\"\\\", \"/\", \"C:\" or \"C:/\"</b>");
return false;
}
return true;
}
public static bool IsStreamingAssetsPath(string relativeFolderPath)
{
if (IsValidRelativePath(relativeFolderPath))
{
string absoluteFolderPath = Path.Combine(Application.streamingAssetsPath, relativeFolderPath);
if (Directory.Exists(absoluteFolderPath) || File.Exists(absoluteFolderPath))
{
return true;
}
else
{
Debug.LogWarning($"StreamingAssets doesn't contain the path: <i>{relativeFolderPath}</i>");
return false;
}
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment