How to Add and Access Custom Data Directly to Unity Sprite at Runtime?

Overview

I’m developing a Unity plugin called TwentyFiveSlicer. This library extends Unity’s standard 9-slice functionality to support 25-slice image slicing in UGUI.

Currently, the plugin works by analyzing the Sprite, generating unique slicing data (vertical and horizontal borders), and storing this information in a JSON file. While functional, this approach feels overly complex and inefficient, especially for projects with many sprites.


Current Implementation

Here’s how the plugin currently handles slicing data:

  1. Saving Data:
  • A hash is generated for each Sprite based on its texture and other properties.
  • This hash is used to create a unique filename.
  • The slicing data (vertical and horizontal borders) is serialized into JSON and saved in a Resources folder.
private void SaveBorders()
{
    if (_targetSprite == null) return;

    var hash = TfsHashGenerator.GenerateUniqueSpriteHash(_targetSprite);
    string directoryPath = $"{Application.dataPath}/Resources/TwentyFiveSliceData";
    string filePath = $"{directoryPath}/{hash}.json";

    if (!System.IO.Directory.Exists(directoryPath))
    {
        System.IO.Directory.CreateDirectory(directoryPath);
    }

    _sliceData = new TwentyFiveSliceData
    {
        verticalBorders = _verticalBorders,
        horizontalBorders = _horizontalBorders
    };

    string data = JsonUtility.ToJson(_sliceData);
    System.IO.File.WriteAllText(filePath, data);
}
  1. Loading Data:
  • At runtime, the same hashing algorithm is applied to locate the JSON file for the target Sprite.
  • The JSON is deserialized to load the slicing data.

The Problem

While this JSON-based approach is functional, it introduces significant inefficiencies:

  1. Hashing Overhead:
  • Each Sprite must be hashed to determine the filename, which adds unnecessary computation during loading.
  1. File I/O Operations:
  • Every Sprite load requires disk access to read the corresponding JSON file.
  1. Workflow Complexity:
  • External JSON files complicate data management, especially for large projects.
  1. Runtime Performance:
  • On first load, all slicing data needs to be regenerated by hashing and file I/O.

What I’ve Tried

  1. Custom JSON and ScriptableObject:
  • The current implementation with JSON files works but is inefficient.
  • Using ScriptableObject was explored but felt cumbersome as it introduced extra assets to manage.
  1. TextureImporter.userData:
  • I attempted to store slicing data in the userData field of the TextureImporter. While this works in the Editor, there’s no clear way to access this data at runtime.
importer.userData = JsonUtility.ToJson(sliceData);
  1. ISpriteEditorDataProvider:
  • Unity’s Sprite Editor Data Provider API seemed promising but is limited to Editor workflows, making it unsuitable for runtime use.

The Goal

I want to store custom slicing data directly on the Sprite itself, making it accessible both at runtime and in the Editor. Ideally, this would work similarly to how the border property functions for 9-slice sprites.


The Question

  • Is there any way to attach and persist custom data directly to Unity’s Sprite objects so that it can be accessed at runtime?
  • If this isn’t directly possible, what would be the most efficient alternative to achieve similar functionality without external JSON files or hashing?