Each time I compile c++ with the editor active, I can no longer save blueprints with blueprintcallable functions that I've made

I get the same error as this: https://answers.unrealengine.com/questions/302157/graph-is-linked-to-private-objects-in-an-external-3.html

When I press cancel on the retry prompt, I get:

EditorErrors:Warning: Warning Can’t save F:/UnrealProjects/4.13/Outpost/Content/Outpost/Core/BP_OutpostGameInstance.uasset: Graph is linked to external private object (unknown culprit) (unknown property ref)

When I copied all nodes and pasted them into a text editor, and searched for “transient” I saw this:

Begin Object Class=K2Node_CallFunction Name="K2Node_CallFunction_1726"
   FunctionReference=(MemberParent=Class'/Script/Outpost.OutpostFunctionLibrary',MemberName="SetSoundClassVolume")
   NodePosX=1024
   NodeGuid=E3777EE340C863C7DA621A8F942FE15D
   CustomProperties Pin (PinId=6ED45D7E4E4574AB7FF9879AB3E96097,PinName="execute",PinToolTip="\nExec",PinType.PinCategory="exec",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.bIsArray=False,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,LinkedTo=(K2Node_FunctionEntry_318 BC8308B644848CA0319CF18BB166E066,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,)
   CustomProperties Pin (PinId=B176B579428ADD6FBB3E4283E82BC3A5,PinName="then",PinToolTip="\nExec",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.bIsArray=False,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,LinkedTo=(K2Node_CallFunction_1727 6ED45D7E4E4574AB7FF9879AB3E96097,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,)
   CustomProperties Pin (PinId=1036CF174AED48EFA61CCD9AFCA59580,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nOutpost Function Library Reference",PinType.PinCategory="object",PinType.PinSubCategoryObject=Class'/Script/Outpost.OutpostFunctionLibrary',PinType.PinSubCategoryMemberReference=(),PinType.bIsArray=False,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,DefaultObject="/Engine/Transient.BPGC_ARCH_FOR_CDO_OutpostFunctionLibrary_21",PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,)
   CustomProperties Pin (PinId=C014826F42393D97A5B293914613325C,PinName="TargetSoundClass",PinToolTip="Target Sound Class\nSound Class Reference",PinType.PinCategory="object",PinType.PinSubCategoryObject=Class'/Script/Engine.SoundClass',PinType.PinSubCategoryMemberReference=(),PinType.bIsArray=False,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,DefaultObject="/Game/Outpost/Audio/SoundClasses/Master.Master",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,)
   CustomProperties Pin (PinId=63269950492EDA3EEF2EFBBFC7B9AB25,PinName="NewVolume",PinToolTip="New Volume\nFloat",PinType.PinCategory="float",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.bIsArray=False,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,DefaultValue="0.0",AutogeneratedDefaultValue="0.0",LinkedTo=(K2Node_CallFunction_1720 8E3D97EA40A8AB3611B3AEBCC4B66774,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,)
End Object

Compare that to the same node before I compiled the c++:

Begin Object Class=K2Node_CallFunction Name="K2Node_CallFunction_1726"
   FunctionReference=(MemberParent=Class'/Script/Outpost.OutpostFunctionLibrary',MemberName="SetSoundClassVolume")
   NodePosX=1024
   NodeGuid=E3777EE340C863C7DA621A8F942FE15D
   CustomProperties Pin (PinId=6ED45D7E4E4574AB7FF9879AB3E96097,PinName="execute",PinToolTip="\nExec",PinType.PinCategory="exec",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.bIsArray=False,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,LinkedTo=(K2Node_FunctionEntry_318 BC8308B644848CA0319CF18BB166E066,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,)
   CustomProperties Pin (PinId=B176B579428ADD6FBB3E4283E82BC3A5,PinName="then",PinToolTip="\nExec",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.bIsArray=False,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,LinkedTo=(K2Node_CallFunction_1727 6ED45D7E4E4574AB7FF9879AB3E96097,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,)
   CustomProperties Pin (PinId=1036CF174AED48EFA61CCD9AFCA59580,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nOutpost Function Library Reference",PinType.PinCategory="object",PinType.PinSubCategoryObject=Class'/Script/Outpost.OutpostFunctionLibrary',PinType.PinSubCategoryMemberReference=(),PinType.bIsArray=False,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,DefaultObject="/Script/Outpost.Default__OutpostFunctionLibrary",PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,)
   CustomProperties Pin (PinId=C014826F42393D97A5B293914613325C,PinName="TargetSoundClass",PinToolTip="Target Sound Class\nSound Class Reference",PinType.PinCategory="object",PinType.PinSubCategoryObject=Class'/Script/Engine.SoundClass',PinType.PinSubCategoryMemberReference=(),PinType.bIsArray=False,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,DefaultObject="/Game/Outpost/Audio/SoundClasses/Master.Master",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,)
   CustomProperties Pin (PinId=63269950492EDA3EEF2EFBBFC7B9AB25,PinName="NewVolume",PinToolTip="New Volume\nFloat",PinType.PinCategory="float",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.bIsArray=False,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,DefaultValue="0.0",AutogeneratedDefaultValue="0.0",LinkedTo=(K2Node_CallFunction_1720 8E3D97EA40A8AB3611B3AEBCC4B66774,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,)
End Object

The formatting makes it hard to see here, but take those two into a text editor in different tabs and flip between the tabs to see the difference. It changes

DefaultObject="/Script/Outpost.Default__OutpostFunctionLibrary"

to

DefaultObject="/Engine/Transient.BPGC_ARCH_FOR_CDO_OutpostFunctionLibrary_21"

This happens for several nodes.
Google gave me no results for what BPGC_ARCH_FOR_CDO is, so that’s why I’m here now. I’m guessing it’s something with Garbage Collecting.

The two options I have at this point is to either restart the editor without saving, in which case those nodes become normal again. Or I can delete them and place them out again, and then I can save the blueprint. The next time I compile the c++ with the editor active, the same thing happens again. Needless to say that this is pretty annoying.

Thankful for any advice!

Hey -

Are you making changes directly to the BlueprintCallable functions before compiling the code? Can you provide the code for the class with the affected functions? Are you able to reproduce this issue by copying the C++ functions into a new class in a new project and have the same issue occur when compiling / saving?

Hi . Had to answer here. The reply didn’t let me for some reason.

No, I didn’t do that when this first occured. I was editing a different class entirely.

I managed to reproduce this in a new project. I created an empty c++ project, created a c++ class from BlueprintFunctionLibrary with the following code:

TestBlueprintLibrary.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Kismet/BlueprintFunctionLibrary.h"
#include "TestBlueprintFunctionLibrary.generated.h"

/**
 * 
 */
UCLASS(BlueprintType, Blueprintable, Config = Game)
class TESTPROJECT_API UTestBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
	
public:

	UFUNCTION(BlueprintCallable, Category = "Outpost|Settings|Sound")
	static void SetSoundClassVolume(USoundClass* TargetSoundClass, float NewVolume);

	UFUNCTION(BlueprintCallable, Category = "Outpost|Settings|Sound")
	static float GetSoundClassVolume(USoundClass* TargetSoundClass);
	
	
};

TestBlueprintLibrary.cpp

// Fill out your copyright notice in the Description page of Project Settings.

#include "TestProject.h"
#include "TestBlueprintFunctionLibrary.h"


void UTestBlueprintFunctionLibrary::SetSoundClassVolume(USoundClass* TargetSoundClass, float NewVolume)
{
	if (TargetSoundClass)
	{
		TargetSoundClass->Properties.Volume = NewVolume;
	}
}

float UTestBlueprintFunctionLibrary::GetSoundClassVolume(USoundClass* TargetSoundClass)
{
	if (TargetSoundClass)
	{
		return TargetSoundClass->Properties.Volume;
	}

	return 0.0f;
}

Then I compiled c++.

Next I created a blueprint from actor called TestActor, and in that I added the GetSoundClassVolume and SetSoundClassVolume nodes after BeginPlay.

Then I changed the GetSoundClassVolume return to 1.0f and recompiled with the editor still open.

After that, I pressed compile in TestActor. No problem. Then save. And I got the same error.

I left a reply in the answers section. The reply box told me I needed to be logged in in order to post a reply (even though I was).

Hey -

Thank you for the detailed reproduction steps. I have reproduced this issue and logged a report for it here Unreal Engine Issues and Bug Tracker (UE-37351) . You can track the report’s status as the issue is reviewed by our development staff.

As a note, I found that the cause of the issue is the functions being declared as static. If you remove this specifier the blueprint will be able to be saved after a hot reload. This will also require you to pass in a blueprint function library variable to the node as the node target becomes a reference to your custom blueprint function library.

Cheers

Hi,
Isn’t the whole point of the BP function library that it has static functions that can be called from everywhere in the project? Removing the “static” isn’t really an option if you’re using them, unless I’m missing something. Right now I can’t use hot reload in any of my projects because of this bug and looking at the issue tracker, it seems I’m the only one that has voted for it haha (Unreal Engine Issues and Bug Tracker (UE-37351))

Yes, you are correct that blueprint function library functions being static is what allows them to easily be used in different parts of the game logic (in code and blueprints). I was simply stating that to get the save error to go away so that the project could be saved, removing static from the function declaration makes this possible.

Ah, okay. :slight_smile: But that’s not really a workaround that you can apply to a real project. Do you know if this issue is being worked on? I mean, right now it’s basically “you can’t use BP function libraries and hot-reload your code”, though both are elemental features I can’t really work without.

Currently our resources are dedicated elsewhere and UE-37351 is not a priority item for us at this time. We don’t have a timeframe for when this may be addressed. If you are using source code, a programmer on your project can implement your own solution, and you are welcome to share that result with Epic for possible integration.