Guidelines for Programming for Blueprints

There are two driving considerations when deciding to use C++ or Blueprints:

Speed

Complexity of expression

Beyond those two factors, a lot of it comes down to the complexity of the game, and the composition of the team. If you have many more artists than programmers, you'll probably have significantly
more Blueprints than C++ code. In contrast, if you have a lot of programmers, they're probably keen to keep things in C++. We expect people to fall somewhere in the middle. At Epic,
a lot of the workflow is that content creators will make a very complex Blueprint, and a programmer can see how he can compress a lot of that work into C++ by coding a new Blueprint node,
so he moves that chunk of functionality into a new C++ function. A good practice to follow would be to use Blueprints extensively, and then push things into C++ as they reach a complexity
where that would enable a more concise expression of the functionality (or it becomes too complex for a non-programmer), or speed of execution dictates a move to C++.

Speed

For speed, the fact is that Blueprint execution is slower than C++ execution. That's not to say performance is bad, but if you're doing something that requires a lot of calculations, or operates
at a high frequency, it might be better to use C++ instead of Blueprints. However, it is possible to combine the two in the way that works best for your team and your project's performance.
If you have a Blueprint that has a lot of functionality, you can push some of that functionality into C++ to speed it up, but keep the rest in Blueprints to retain the flexibility.If your profiling shows that one operation is taking a lot of time in Blueprints, consider moving just that section into C++, while keeping the rest in Blueprints.

An example of a system that would take a lot of time to execute if done with Blueprints visual scripting is a crowd system that controls a thousand Actors In this case, it would be better for performance
to handle decision making, pathing, and other crowd functionality in C++, and then maybe expose some tweaking parameters and controlling functions to Blueprints.

Complexity

For complexity of expression, there are just some things that are easier to do in C++ than in Blueprints. Blueprints do a lot of things well, but some things are just not very
easy to express in nodes. Operating on large sets of data, doing string manipulation, complex math over large data sets, etc. are all very complex, and aren't easy to follow in a visual system.
Those things are better kept in C++ than in Blueprints, just because they're easier to look at and figure out what's going on. Complexity of expression is another reason a crowd system would
be better to implement in C++ code than in Blueprints.

Examples

Since there are different pieces of functionality that are best handled in C++ or in Blueprints, here are some examples of how C++ programmers and Blueprint authors can work
together while creating a game.

The programmer could create a Character class in C++ that defines some custom events, and then Blueprints could be used to extend that Character class and actually assign meshes and set defaults.
Check out the player character and the enemy bots in the ShooterGame sample project to see implementations like this.

A ability system where the base class is implemented in C++ but then designers can create Blueprints which actually do something. In the StrategyGame sample, there is a base turret defined in C++,
but the behavior of the flamethrower, cannon, and arrow turrets is all defined in those Blueprints.

A pickup where the "Collect" or "Respawn" functions are Blueprint Implementable Events that can be overridden for designers to spawn different particle emitters and sound effects. Both ShooterGame and
StrategyGame have examples of pickups created this way.

Creating a Blueprint API : Tips and Tricks

Here are some points to consider as a programmer creating a Blueprint-exposed API:

Optional parameters are handled well in Blueprints:

/**
* Prints a string to the log, and optionally, to the screen
* If Print To Log is true, it will be visible in the Output Log window. Otherwise it will be logged only as 'Verbose', so it generally won't show up.
*
* @param InString The string to log out
* @param bPrintToScreen Whether or not to print the output to the screen
* @param bPrintToLog Whether or not to print the output to the log
* @param bPrintToConsole Whether or not to print the output to the console
* @param TextColor Whether or not to print the output to the console
*/
UFUNCTION(BlueprintCallable, meta=(WorldContext="WorldContextObject", CallableWithoutWorldContext, Keywords = "log print", AdvancedDisplay = "2"), Category="Utilities|String")
static void PrintString(UObject* WorldContextObject, const FString& InString = FString(TEXT("Hello")), bool bPrintToScreen = true, bool bPrintToLog = true, FLinearColor TextColor = FLinearColor(0.0,0.66,1.0));

Favor functions with lots of return parameters over functions that return structs. Here's a snippet showing how to create multiple output pins on your node:

Adding new parameters to an existing function is fine, but if you need to remove or change them, you should deprecate the original and add a new function. Make sure to use the deprecation metadata so the information about the new function will show up in Blueprints: