Around 4.7 if I remember correctly, a new “Interface Call” method was implemented in Blueprint, in addition to the Interface Messages that have been there for a while.
I understand how Interface Messages work and have used them extensively in the project we just shipped. I understand that Call Function on an Interface function just calls that function locally. But I don’t really understand what “Interface Call” is for.
There are several threads talking about Interface Calls vs Messages, however I believe the people answering those threads misunderstood the question as asking about calling interface functions locally (“Call Function”), not about “Interface Call”.
What is Interface Call used for? Why does it take an Interface type variable as its target, and what are Interface type variables used for?
Below is an image about the 3 types of Interface interactions I’m talking about.
This is something that is long overdue some official documentation. Here’s my take.
As far as I can see, the direct call is only available in the case that your blueprint or a parent blueprint had the interface added to it. If instead it derived from a C++ class implementing the interface, you get InterfaceCall and no direct call option. I don’t know why this is, but my guess is that in practice there is no real difference between the two.
InterfaceMessage is different in that you call it on an arbitrary object, not knowing whether the object implements the interface. I imagine it is less performant as a result.
InterfaceType variables are useful in that they provide a safety guarantee - if the variable is not null, then it references some object that definitely implements the interface. So when you need to store or pass around something with that interface (which could be any object type), you can use this rather than passing around a variable of type Object, which you had to do previously. The latter wasn’t ideal since it could potentially be assigned an object which didn’t implement the interface.
I’m not sure, but I would guess there’s probably no longer any need to use InterfaceMessage at all. Anything that should store or operate on an interface should use the interface type for its variable/parameter. You can use the cast node to convert an object to an interface type.
The way I used Interfaces in our last project was to break the direct references between certain Blueprints. For example, our GameInstance blueprint directly referred to the character and some other Blueprints, which meant that the character and a bunch of unnecessary stuff was loaded on boot, which made our PS4 boot times atrocious.
I fixed this by using Interface Messages in places where I still needed to do something on the character from the Game Instance. Obviously it was then up to me to make sure the BP receiving the message implemented the Interface, but that wasn’t much of a problem.
For our next project, I want to use interfaces to both keep this direct referencing in check (for memory reasons), and to have different objects in our world react to the same event differently. For this, Interface Messages are the obvious solution to me.
In this above example, why would I want to use Interface Calls over Messages, and how would I use them? Could you give a specific example of Interface Call usage?
You should be able to use Interface Calls in essentially the same way that you were using Interface Messages. Taking your example, I’m not sure how exactly you were doing it, but let’s assume you got the character reference through a GetPlayerCharacter node.
So they’re both doing the same thing. I guess you could say the first is less hassle, but that’s only because it’s a bit of an unusual way to use an interface. For the most part, the dependency reduction should be achievable by using asset ID types rather than hard object references where applicable, and in the case you mentioned, having a base character blueprint that declares the functions your game instance needs to call, and overriding those functions in your full character blueprint. That way your game instance is dependent only on the base character class, which if you don’t configure all sorts of properties pointing to other assets, should be very lightweight.
The second use case you gave is I think a more standard way of using an interface. Let’s contrive an example where you have an inventory of objects, they could be any type underneath, but they need to implement this InteractableInterface. Your inventory can store an array of InteractableInterface types.
As I said in the first post, by using interface type variables, you just get some extra safety for free (you only allow objects that you know implement the interface to be added to the inventory). You probably also get a very minor performance improvement, because you only cast an object to the interface once and store it, whereas with interface messages, it would need to internally check to see if the object implements the interface on every call.
I realize these differences aren’t all that significant, and you could very well just continue to use interface messages if you prefer. For me, the main advantage is just that this addition has brought blueprint interfaces a little bit more in line with my idea of what an interface is.
And yeah, the first use case I mentioned was more of a patch to a memory and dependency problem we realized far too late in the project, and it was before Async loading even existed in Blueprint (our project is 75%+ Blueprint). The real solution, as you mentioned, is setting up proper architecture of our classes.