Cooking unreferenced assets

My project generates levels dynamically, so I need to spawn assets from code that are not referenced by any map.
By default such assets are not cooked and cannot be found at runtime.

When I execute RunUAT.bat manually, I can use the option -CookDir=“Somewhere” to cook all assets beneath a specific directory even when they are not referenced, the project then runs correctly.
The editor actually has an option “Directories to Always Cook” under “Project Settings → Game → Packaging”, but adding directories there seems to have no effect at all.
Is the option not for this use case or am I using it wrong? And is there any other way to cook unreferenced assets that I am not aware of? I could probably add a map that references all assets and is not used in the game, but I would really like to avoid this.

For windows the manual build is not a big problem, but I would also like to test my project on Android and have not yet managed to manually build and deploy to an android device.

1 Like

As a followup, I would also like to know if the “Directories to Always Cook” under “Project Settings → Game → Packaging” params are being used during the Editor-cook process as I am unable to force it to cook the contents of the specified directory. The unreferenced (not in any map) assets are never placed in the %Projectname%\WindowsNoEditor content folders.

Thanks

BStbck and b14de; yes, that is the correct thing to use if you need to always cook some content.

BStbck - How are you observing that it has no effect, and what directory are you adding to the list? I forget what format it needed in 4.2, but this interface has been improved for 4.3 and the UI will now ensure the path is correct for your project (it stores them relative to your Content directory now). You also have additional options in 4.3 to stage additional non-uasset files for use in your game.

b14de - The cooked assets will be placed in the pak file for your project. You won’t see them added as individual files unless you also disable “Use Pak File”.

Hi Jamie, thanks for the speedy reply.
Awesome! Looking forward to giving those a go in 4.3!

In my current 4.2.1 build, when cooking and packaging from the Editor the resulting StagedBuild never contains all the SkelitalMeshes contained in the ‘Alway Cook’ directory - Only those referenced directly in a existing blueprint.
My Packaging settings are as follow:

The way I am determining if they exist is by running the game and noting their absence and looking in the J:\Game Projects\Active\Unreal Projects\SHMG\Saved\StagedBuilds folder, which appears to be created when File->Package Project is ran. My knowledge of the Cook and Package process is very limited so please correct me on this.

In addition I went ahead and tried to use the RunUAT.bat with the -CookDir param with no success. My full cmd was

RunUAT BuildCookRun -project="J:\Game Projects\Active\Unreal Projects\SHMG\SHMG".uproject -Build -noP4 -platform=Win64 -clientconfig=Development -serverconfig=Development -cook -maps=AllMaps -compile -stage -archive -CookDir="J:\Game Projects\Active\Unreal Projects\SHMG\Content\Character\PartsTest" -archivedirectory="J:\Game Projects\Active\Unreal Projects\SHMG\UATBuilds"

Right, that should work since it’s an absolute path (but it makes your project non-portable, which is why in 4.3 it stores them relative to the Content directory of your project).

I remember fixing a bug in 4.2 where it would fail to enumerate the directories properly because the editor adds quotes around the path when passing them on the command line.

Are you building from source? If so, could you try making the following change to CookCommandlet.cpp:

Inside UCookCommandlet::CollectFilesToCook, after:

DirToCook = DirToCook.Right(DirToCook.Len() - (PlusIdx + 1));

Add:

DirToCook = DirToCook.TrimQuotes();

I had fixed this in 4.2, but the subsequent changes we’d made for staging additional directories rendered my original change obsolete.

Hi Jamie, thanks for that. I’ve made the edit and recompiled (Module.UnrealEd.12_of_21.cpp) however i’m still unable Always Cook the given directory from both editor and RunUAT BuildCookRun command. As this is updated in 4.3 I shall wait for this release and, for now, place all Run-time loaded assets into an unused Cooked map.

Hi Jamie, thanks for the answer.
I just tried again with 4.2.1, but the result is the same. I am doing the same as b14de and just add the absolute paths to “Directories to always cook”. I have added paths to my ‘Blueprints’ folder and to a specific folder under ‘Blueprints’ where I know an asset is ignored.
For testing I disabled ‘Use Pak file’, so I can directly see which assets are cooked. The unreferenced asset is not in the cooked content folder, another asset in the same folder (that is directly referenced) is there.
I am not building from source right now, so I cannot easily test the change to CookCommandlet.cpp you mentioned in your answer to b14de.

I also tried manually calling RunUAT.bat again and it still works. The unreferenced assets are correctly placed in the output folders. The exact line is:

"C:\Program Files\Unreal Engine\4.2\Engine\Build\BatchFiles\RunUAT.bat" BuildCookRun -project=<PATH_TO_PROJECT_FILE>.uproject -CookDir="<PATH_TO_BLUEPRINT_FOLDER>" -noP4 -platform=Win64 -clientconfig=Development -serverconfig=Development -cook -maps=AllMaps -NoCompile -stage -archive -archivedirectory="Output Directory"

Okay, I’ve checked in our Main Perforce branch (and it was a good thing I did since I found some more parsing issues in that code), and the change I gave above won’t have any affect when only a single directory is passed.

Below is the complete (fixed) code that handles parsing that argument, hopefully this will sort you out:

if (Switch.StartsWith(TEXT("COOKDIR=")) == true)
{
	FString DirToCook = Switch.Right(Switch.Len() - 8);
	
	// Allow support for -COOKDIR=Dir1+Dir2+Dir3 as well as -COOKDIR=Dir1 -COOKDIR=Dir2
	for (int32 PlusIdx = DirToCook.Find(TEXT("+")); PlusIdx != INDEX_NONE; PlusIdx = DirToCook.Find(TEXT("+")))
	{
		FString DirName = DirToCook.Left(PlusIdx);
		
		// The dir may be contained within quotes
		DirName = DirName.TrimQuotes();
		FPaths::NormalizeDirectoryName(DirName);
		CmdLineDirEntries.Add(DirName);

		DirToCook = DirToCook.Right(DirToCook.Len() - (PlusIdx + 1));
	}
			
	// The dir may be contained within quotes
	DirToCook = DirToCook.TrimQuotes();
	FPaths::NormalizeDirectoryName(DirToCook);
	CmdLineDirEntries.Add(DirToCook);
}

Hi Jamie, thanks for looking into this further. I gave this a go and at first had no success, both command line and Editor packaging.

For some reason I thought this might be linked to an issue i’m having (reported here) with HTML5 packaging failed due to a space in the directory structure. I went ahead and moved my projects to the root of my J:/ and packaged. It worked and always cooked the given directories

From the log when Packaging from editor, this is the command that fails to Always Cook:
LogInit: Command line: “J:\Game Projects\Active\Unreal Projects\SHMG\SHMG.uproject” -run=Cook -MapIniSection=AllMaps -CookDir=J:/Game Projects/Active/Unreal Projects/SHMG/Content/Character/PartsTest+J:/Game Projects/Active/Unreal Projects/SHMG/Content/Character/SaveThis -TargetPlatform=WindowsNoEditor -buildmachine -Unversioned -fileopenlog -abslog=E:\GitHub\UnrealEngine\Engine\Programs\AutomationTool\Saved\Logs\Cook.txt -stdout -FORCELOGFLUSH -CrashForUAT -unattended -AllowStdOutLogVerbosity

Command that is able to always cook:

LogInit: Command line: J:\SHMG\SHMG.uproject -run=Cook -MapIniSection=AllMaps -CookDir=J:/SHMG/Content/Character/PartsTest+J:/SHMG/Content/Character/SaveThis -TargetPlatform=WindowsNoEditor -buildmachine -Unversioned -fileopenlog -abslog=E:\GitHub\UnrealEngine\Engine\Programs\AutomationTool\Saved\Logs\Cook.txt -stdout -FORCELOGFLUSH -CrashForUAT -unattended -AllowStdOutLogVerbosity 

Is this a known requirement to have the projects parent-directories free of spaces that I missed? Are others not experiencing this?

The CookDir value(s) should have quotes around them if the directory has spaces.

Try this:
-CookDir=“J:/Game Projects/Active/Unreal Projects/SHMG/Content/Character/PartsTest”+“J:/Game Projects/Active/Unreal Projects/SHMG/Content/Character/SaveThis”

Yup that works :slight_smile: It’s the command generated by the Editor->file->Package that failed to give it quotes in my above post which I believe to be a bug, I pulled the command from its Log, sorry for the confusion.

Pete Replied to my html5 bug report of a similar nature, although the two could be unrelated.

Hmm, if you look in FMainFrameActionCallbacks::PackageProject where it sets up the -cookdir flag, it looks to me like it should be adding quotes.

Regardless, the code in FMainFrameActionCallbacks no longer exists in 4.3, and those directories are read directly from your project INI file instead :slight_smile:

Does this still work with PS4 in 4.3 version?
I have a few files that are just loaded on the fly, and no matter what I try it doesn’t include them in the package for the PS4. It mentions the files when I run the command under the “LogCookCommandlet:Display: Loading” section, and finds them if I add print outs in CookCommandlet.cpp when it is iterating through CmdLineDirEntries in CollectFilesToCook where it adds them to FilesInPath, but during the build they never show up under the D:\depot\UE4QA\MyGame\Saved\Cooked\PS4\MyGame\Content\GameUI folder with the other files that are properly being cooked, and don’t show up in the log when it does the “LogCookCommandlet:Display: Cooking” section.

These missing files I am loading up in the game by going:
m_pTexture = LoadObject(NULL, *p_pTexture, NULL, LOAD_None, NULL);

And I am cooking the game by going:
Engine\Build\BatchFiles\RunUAT BuildCookRun -project=MyGame -build -ps4 -cook -map=lvl_1+Main_Menu -stage -package -pak -manifests -cmdline=Main_Menu -clientconfig=Development -CookDir=D:\depot\UE4QA\MyGame\Content\GameUI

Looking at the answers below, it looks like I am doing everything correctly, but when I make a build on the ps4 is crashes because it can’t find these dynamically loaded files since they never get packaged. Is there something I am missing here, or does these commands not work properly for PS4 builds? I managed to fix one issues just by putting one of the UI textures on an off camera box, and figure I could just manually load them with the ConstructorHelpers like the other UI textures that are working, but that doesn’t seem to be the proper way to fix this.

For anyone reading this thread in 2022 - DirectoriesToAlwaysCook does not work properly or rather as you would expect, with the same precedence as DirectoriesToNeverCook. So you cant combine these 2.

The only granular control you have is over map objects for some reason. That, or you have to populate DirectoriesToNeverCook with 9999 entries.