[4.7.6] - Not sure if bug but FindFunction fails in Standalone

Hey Guys,

I am having an issue. I was pretty excited how to learn about UE4’s version of function pointers in C++ to help me get access to BP’s in the Editor. I got it working great in the editor but in Standalone it fails to find the function returning a nullptr for the UFunction pointer.

Here is my snippet of code…

struct FMiniMap_Register_Parameters
		{
			FName Name;
			EMiniMapUnitType Type;
			UTexture2D* Texture;
			FLinearColor Color;
			float StartX;
			float StartY;

			UUserWidget* Result;
		};

		static FMiniMap_Register_Parameters FunctionParameters;
		FunctionParameters.Name = FName(*Unit->GetName());
		FunctionParameters.Type = UnitInterface->Execute_GetUnitType(Unit);
		FunctionParameters.Texture = UnitInterface->Execute_GetUnitIcon(Unit);
		FunctionParameters.Color = UnitInterface->Execute_GetUnitColor(Unit);
		FunctionParameters.StartX = 0.f;
		FunctionParameters.StartY = 0.f;

		UFunction* RegisterUnitFunction = MiniMap->FindFunction(TEXT("Register Unit"));
		MiniMap->ProcessEvent(RegisterUnitFunction, &FunctionParameters);
		
		return FunctionParameters.Result;

The MiniMap is a custom UUserWidget I created in UMG and it is not coming back w/ a nullptr. I did check to see if source control was out of sync but the Widget in BPs does have that function and this does work when running inside the editor.

I was originally running this function from Event Begin Play, where it would iterate over every Player Pawn and call the function that runs the above code. I wondered if it had something to do with the order of operations so I moved that code to the Level’s Tick using a DoOnce at the beginning and that also failed.

Let me know what you think why the UFunction may not be able to be found outside of the editor. Is FindFunction only meant to work inside the editor and if so, is there a workaround to get the same effect?

Thanks again and have a great day!

EDIT: Now I’m noticing it failing as well in the editor. Hang tight, this might be my issue.
EDIT #2: Still an issue. I checked and for some reason I needed to change a line of code to make the code re-compile again (The editor was holding onto something that needed to be recompiled from yesterday). Once I did this, it now works again in editor but is still failing to find the function in an external staging build in standalone.

Thanks!

Hey -

I’m not sure I fully understand what is happening. Can you explain exactly what effect you’re trying to get by using FindFunction()? Additionally if you could provide a small sample project with the problem you’re encountering it will help me understand what is going on.

Cheers

Absolutely .

Okay, so I have a UMG Widget that represents a MiniMap and I have a couple of functions I want to call on it to lets say register a unit on the map, update it or unregister it.

I’m using the FindFunction… function :slight_smile: to basically find that method and call it without having a base class or interface to get the function directly.

Here is a section of code I am using it in…

IMiniMapUnitInterface* UnitInterface = Cast<IMiniMapUnitInterface>(Unit);
	if (UGameExtensions::IsValid(MiniMap) && UGameExtensions::IsValid(Unit) && UGameExtensions::IsValid(UnitInterface))
	{
		struct FMiniMap_Register_Parameters
		{
			FName Name;
			EMiniMapUnitType Type;
			UTexture2D* Texture;
			FLinearColor Color;
			float StartX;
			float StartY;

			UUserWidget* Result;
		};

		static FMiniMap_Register_Parameters FunctionParameters;
		FunctionParameters.Name = FName(*Unit->GetName());
		FunctionParameters.Type = UnitInterface->Execute_GetUnitType(Unit);
		FunctionParameters.Texture = UnitInterface->Execute_GetUnitIcon(Unit);
		FunctionParameters.Color = UnitInterface->Execute_GetUnitColor(Unit);
		FunctionParameters.StartX = 0.f;
		FunctionParameters.StartY = 0.f;

		UFunction* RegisterUnitFunction = MiniMap->FindFunction(TEXT("Register Unit"));
		if (UGameExtensions::IsValid(RegisterUnitFunction))
		{
			MiniMap->ProcessEvent(RegisterUnitFunction, &FunctionParameters);
			return FunctionParameters.Result;
		}
	}

What I am noticing is when I run the Game from the editor, it finds it flawlessly. However, when I run an external staging build, it is unable to find the function.

Are there specifics w/ how this functions in regards to the editor compared to standalone process builds?

Thanks again for the help and looking forward to your response. Take care.

Hey -

There may be an issue with *Unit->GetName() coming back with nothing. Can you run through a debugger and let me know what this line is returning in a standalone game?

Absolutely! Sorry about the delay. Was on vacation and at E3 last week. I’ll try this shortly and get right back to you with an update. Thanks!

Okay , just tested things.

In the editor, both are found as expected. However in Standalone (running from VS as DebugGame), calling GetName from the Unit did work and return the hero pawn in question but couldn’t find the function and came back null.

I was hoping it wouldn’t work as you suggested since it sounded like you had an inclination on what it might be but in Standalone, the name came back but function didn’t. Let me know what you want me to evaluate next and hope you had a great week !

Hey -

After speaking with a developer I found that FindFunction is only usable inside the editor which is why it’s failing in Standalone. If I understand correctly you’re trying to use FindFunction() to have the minimap draw different units onto it. If that’s the case this can be done in a couple other ways. If the “Draw” function is part of the minimap widget then each unit can call that function and tell the minimap to draw it (the unit) when the unit needs to be drawn onto (or removed from) the minimap. The other solution would be to include an interface on the unit (as you mentioned previously), then the minimap can check if the unit has that interface and react accordingly. Let me know if this doesn’t hep or if I’m misinterpreting what you’re trying to accomplish.

Cheers

Hey ,

Thanks for the quick response and I really appreciate you looking into this ! :slight_smile:

That’s a bummer it only is meant to work in the editor. A feature like this outside of the editor would be a major benefit and did the developer mention what would be entailed to get it to work outside or is it not possible?

The only problem w/ solution 1 is I’m trying to call these functions from code so unless I had a BP that was based off of that class, my code won’t be able to know about the Widget Type and make the call. I can get around this of course by simply moving this functionality to the BP instead of code in this case but if certain functionality needs to exist in C++ (maybe in a future case to run faster), then I’d only be able to do this by calling an event or function at the end of that which could then be overridden in the BP. This could make things messy but might not be that bad.

For option 2, wouldn’t the interface on the unit only work if the overridden functions in the BP directly called the Widget? I might have meant an interface on the Widget.

To probably get around this the best I can and be able to allow me to keep everything in C++ if needed, I’ll likely just create a C++ Interface (or base UUserWidget class) that the Widget can inherit and I can cast it to that interface to get what I need. Do you think this is the best route if I want to call the functions in question from C++?

Also, if you do get a chance to see if the FindFunction could be adapted for Standalone, or if that would be too hard to implement, I’d be really curious to see if it might be possible since it’s so handy (reliable function pointers to BP based UE types would rock!) :slight_smile:

Thanks again !

EDIT: Oh, I understand what you meant now by solution 2 after looking at my code above I posted. I have a feeling that may not work based off of how I set this up but let me give you a rundown of what I have currently just in case.

The first thing that happens is when a Pawn is created on the Map, it looks for a BP in the level called a ‘MiniMapRegion’. It’s an instance of a BP that myself or a level designer could place in the level to determine the playable space and also cross reference a given units position based on where they lie inside of a volume (that is part of the BP). It then will update the Mini-Map region accordingly.

After the pawn is created, it calls a function on the MiniMapRegion (if one is found in the level) called Register. Once it does this, the Mini-Map then (after already finding the current Widget instance of the Mini-Map and storing its reference during BeginPlay(…)), calls into that reference to the Widget to register it on the actual Mini-Map. When it registers it, it creates a custom Widget that represents the unit and stores it’s data.

During Tick, the Pawn calls an Update function on the Mini-Map Region which passes on the Pawn (or unit) reference and outputs a normalized 0-1 of where they lie and then passes that + the other unit data to the Mini-Map Widget to update.

I use a structure to store the important UnitInfo bits such as Color, NormalizedLocation, UnitName so that when I pass a Pawn into those update functions, it will cross-reference the name of that Pawn w/ all the registered MiniMapUnits (custom widget representing moving icon, alerts, POI, etc) in the MiniMap.

That’s the flow I’m currently using so I think if I set it up so that I have those Anonymous Blueprints I’m calling into from C++ inherit a interface w/ functions for Register, Unregister and Update. That’d work perfectly.

But if you do get some Epic Dev input about making FindFunction work in Standalone, definitely let me know.

Thanks again !

Hey ! I guess if you get any info on that, feel free to post it here if that might be possible in the future.

Check this out though…

When dealing with another issue to get around this one (link in case you may be able to help: [4.8.0] - Cannot Cast UMG Widget To C++ Interface - UI - Epic Developer Community Forums), I found that in the engine code, interfaces are able to use the ‘ProcessEvent’ function.

If FindFunction isn’t available but ProcessEvent is, since an interface (in the generated code) is able to re-map to the functions in the class, wouldn’t it be possible to still make anonymous function calls and find the memory address to the function in question another way? Maybe by getting back all UFunctions in a UClass and maybe they’d have an FName I could cross-reference?

Just a thought