UAssetAPI
Please note that this may be quite complicated for those new to C# or programming in general as this is object oriented programming
-
UassetAPI is a C# API made by atenfyr that allows extensive editing of unreal engine 4 assets
-
The main advantage of this API over UAssetGUI is that with a little C# experience, very impressive edits can be made to .umaps and .uassets very quickly
-
This will be mostly done through iteration
-
First download the UassetAPI source code using github desktop or as a .zip file
-
Then open the .sln in visual studio(Make sure dotnet 4.7.2 SDK and compiler are installed for visual studio) and build UassetAPI
-
This will generate some .dlls in UassetAPI's debug folder which we can reference in our visual studio project
-
Set up a visual studio project from a template (for applications I use a winforms template and for general .uasset editing I use the command line interface)
-
This will generate a simple template in dotnet 4.7.2 that can be used with UassetAPI (if you want to add source control I recommend the github extension by github and then you can add source control from the file dropdown)
-
reference the generated .dlls from the project dropdown and you're ready to start
-
The basic setup you'll want to start in the namespace with will be something like
using System;
using System.Collections.Generic;
using System.Linq;
using UAssetAPI;
namespace WhateverYouCalledYourProject
{
class Program
{
static void Main(string[] args)
{
static public void RandTransform(string filepath, string endpath)//I make this a function so it's callable for multiple uassets
{
Uasset y=new Uasset(filepath,UE4Version./*Put the corresponding version-intellisense will give you some suggestions*/)
MessageBox.Show($"Data preserved:{(y.VerifyBinaryEquality() ? "yes" : "no")}");
//checks if data has been parsed properly. If it has not then report it to atenfyr using his issue templates here:
//https://github.com/atenfyr/UAssetAPI/issues/new?assignees=&labels=&template=bug_report.md&title=
//for loop loops through exports(alternatively use a foreach loop)
for (int i = 0; i < y.Exports.Count; i++)
{
Export export=y.Exports[i];
if (export is NormalExport ex)
{
//loop through subcategories to find whatever you're looking for
for (int j = 0; j < ex.Data.Count; j++)
{
//do whatever you want to the subcategories
}
}
}
y.Write(endpath); //remember to do this otherwise your edits will not be saved
}
}
}
}
You can do checks for certain exports using if statements
e.g if(ex.Data[j].Name.Equals(FName.FromString("Item")) && ex.Data[j] is BytePropertyData byt){}
And then do things to the the export byt in this example like
byt.Value = y.AddNameReference(FString.FromString(Items[19]));
Using this method you can loop through multiple files very quickly to make edits that would have taken ages to do manually with UassetGUI
Below I will include some code snippets for editing common PropertyData types:
Enums
static public void Enums(string filepath, string endpath, int indexes)//I state the number of indexes because sometimes eh.Count causes an index out of range error
{
//Load enum
UAsset y = new UAsset(filepath, UE4Version.VER_UE4_25);
//Only one export so for loop isn't needed
Export baseUs = y.Exports[0];
if (baseUs is EnumExport us)
{
List<Tuple<FName, long>> eh = us.Enum.Names;
for (int j = 0; j < indexes; j++)
{
eh[j] = new Tuple<FName, long>(us.Enum.Names[j].Item1, 2/*Enum index you wish to use*/);
}
}
y.Write(endpath);
}
Location
static public void RandTransform(string filepath, string endpath)
{
UAsset y = new UAsset(filepath, UE4Version.VER_UE4_25);
for (int i = 0; i < y.Exports.Count; i++)
{
if (y.Exports[i] is NormalExport us)
{
for (int j = 0; j < us.Data.Count; j++)
{
if (us.Data[j].Name.Equals(FName.FromString("RootComponent")) && us.Data[j] is ObjectPropertyData ob)
{
//MessageBox.Show(y.Exports[Convert.ToInt32(ob.Value.ToString())].ObjectName.ToString());
if (y.Exports[Convert.ToInt32(ob.Value.ToString())] is NormalExport egg)
{
foreach (var data in egg.Data)
{
if (data.Name.Equals(FName.FromString("RelativeLocation")) && data is StructPropertyData loc)
{
loc.Value = new List<PropertyData>
{
new VectorPropertyData(FName.FromString("Vector"))
{
Value= new FVector(50,50,50)
}
};
}
}
}
}
}
}
}
y.Write(endpath);
}
For rotators replace:
if (data.Name.Equals(FName.FromString("RelativeLocation")) && data is StructPropertyData loc)
{
loc.Value = new List<PropertyData>
{
new RotatorPropertyData(FName.FromString("Vector"))
{
Value= new FVector(50,50,50)
}
};
}
with this:
if (data.Name.Equals(FName.FromString("RelativeRotation")) && data is StructPropertyData rot)
{
rot.Value = new List<PropertyData>
{
new RotatorPropertyData(FName.FromString("Rotator"))
{
Value= new FRotator(50,50,50)
}
};
}