Creating a class that inherits AVolume in a plugin causes the editor to fail to load because it could not load

Creating a class that inherits AVolume in a runtime plugin causes the editor to fail to load because it could not load according to the error message.

Hey MJLaukala`-

Can you elaborate on your plugin setup? Are you using the plugin wizard to create the new plugin? If so, which template are you using? Can you provide the minimal code that reproduces the load issue you’re seeing?

Here is the setup. Took me awhile to figure out what was actually causing it. Had to rush to work. I used this site to create the plugin template Ue4-Web-Plugin-Generator. I haven’t actually tested other actors to see if it was limited to inheriting AVolume. Maybe my setup is wrong or I am missing a dependency. Basically I’m trying to duplicate the ProceduralFoliageVolume.h/.cpp but to use my own RuntimeFoliageComponent.

(Sidenote: If you know any resources or methods of creating foliage instances procedurally at runtime, that’s what I am looking to achieve.)

(P.S. comments wouldn’t allow me to post this.)

.uplugin setup

"Modules" :
[
	{
		"Name" : "RuntimeFoliageComponent",
		"Type" : "Runtime"
	}
]

My Build.cs is setup as

namespace UnrealBuildTool.Rules
{
	public class RuntimeFoliageComponent : ModuleRules
	{
		public RuntimeFoliageComponent(TargetInfo Target)
		{
			PublicIncludePaths.AddRange(
				new string[] {
                    "RuntimeFoliageComponent/Public",
					// ... add public include paths required here ...
				}
				);

			PrivateIncludePaths.AddRange(
				new string[] {
					"RuntimeFoliageComponent/Private",
					// ... add other private include paths required here ...
				}
				);

			PublicDependencyModuleNames.AddRange(
				new string[]
				{
					"Core",
                    "CoreUObject",
                    "Engine",
					// ... add other public dependencies that you statically link with here ...
				}
				);

			PrivateDependencyModuleNames.AddRange(
				new string[]
				{
					// ... add private dependencies that you statically link with here ...
				}
				);

			DynamicallyLoadedModuleNames.AddRange(
				new string[]
				{
					// ... add any modules that your module loads dynamically here ...
				}
				);
		}
	}
}

The module interface

#pragma once

#include "ModuleManager.h"


/**
 * The public interface to this module.  In most cases, this interface is only public to sibling modules 
 * within this plugin.
 */
class IRuntimeFoliageComponentPlugin : public IModuleInterface
{

public:

	/**
	 * Singleton-like access to this module's interface.  This is just for convenience!
	 * Beware of calling this during the shutdown phase, though.  Your module might have been unloaded already.
	 *
	 * @return Returns singleton instance, loading the module on demand if needed
	 */
	static inline IRuntimeFoliageComponentPlugin& Get()
	{
		return FModuleManager::LoadModuleChecked< IRuntimeFoliageComponentPlugin >( "RuntimeFoliageComponentPlugin" );
	}

	/**
	 * Checks to see if this module is loaded and ready.  It is only valid to call Get() if IsAvailable() returns true.
	 *
	 * @return True if the module is loaded and ready to use
	 */
	static inline bool IsAvailable()
	{
		return FModuleManager::Get().IsModuleLoaded( "RuntimeFoliageComponentPlugin" );
	}
};

The class that implements the module interface

#include "RuntimeFoliageComponentPluginPrivatePCH.h"


class FRuntimeFoliageComponentPlugin : public IRuntimeFoliageComponentPlugin
{
	/** IModuleInterface implementation */
	virtual void StartupModule() override;
	virtual void ShutdownModule() override;
};

IMPLEMENT_MODULE( FRuntimeFoliageComponentPlugin, RuntimeFoliageComponent )



void FRuntimeFoliageComponentPlugin::StartupModule()
{
	// This code will execute after your module is loaded into memory (but after global variables are initialized, of course.)
}


void FRuntimeFoliageComponentPlugin::ShutdownModule()
{
	// This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,
	// we call this function before unloading the module.
}

And my class that inherits AVolume

RuntimeFoliageVolume.h

#pragma once

#include "GameFramework/Volume.h"
#include "RuntimeFoliageVolume.generated.h"

//class URuntimeFoliageComponent;

UCLASS()
class RUNTIMEFOLIAGECOMPONENT_API ARuntimeFoliageVolume : public AVolume //This is broke as ■■■■ ■■■■
{
	GENERATED_UCLASS_BODY()

	/*UPROPERTY(Category = RuntimeFoliage, VisibleAnywhere, BlueprintReadOnly)
	URuntimeFoliageComponent* RuntimeComponent;*/
};

RuntimeFoliageVolume.cpp

#include "RuntimeFoliageComponentPluginPrivatePCH.h"
#include "RuntimeFoliageVolume.h"
//#include "RuntimeFoliageComponent.h"


ARuntimeFoliageVolume::ARuntimeFoliageVolume(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
	//RuntimeComponent = ObjectInitializer.CreateDefaultSubobject<URuntimeFoliageComponent>(this, TEXT("RuntimeFoliageComponent"));
	//RuntimeComponent->SetSpawningVolume(this);

	//if (UBrushComponent* MyBrushComponent = GetBrushComponent())
	//{
	//	MyBrushComponent->SetCollisionObjectType(ECC_WorldStatic);
	//	MyBrushComponent->SetCollisionResponseToAllChannels(ECR_Ignore);

	//	// This is important because the volume overlaps with all procedural foliage
	//	// That means during streaming we'll get a huge hitch for UpdateOverlaps
	//	MyBrushComponent->bGenerateOverlapEvents = false;
	//}
}

My reply to your question is posted below. Comment wouldn’t allow me post.

I tried to follow your process, and ensure that my files matched the first four code blocks posted. I then created a new class in the plugin and copied the code of the last two blocks. Doing this, I was able to successfully compile the engine without any errors. What is the full error that is generated on compile? Does the compile succeed if you remove public: AVolume?

It compiles just fine. However, the editor fails to load and crashes out.

97727-capture.png

Assertion failed: GIsHotReload [File:D:\Build++UE4+Release-4.12+Compile\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectBase.cpp] [Line: 564]

Crash Log

Assertion failed: GIsHotReload [File:D:\Build\++UE4+Release-4.12+Compile\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectBase.cpp] [Line: 564] 



UE4Editor_CoreUObject!UObject::ConditionalBeginDestroy() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\coreuobject\private\uobject\obj.cpp:675]
UE4Editor_CoreUObject!StaticExit() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\coreuobject\private\uobject\obj.cpp:3768]
UE4Editor_CoreUObject!TBaseStaticDelegateInstance<void __cdecl(void)>::ExecuteIfSafe() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\public\delegates\delegateinstancesimpl_variadics.inl:1021]
UE4Editor!TBaseMulticastDelegate<void>::Broadcast() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\core\public\delegates\delegatesignatureimpl_variadics.inl:921]
UE4Editor!FEngineLoop::AppPreExit() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\launchengineloop.cpp:3343]
UE4Editor!FEngineLoop::Exit() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\launchengineloop.cpp:2414]
UE4Editor!GuardedMain() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\launch.cpp:159]
UE4Editor!GuardedMainWrapper() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:126]
UE4Editor!WinMain() [d:\build\++ue4+release-4.12+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:200]
UE4Editor!__scrt_common_main_seh() [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:264]
kernel32
ntdll

I’ll play with it some more and see if i can figure out exactly what it is.

You guys really really need to have a clear cut tutorial on plugin creation.

Not really sure what the issue was. I completely removed and recreated my plugin using the UE4 helper and now everything works great.