C++ Only Classes with Blueprint annotations being bound to Sk


#1

I wanted to see whether I’m experiencing expected behavior.

I’m running 4.11.1 engine and am also on SK 4.11 source from github.

I’ve noticed that my pure C++ classes don’t show up in the Skookum Browser. If I create a new blueprint that inherits from such a class, it will then show up in the browser but none of my BlueprintReadWrite variables or BlueprintCallable functions can be seen.

Is this the expected behavior? If not, any recommendations where to poke around? I’ve looked a bit at the SkookumScriptGenerator and from what I see, it only seems to scan blueprints. My main goal is to allow calling various C++ functions from SK.


#2

Ok, I think I have some selective amnesia, I’ve received an answer to this question previously.


#3

Ha :slight_smile: If that doesn’t work for you, try this:

  1. Make sure the :sk: plugin is in <your_project_folder>/Plugins not in Engine/Plugins
  2. In Engine\Programs\UnrealHeaderTool\Config\DefaultEngine.ini, add the name of your C++ game module to the list of ScriptSupportedModules
  3. Clean UnrealHeaderTool
  4. Compile your game project

Does this do the trick for you?


#4

For others who are interested, the similar question and answer that is being referencing is probably:


#5

That was the post I was referencing. I think I’m on the right path here. I’m recompiling engine still. I think I hit a snafu the first time, I had ScriptSupportedModules=SpaceGame and UHT just spun for 30 minutes before I killed it. Since I’m building the development editor I think my module name in this case is actually SpaceGameEditor but I’m not certain.

We’ll find out soon. If not, I may need to attach to UHT and see what’s going on.


#6

Ok, so to clear a few things up. SpaceGame is the correct module.

I’m getting stuck in an infinite loop in SkookumScriptGenerator the class in question is ActorComponent.

I’ll continue debugging when I have time.


#7

Hi so first I found that there were some problems with the plugin (probably due to some recent engine changes) that disallowed the SkookumScriptGenerator to export reflection data from game modules. That is fixed, and I uploaded a new version of the plugin, so please re-download the latest plugin.

Also, please make sure that the plugin is placed in your project folder (SpaceGame), and not in the engine folder, as you’ll need to make project-specific modifications to the plugin. Then, in SpaceGame/Plugins/SkookumScript/Source/SkookumScriptRuntime/SkookumScriptRuntime.Build.cs, add your project module name SpaceGame to the list of modules in PrivateDependencyModuleNames.

If you are still having issues let me know!


#8

I pulled down latest 4.11 branch and confirmed that I see your commit. However I am still getting stuck in an infinite loop in the same location, so the symptoms appear to be the same.

To confirm my environment up to this point:

  • UHT DefaultEngine.ini contains +ScriptSupportedModules=SpaceGame
  • The SS plugin exists in my game project’s Plugins folder
  • SpaceGame has been added to the PrivateDependencyModuleNames in SkookumScriptRuntime.cs

Can you recommend a good place to hook into UHT or SkookumScriptGenerator to try and narrow this down to a specific class that might be causing the issue?

–Edit–
I also wanted to add that I did a full clean and rebuild of my project, engine and UHT. I also regenerated my project after building UHT.


#9

I am not 100% sure why this is happening to you. I would try making a debug build of UHT and run it in the VS2015 debugger to step through the code and identify the problem. I don’t think you can make a debug build of UHT in a C++ project generated by Epic Games Launcher though (only via code synced from GitHub). I will send you a debug build of UHT in a PM, and you can attach the debugger to it like you did to the developer build earlier. Maybe you will get more clues that way.


#10

I’m on a github build of the engine, I just don’t yet understand the full interaction between the SS Generator and UHT so my single stepping is taking a bit. I’ll let you know what I find.


#11

Ah ok then you can make a debug build of UHT via the command line. cd to your UE4 root folder, then run

call Engine\Build\BatchFiles\build.bat UnrealHeaderTool Win64 Debug -NoMutex -2015 -PLUGIN "<your_ue4_root_path>\Engine\Plugins\SkookumScript\SkookumScript.uplugin"

You can then set it as the startup project and debug it in VS2015. Needs to have the correct command line of course. You can spy the command line when you build your game. It appears in the Output window where it says Running UnrealHeaderTool <command_line>.

<command_line> would be something like

"<path_to_space_game>\SpaceGame.uproject" "<path_to_space_game>\Intermediate\Build\Win64\MyCppProject9Editor\Debug\UnrealHeaderTool.manifest" -LogCmds="loginit warning, logexit warning, logdatabase error" -Unattended -WarningsAsErrors

You can then set a breakpoint in FSkookumScriptGenerator::FinishExport(), line 299 where it loops forever for you.


#12

Right, sorry I haven’t been very clear here :confused: This is exactly how I’ve been determining that I’m getting stuck in this code.

Here are the last couple lines of output from the generator:

[2016.04.11-16.26.27:693][  0]LogSkookumScriptGenerator: Generating struct RootMotionSource_MoveToForce
[2016.04.11-16.26.27:697][  0]LogSkookumScriptGenerator: Generating struct RootMotionSource_JumpForce
[2016.04.11-16.26.27:700][  0]LogSkookumScriptGenerator: Generating struct ClientReceiveData
[2016.04.11-16.26.27:704][  0]LogSkookumScriptGenerator: Generating struct HierarchicalSimplification
[2016.04.11-16.26.27:707][  0]LogSkookumScriptGenerator: Generating struct AnimInstanceProxy
[2016.04.11-16.26.27:710][  0]LogSkookumScriptGenerator: Generating struct AnimSingleNodeInstanceProxy
[2016.04.11-16.30.54:947][  0]LogSkookumScriptGenerator: Generating class WidgetAnimation
[2016.04.11-16.32.30:014][  0]LogSkookumScriptGenerator: Generating class MovieScene
[2016.04.11-16.32.48:106][  0]LogSkookumScriptGenerator: Generating class MovieSceneTrack
[2016.04.11-16.33.04:287][  0]LogSkookumScriptGenerator: Generating class Entity
[2016.04.11-16.33.15:943][  0]LogSkookumScriptGenerator: Generating class MovieSceneSequence
[2016.04.11-16.33.27:554][  0]LogSkookumScriptGenerator: Generating class Entity
[2016.04.11-16.43.29:551][  0]LogSkookumScriptGenerator: Generating class AIController
[2016.04.11-16.43.31:572][  0]LogSkookumScriptGenerator: Generating struct GameplayResourceSet
[2016.04.11-16.43.32:667][  0]LogSkookumScriptGenerator: Generating class Pawn
[2016.04.11-16.43.35:075][  0]LogSkookumScriptGenerator: Generating class PawnMovementComponent
[2016.04.11-16.43.36:969][  0]LogSkookumScriptGenerator: Generating class ActorComponent
[2016.04.11-16.44.43:306][  0]LogSkookumScriptGenerator: Generating class ActorComponent
[2016.04.11-16.45.16:554][  0]LogSkookumScriptGenerator: Generating class ActorComponent
[2016.04.11-16.45.20:368][  0]LogSkookumScriptGenerator: Generating class ActorComponent
[2016.04.11-16.46.23:102][  0]LogSkookumScriptGenerator: Generating class ActorComponent
[2016.04.11-16.46.23:629][  0]LogSkookumScriptGenerator: Generating class ActorComponent

It’s pretty clear what the high-level cause is from the stack trace below where m_used_classes gets ActorComponent popped only to get re-added in get_skookum_property_type_name:

// "PrerequisiteComponent"
UObjectPropertyBase * object_property_p = Cast<UObjectPropertyBase>(property_p);     

// param evals to "ActorComponent"
m_used_classes.AddUnique(object_property_p->PropertyClass);

Stack Trace:

UnrealHeaderTool-SkookumScriptGenerator.dll!FSkookumScriptGenerator::get_skookum_property_type_name(UProperty * property_p) Line 1529	C++
UnrealHeaderTool-SkookumScriptGenerator.dll!FSkookumScriptGenerator::generate_method_script_file(UFunction * function_p, const FString & script_function_name) Line 755	C++
UnrealHeaderTool-SkookumScriptGenerator.dll!FSkookumScriptGenerator::generate_method(const FString & class_name_cpp, UClass * class_p, UFunction * function_p, const FSkookumScriptGenerator::MethodBinding & binding) Line 732	C++
UnrealHeaderTool-SkookumScriptGenerator.dll!FSkookumScriptGenerator::generate_class_binding_file(UStruct * class_or_struct_p) Line 509	C++
UnrealHeaderTool-SkookumScriptGenerator.dll!FSkookumScriptGenerator::FinishExport() Line 304	C++

It may be more useful to find which source files the ActorComponent originates from, so I’m digging into this next.


#13

Well, wow I finally narrowed this down.

I had to get my workflow down to reproduce this. I’m using the following workflow when I make a change:

  1. Clean UHT
  2. Build UHT
  3. Delete all files in Plugins\SkookumScript\Intermediate\Build\Win64\UE4Editor\Inc\SkookumScriptRuntime
  4. Regen project files
  5. Compile project

I have two functions that when defined will reproduce the infinite loop, the prototypes are:

UFUNCTION(BlueprintCallable, Category = "World")
void SpawnAsteroids(TArray<TSubclassOf<ABaseDamageableActor>>& AsteroidArray, int32 count, float minScale, float maxScale, float spawnRadius, float ZDepth);

UFUNCTION(BlueprintCallable, Category = "World")
void SpawnFluffAsteroids(TArray<TSubclassOf<AActor>>& AsteroidArray, float WorldSize, int32 count, float minScale, float maxScale, float spawnRadius, float ZDepthMin, float ZDepthMax);

ABaseDamageableActor is just an AActor

If I comment these functions out and perform the 5 step process above then UHT completes.


#14

Thanks for your efforts! Will look into this and get back to you shortly.