Crash while recompiling In Editor / BlueprintImplementableEvent

So, I was having some issues recompiling in the editor. The issue was a crash something along the lines of, “Unable to find function ‘None’”. I finally tracked down the cause:

When the editor recompiles the code, it instantiates the UObject derived classes. If one of these classes’ constructor triggers a BlueprintImplementableEvent, it fails to find the function and crashes. Both the index and number of the function FName is 0 in the inl file.

Is there a way to detect this default instantiation and not call something which will cause this issue?

Hi TTaM,

I am going to guess your talking about the CDO (class default object), which we instantiate for every UObject class. You should be able to check IsDefaultSubobject() on the object in question.

However, while I don’t know the specifics of your situation (some code snippets would help clarify), invoking a BlueprintImplementableEvent in a UObject’s constructor can be dangerous. The object isn’t considered fully instantiated at that point (has to serialize in any properties, etc.). You may want to move your setup code into somewhere like PostLoad() or better yet: BeginPlay().

Hopefully I understand your question and gave you the answer you we’re looking for.

Thanks for the reply. The IsDefaultSubobject0 method is exactly the sort of thing I was looking for. Something along the lines of:

if ( !IsDefaultSubobjected() )
{
  // Code that calls BIE
}

My next question is, however, if I create a subobject with NewObject() in either of the methods you suggested, does the object created become “fully instantiated” with all PostLoad and BeginPlay methods for the very next line of code. Let me give you an example:

class UExampleOne
{
  virtual void BeginPlay()
  {
    UObject* blah = NewObject<UExampleTwo>();
    blah->Test();
  }
}

class UExampleTwo
{
  uint8 Value = 0;

  virtual void BeginPlay()
  {
    Value = 1;
  }

  virtual uint8 Test()
  {
    return Value;
  }
}

Does the ExampleOne BeginPlay() method guarantee the blah object Test() method returns 1? If it returns 0, then I cannot use BeginPlay. If the same is true of PostLoad, then that’s unusable as well. I’m currently using the generated constructors because I know that they are called when I create the object, so I don’t have to use some sort of superfluous asynchronous coding.

BeginPlay() really only applies to AActors, and it generally gets called when the “match” has started (or if it’s instantiated after that, then it’s called when it is added to a world where the match is already running).

PostLoad() should work for what you want though (or there are a number of other PostBlah() functions that you can hook into for different stages of the object’s instantiation).

I’ve encountered a problem with PostLoad(). It’s just not called. I recompiled the project in DebugGame Editor, hit f5 with a breakpoint in a PostLoad() method and… it never triggered, despite having the object with the overriden method definitely being instantiated.

virtual void PostLoad() OVERRIDE;

void UMyTestClass::PostLoad()
{
	Super::PostLoad();
	// Break point here
	UE_LOG( LogTemp, Log, TEXT( "Post Load" ) );
}

When instantiating UMyTestClass the breakpoint in this method does not trigger and “Post Load” never appears in the log, either when the editor starts and creates its CDOs or when I do Play In Editor.

Hmmm… PostLoad() should get hit at the very least for the CDO. How about PostInitProperties(), pretty sure that one should be hit everytime you spawn an instance.

Hey Mike. PostInitProperties() works exactly as you mentioned, triggering when you instantiate an object, but before the next operation.

Thanks!

It would be great, though, that if you did call a BIE during default subobject creation, that a warning could be generated, instead of it just silently crashing :slight_smile: