Solving Plugin dependence on collision channel

I’m writing a custom plugin which requires use of its own trace channels.

Currently the only way I can see to make this work is to require the user to create the trace channels manually within the editor project settings and then a way must be found to communicate to the plugin which ECC_GameTraceChannel enums correspond to the created trace channels.

Clearly this isn’t very friendly since it requires some manual setup from the user to be able to use the plugin. Furthermore it creates an unwanted dependence between the plugin and engine since the engine must communicate back to the plugin which channel enums were used and preferably the engine shouldn’t require knowledge of the plugin for it to work.

Ideally the plugin should be able to find unused trace channel slots and assign them for itself when it is activated thus making it fully automated and removing the need for any back communication from the engine. Does anyone know any way I could go about achieving this?

1 Like

Bump

Is it really not possible to create custom collision channels from a plugin in a flexible way? I’m surprised given how flexible and extendible a lot of the engine is that the collision channels are still handled by a rigid “.ini” file and there’s seemingly no functionality to read and modify this from a plugin. Seems like a pretty poor design choice by the engine programmers if that’s the case.

You can’t call the Windows API WritePrivateProfileString() ?

The collision channels aren’t stored in the registry so no. Besides which, using the windows API to achieve this outside of Unreal would require I write a separate program which the user would have to run to prep the environment for the plugin before installing it which I’d rather not do. Surely there should be a way for the plugin to be able to handle this situation for itself without external user intervention or assistance.

Bump - or is trying to get support for this engine an exercise in futility?

Hi,
you probably could achieve this by checking for existing collision profile during plugin startup in *Engine.ini config file and add one if required, this way it should appear in editor.

Hi BiggestSmile, thank you for the reply.

What I know so far is that when a custom collision channel is created inside the editor it is added to both the ‘Engine.ini’ and the ‘DefaultEngine.ini’ files which it seems is how Unreal keeps track of them. When the editor is started these files are scanned and used to set the custom collision channel names.

I had considered trying to get access to these ini files and modifying them directly like you suggest. Theoretically if my plugin could get access to these files then I could scan them to see whether the channels required by the plugin had yet been added. If they hadn’t then the plugin could write these channels to the ini files in unused slots. There are some issues with this though.

Firstly the plugin would need to be able to modify the ini files before the editor had accessed them itself to populate its collision channels. I doubt that anything I could hook into in the plugin would be called before the editor had already configured itself. Even if the plugin could get there first assuming the plugin was already installed, what happens when the user installs and activates the plugin for the first time since the editor will already be running and have gone through its boot up in that case. In that case some functionality would need to exist to inform the UE4 editor to rescan the ini files and re-populate its collision channels and I don’t know if such a thing exists.

Secondly as far as I could see no functionality is provided by the engine for a plugin to even be able to access and modify the ini files. I’d probably have to write my own ini file loader and parser which seems like a real round the houses way of achieving something that should really be much simpler.

Finally I also image its quite likely that if I did modify the ini files whilst the editor was running, the the editor would simply write over my changes when it saves since it wouldn’t be aware of the the changes I’ve made.

Ideally what I’m after is a way to access and add channels to the editors internal representation of channels when the editor is running so that the change will be immediately reflected within the editor and the editor will take care of adding these new channels to the ini files when it saves. Does anyone have a solution for this since I’m not finding anything myself?

There are various loading phases available, something like PreDefault, PostConfigInit and so on. I’m pretty much sure the PreDefault phase happens right after core system initializations, such as UObject, just make sure to not depend on anything that will load after this.

You should have access to engine functions when you link your plugin against Engine module; config files variables are stored somewhere inside UEngine or inside some of UEngine-derived class, you should have access to it via GEngine variable if i recall correctly.

Regarding the rescan case, many of “out of the box” plugins require editor restart to function properly, nothing bad will happen if your plugin will do the same :slight_smile:

Edit: you can look at loading phases in Source\Runtime\Projects\Public\ModuleDescriptor.h. PostConfigInit seems to suit your needs just fine.

Also take a look at Source\Runtime\Engine\Classes\Engine\CollisionProfile.h. Things might be a little bit easier.

Thanks again for the reply.

It was a while ago now but I already had a good look around the code for what I needed which included Collision Profile. Unfortunately what I wish to do is add a collision channel, not a collision profile. What this comes down to is telling Unreal Editor to associate a name with one of the unused ECC_GameTraceChannel enums and populate the editor with that name. I cant remember where it lives now but I did come across the editor code where the custom channel names are parsed from the ini file and used to populate some internal channel naming representation that the engine keeps. Unfortunately non of that functionality it was using as far as I could see was exposed to plugins or game code since it was either private or not tagged with ENGINE_API.

If you know of some exposed functionality which would allow me to achieve this could you point me to it.

You’ll have to bear with me, I’m trying to get my head back into this problem since I’ve obviously not been twiddling my thumbs for the past two weeks but have been doing other things.

The channel names are parsed from the ini file and stored within each CollisionProfile in a member array called ‘ChannelDisplayNames’. Unfortunately this member is private and not exposed by any functionality for inserting new channel names into it. The only place this member is populated is when the collision profile is loaded from UCollisonProfile::LoadProfileConfig during which custom channel names are pulled from the ini file. This takes me back to the earlier mentioned problem, since I cant add channel names directly in code I’d have to parse the ini file and write the custom channels to it myself before the collision profiles are loaded.

Therefore I guess what I’m asking is, firstly is there really no better more flexible way of adding a custom collision channel than messing with ini files. If not then how would I modify the Engine.ini from code to add a custom channel to it?

I’ve just done some more digging around and it looks like I can pull the collision profiles out of the ini using something like:

I haven’t really dug around in this config code too deeply yet. Can I insert a new line into the collision profile part of the ini and save it from here?

First, learn how to extend the editor adding a Editor Module to your plugin:C++ Extending the Editor | Live Training | Unreal Engine - YouTube
Then use System.IO to add the channels to the .ini files from the Editor module of your plugin so then the runtime module can work. You set the runtime module to not loaded by default while the Editor module is running; when activated the plugin manager window will ask for a restart of the editor. By the the time the editor reboots your ini modificarions should already be there, implemented by the Editor module.

1 Like

Thanks for the reply Bruno.

The good news is that my plugin already extends the editor but that video looks very helpful, I’ll certainly give it a watch when I get the time.

So there really isn’t any way to add a collision channel without having to write my own parser and messing with ini files? As a dedicated physics programmer I’m really feeling the lack of love for physics from the Unreal coders in pretty much everything I’ve encountered so far. Its a shame really because if I were a graphics programmer or an artist I’m sure I’d find UE4 amazing, but from a physics perspective its really very disappointing.

I’m having the exact same problem.
I want my plugin to create custom collision response channels automatically so I’m not forcing users using my plugin to create them manually. So far I have found next to no information on whether this is even possible.

Have there not been any decent alternatives added after all these years?

1 Like

There is not - but in fairness if I imported a plugin into my project and it messed with my collision channel setup I’d be pretty annoyed. There are a limited number of channels available and it’s likely a complex project will be butting up to the limit already.

It’d be much more preferable to have end-users create a collision channel, and tell the plugin what channel that is, rather than have the plugin make assumptions. Just grab the channel from the plugins’ settings when it’s used.

The plugin is for internal company use, and so we have more insight into whether collision channels are already in use, we just want to limit the required amount of setup and required knowledge for each project.

The easiest way IMO is still to just pick a collision channel for the plugin to use, both for code and end users.

Like @Jambax said, the easiest option you have is hard-coding the channels within your plugin. To make it more comfortable for users who may already have created their own channels, i’d recommend moving from back to front, i.e. starting with Channel 18, then Channel 17, etc.

This makes it annoying for your users to set up the channels themselves, but you can use an Editor-only module to handle that bit for you. The code isn’t actually too complex, the simplest way I’ve found is the following:

FString file = FPaths::ProjectConfigDir();
	file.Append(TEXT("DefaultEngine.ini"));

	IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();

	FString FileContent;
	
	if (FileManager.FileExists(*file))
	{
		if(FFileHelper::LoadFileToString(FileContent,*file,FFileHelper::EHashOptions::None))
		{
			
// This is where you add your own content to the file
FileContent.Append("\n[/Script/Engine.CollisionProfile]\n+DefaultChannelResponses=(Channel=ECC_GameTraceChannel18,DefaultResponse=ECR_Block,bTraceType=True,bStaticObject=False,Name=\"YourChannelName\")");

			IPlatformFile& WriteFileManager = FPlatformFileManager::Get().GetPlatformFile();

			if (WriteFileManager.FileExists(*file))
			{
				FFileHelper::SaveStringToFile(FileContent,*file)
			}
		}
	}

The base code is taken from here: File manipulation: Read,Write | Unreal Engine Community Wiki

Like this you can only write to the end of the file, hence the redefinition of [/Script/Engine.CollisionProfile]. This isn’t really a downside in my view, since it lets you create your own little plugin-specific chunk of text, which can be easily removed by users if they stop using the plugin. I’d probably do some more validation to make sure you’re not creating that section multiple times, but this is the best way I’ve found to handle this until we get plugin-specific collision channels.

Hopefully that helps someone out!

Hello! I had this exact issue to solve today and after checking potential solutions I decided to go with what @Jambax suggested.

I’m creating a generic Player Interaction plugin and in my Player Interaction Component I added the Interaction Channel configurable property, which is then used in the Line Trace check.

image

As a default I set the built-in Visibility channel.

UPROPERTY(EditAnywhere, Category = "Interaction")
TEnumAsByte<ECollisionChannel> InteractionChannel = ECollisionChannel::ECC_Visibility;

I agree that plugins shouldn’t modify existing Project Settings.