Paradise.BLOB 0.47.0

dotnet add package Paradise.BLOB --version 0.47.0
                    
NuGet\Install-Package Paradise.BLOB -Version 0.47.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Paradise.BLOB" Version="0.47.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Paradise.BLOB" Version="0.47.0" />
                    
Directory.Packages.props
<PackageReference Include="Paradise.BLOB" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Paradise.BLOB --version 0.47.0
                    
#r "nuget: Paradise.BLOB, 0.47.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Paradise.BLOB@0.47.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Paradise.BLOB&version=0.47.0
                    
Install as a Cake Addin
#tool nuget:?package=Paradise.BLOB&version=0.47.0
                    
Install as a Cake Tool

Paradise.BLOB

Paradise.BLOB builds immutable unmanaged data with Unity-style blob primitives in plain .NET. Declare an unmanaged struct; a builder writes contiguous bytes with relative offsets, and a reader exposes the struct over those bytes without parsing or copying.

Used by collision worlds, behavior trees, mesh blobs, skeletons and animation clips.

Install

dotnet add package Paradise.BLOB

Features

  • Build immutable unmanaged roots with ValueBuilder<T> and StructBuilder<T>.
  • Store arrays, strings, pointers, trees, sorted arrays, and dynamically typed payloads — including arrays whose elements themselves hold arrays and strings.
  • Read blobs from one aligned native copy (NativeBlobAssetReference<T>) or over a pinned managed array (ManagedBlobAssetReference<T>).
  • Keep offsets and alignment correct without hand-rolling binary layouts.
  • Supports .NET and NativeAOT without reflection.

Quick start

using Paradise.BLOB;
using System.Text;

public struct DemoBlob
{
    public BlobString<UTF8Encoding> Name;
    public BlobArray<int> Values;
    public BlobPtr<int> MaxValue;
}

var builder = new StructBuilder<DemoBlob>();
builder.SetString(ref builder.Value.Name, "demo");
builder.SetArray(ref builder.Value.Values, new[] { 1, 2, 3 });
builder.SetPointer(ref builder.Value.MaxValue, 3);

byte[] bytes = builder.CreateBlob();               // what you store, ship or hash

using var blob = new NativeBlobAssetReference<DemoBlob>(bytes);   // one aligned copy, no pinning
ref var root = ref blob.Value;

Console.WriteLine(root.Name.ToString());
Console.WriteLine(string.Join(", ", root.Values.ToArray()));
Console.WriteLine(root.MaxValue.Value);

Reading: native or managed

  • NativeBlobAssetReference<T>(ReadOnlySpan<byte>, int alignment = 16) makes one aligned native copy, with no GC pinning. Prefer it at runtime; the input can be a file read or a larger span's slice. Dispose it after upload or use; a finalizer frees undisposed memory.
  • ManagedBlobAssetReference<T>(byte[]) pins a managed array in place and reads through the pin. Use it when the bytes must stay a byte[] you also hand elsewhere. Dispose it, or the array stays pinned.

Both hand back ref T Value — a reference into the blob, not a copy.

Nested layouts: arrays of structs that hold arrays

An element type may itself carry BlobArray<T> and BlobString<TEncoding> fields. Build such an array from one builder per element:

public struct Draw
{
    public uint FirstIndex;
    public uint IndexCount;
    public BlobString<UTF8Encoding> Name;
}

public struct MeshBlob
{
    public uint Magic;
    public uint Version;
    public BlobArray<float> Vertices;
    public BlobArray<Draw> Draws;
}

var mesh = new StructBuilder<MeshBlob>();
mesh.Value.Magic = 0x48534D50;   // "PMSH"
mesh.Value.Version = 1;
mesh.SetArray(ref mesh.Value.Vertices, vertices);
mesh.SetArray(ref mesh.Value.Draws, draws.Select(d =>
{
    var draw = new StructBuilder<Draw>();
    draw.Value.FirstIndex = d.First;
    draw.Value.IndexCount = d.Count;
    draw.SetString(ref draw.Value.Name, d.Name);
    return (IBuilder<Draw>)draw;
}));

Conventions the engine's formats follow

  • Magic and version first. The first two fields of a root are a uint magic and a uint version, so a reader can refuse a foreign or newer blob by name before touching an offset. Check them on the bytes (BitConverter.ToUInt32(bytes)) before constructing a reference.
  • Validate after opening. Before indexing trusted blob memory, check required counts and indices, such as draw ranges and joint indices. Dispose the reference before throwing on invalid data.
  • Deterministic bytes. The same input builds the same bytes, so a blob can live in a source tree beside what it was made from and be fingerprinted by hash.

Read blob headers by reference

BlobArray<T>, BlobString<TEncoding> and BlobPtr<T> hold offsets relative to their own address. Copying a header makes its offset point outside the blob, silently returning wrong data. Avoid these accidental copies:

// WRONG: `in` makes `blob` a readonly reference; calling a non-readonly member on
// blob.Draws forces a defensive COPY of the array header.
static void Check(in MeshBlob blob) { var n = blob.Draws[0].IndexCount; }

// WRONG: a `readonly` member on the struct does the same to every array it touches.
public readonly float FirstVertex => Vertices[0];

// WRONG: passing a BlobString (or BlobArray) by value to a helper.
static string? NameOf(BlobString<UTF8Encoding> name) => name.ToString();

Do this instead:

static void Check(ref MeshBlob blob) { ref var draw = ref blob.Draws[0]; var n = draw.IndexCount; }
public float FirstVertex => Vertices[0];                      // mutable receiver
var name = node.Name.ToString();                               // read in place

Access relative-offset data through a mutable ref; avoid readonly receivers and by-value helpers.

Common builders

  • ArrayBuilder<T> and SetArray(...) for contiguous unmanaged arrays.
  • ArrayBuilderWithItemBuilders<T> and the SetArray(ref field, IEnumerable<IBuilder<T>>) overload for arrays of structs that hold arrays or strings.
  • StringBuilder<TEncoding> and SetString(...) for encoded blob strings.
  • PtrBuilderWithNewValue<T> and SetPointer(...) for blob pointers.
  • TreeBuilder<T> and AnyTreeBuilder for preordered trees with subtree end indices.
  • SortedArrayBuilder<TKey, TValue> for hash-ordered key/value lookup tables.

Notes

  • Blob roots and referenced values must be unmanaged.
  • CreateBlob() returns the raw serialized bytes for storage or transport; CreateNativeBlobAssetReference() and CreateManagedBlobAssetReference() open them directly.
  • Dispose every reference: a native one frees its memory, a managed one unpins its array.
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on Paradise.BLOB:

Package Downloads
Paradise.BT

Pure .NET behavior tree runtime inspired by EntitiesBT.

Paradise.Physics

Stateless collision/physics query library for Paradise Engine: static colliders, raycasts and shape casts with no caches and no hidden state.

Paradise.Assets.Mesh

The Paradise mesh blob: GPU-ready interleaved geometry with draw records as a Paradise.BLOB layout, read at runtime by pinning the bytes the asset pipeline extracted from a GLB. No glTF, no JSON, no images.

Paradise.Animation

Skeletal animation runtime and offline builder in managed code, using ozz-animation's archive format: load an ozz skeleton and clips, sample a clip into local poses and model-space matrices; build, optimize and save the same archives from raw keyframes. No native code.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.47.0 40 9/10/2026
0.46.3 76 9/9/2026
0.46.2 73 9/9/2026
0.46.1 76 9/9/2026
0.46.0 85 9/9/2026
0.45.1 114 9/8/2026
0.45.0 125 9/8/2026
0.44.0 130 9/8/2026
0.42.0 157 9/7/2026
0.41.0 164 9/6/2026
0.40.0 182 9/6/2026
0.39.0 168 9/6/2026
0.38.0 151 9/5/2026
0.37.0 150 9/5/2026
0.36.0 154 9/4/2026
0.35.0 131 9/3/2026
0.34.1 126 9/3/2026
0.34.0 133 9/2/2026
0.33.0 120 9/1/2026
0.32.0 121 9/1/2026
Loading failed