Core Sorting Algorithms and Lua Patterns for Unity Engineers
Bubble Sort Implementation
This algorithm iterates through the dataset multiple times, swapping adjacent elements if they are in the wrong order. An optimization flag is included to terminate early if the list becomes sorted before all passes complete.
public static void ExecuteBubbleSortion(int[] data)
{
bool didSwap;
for (int pass = 0; pass < data.Length - 1; pass++)
{
didSwap = false;
for (int idx = 0; idx < data.Length - pass - 1; idx++)
{
if (data[idx] > data[idx + 1])
{
int cache = data[idx];
data[idx] = data[idx + 1];
data[idx + 1] = cache;
didSwap = true;
}
}
if (!didSwap) return;
}
}
Insertion Sort Logic
Builds the final sorted array one item at a time. It assumes the first element is sorted and inserts subsequent elements into their correct position within the sorted portion.
public static void PerformInsertion(int[] sequence)
{
for (int current = 1; current < sequence.Length; current++)
{
int key = sequence[current];
int position = current - 1;
while (position >= 0 && sequence[position] > key)
{
sequence[position + 1] = sequence[position];
position--;
}
sequence[position + 1] = key;
}
}
Shell Sort Algorithm
An optimization of insertion sort that allows the exchange of items that are far apart. The gap sequence reduces over time until it becomes 1.
public static void ShellSortAlgorithm(int[] dataset)
{
for (int gap = dataset.Length / 2; gap > 0; gap /= 2)
{
for (int i = gap; i < dataset.Length; i++)
{
int tempValue = dataset[i];
int j = i;
while (j >= gap && dataset[j - gap] > tempValue)
{
dataset[j] = dataset[j - gap];
j -= gap;
}
dataset[j] = tempValue;
}
}
}
Merge Sort Strategy
Uses a divide-and-conquer approach. The array is recursively split into halves until single elements remain, then merged back together in sorted order.
public static int[] DivideAndConquer(int[] input)
{
if (input.Length <= 1) return input;
int mid = input.Length / 2;
int[] leftSide = new int[mid];
int[] rightSide = new int[input.Length - mid];
Array.Copy(input, 0, leftSide, 0, mid);
Array.Copy(input, mid, rightSide, 0, input.Length - mid);
return CombineSegments(DivideAndConquer(leftSide), DivideAndConquer(rightSide));
}
private static int[] CombineSegments(int[] left, int[] right)
{
int[] result = new int[left.Length + right.Length];
int lPtr = 0, rPtr = 0, resPtr = 0;
while (lPtr < left.Length && rPtr < right.Length)
{
if (left[lPtr] <= right[rPtr])
result[resPtr++] = left[lPtr++];
else
result[resPtr++] = right[rPtr++];
}
while (lPtr < left.Length) result[resPtr++] = left[lPtr++];
while (rPtr < right.Length) result[resPtr++] = right[rPtr++];
return result;
}
Quick Sort Partitioning
Selects a pivot element and partitions the array into two sub-arrays, according to whether they are less than or greater than the pivot. Uses swapping logic instead of hole filling.
public static void PartitionSort(int[] nums, int low, int high)
{
if (low < high)
{
int pivotIndex = GetPivotIndex(nums, low, high);
PartitionSort(nums, low, pivotIndex - 1);
PartitionSort(nums, pivotIndex + 1, high);
}
}
private static int GetPivotIndex(int[] nums, int low, int high)
{
int pivot = nums[high];
int i = low - 1;
for (int j = low; j < high; j++)
{
if (nums[j] <= pivot)
{
i++;
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
int swap = nums[i + 1];
nums[i + 1] = nums[high];
nums[high] = swap;
return i + 1;
}
Heap Sort Structure
Converts the array into a max heap, then repeatedly extracts the maximum element and rebuilds the heap.
public static void HeapSortProcedure(int[] arr)
{
int size = arr.Length;
for (int i = size / 2 - 1; i >= 0; i--)
SiftDown(arr, size, i);
for (int i = size - 1; i > 0; i--)
{
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
SiftDown(arr, i, 0);
}
}
private static void SiftDown(int[] arr, int size, int root)
{
int largest = root;
int leftChild = 2 * root + 1;
int rightChild = 2 * root + 2;
if (leftChild < size && arr[leftChild] > arr[largest])
largest = leftChild;
if (rightChild < size && arr[rightChild] > arr[largest])
largest = rightChild;
if (largest != root)
{
int swap = arr[root];
arr[root] = arr[largest];
arr[largest] = swap;
SiftDown(arr, size, largest);
}
}
Lua Deep Table Cloning
Recursively copies table contents including nested tables and preserves metatables.
function CloneTable(original)
if type(original) ~= 'table' then
return original
end
local copy = {}
for key, value in pairs(original) do
copy[CloneTable(key)] = CloneTable(value)
end
setmetatable(copy, getmetatable(original))
return copy
end
local sourceData = {1, 2, {3, 4}, name = "Test"}
local clonedData = CloneTable(sourceData)
Lua Object-Oriented Pattern
Implements class-like behavior using metatables and the __index metamethod for inheritance and method resolution.
Character = { name = "Unknown", level = 1 }
Character.__index = Character
function Character:Create(newName, newLevel)
local instance = setmetatable({}, Character)
instance.name = newName or "Unknown"
instance.level = newLevel or 1
return instance
end
function Character:DisplayInfo()
print(self.name .. " - Level " .. self.level)
end
local hero = Character:Create("Arthur", 5)
hero:DisplayInfo()
-- Overriding method
function hero:DisplayInfo()
print("Hero: " .. self.name .. " (Lvl " .. self.level .. ")")
end
hero:DisplayInfo()