Announcement

Collapse
No announcement yet.

Is it possible to use Blueprint variables of a type defined by UINTERFACE?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Is it possible to use Blueprint variables of a type defined by UINTERFACE?

    Hi,

    I've got slightly stuck and although searching has revealed people with all sorts of problems around this area, I haven't seen anyone trying to do exactly this.

    I have an interface defined in C++:

    ----------

    Code:
    UINTERFACE(BlueprintType)
    class UGenerator : public UInterface
    {
    GENERATED_BODY()
    };
    
    class XXX_API IGenerator
    {
    GENERATED_BODY()
    
    // Add interface functions to this class. This is the class that will be inherited to implement this interface.
    public:
    
    ...
    };
    ---------

    At the moment there isn't anything in that bottom "..." section (I only want to identify the inheriting actor types as suitable for passing to other C++-level methods...)

    But if I add a UFUNCTION in there it doesn't seem to change my problem, so I do not think this about empty interfaces.

    I implement this in C++ too:

    ---------

    Code:
    UCLASS(BlueprintType)
    class XXX_API ACubeGenerator : public AActor, public IGenerator
    {
    GENERATED_BODY()
    
    public:
    // Sets default values for this actor's properties
    ACubeGenerator();
    
    protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;
    
    public:
    // Called every frame
    virtual void Tick(float DeltaTime) override;
    
    ... etc ...
    };
    ----------

    Which seems to work happily...

    However then I move to Blueprints and try to use this. I create a variable on a blueprint of type "Generator" and that also works. However, in level editing, when I try to set that variable, it won't take actors of type "Cube Generator"...

    I am thinking what I'm missing is something to tell the reflection system that "Cube Generator" implements "Generator"? e.g. the C++ is aware of that, because of inheriting IGenerator, but there isn't anything specifying the same link between ACubeGenerator and UGenerator. I thought there might be an optional argument for UCLASS, maybe something like "Implements=" but I haven't so-far found anything...

    Can this be done? I guess the alternative is to make the variable just of type Object and cast that to the interface before use, however there doesn't seem to be any point to blueprint variables of interface types if they cannot be populated with different implementations?

    Thanks!

    Ian
    Last edited by TheJamsh; 12-17-2018, 06:49 AM.

    #2
    No, interfaces can't contain UPROPERTY's

    Comment


      #3
      Originally posted by TheJamsh View Post
      No, interfaces can't contain UPROPERTY's
      This isn't what I asked...

      I'm trying to put a variable on a blueprint (created entirely in the editor) but set its type to a interface (created in C++), so that it can contain anything that implements the interface...

      Comment


        #4
        you can check whether a given variable implements the interface.

        but afaik there is no way to get a "list" of all classes that implement the interface (if that is what you are asking).

        (Like what TSubclassOf does with inheritance)
        https://www.casualdistractiongames.com

        Comment


          #5
          Update: https://forums.unrealengine.com/deve...ith-interfaces

          You might be able to force a property to get the behavior you want with MustImplement - e.g.

          UPROPERTY(EditAnywhere, meta = (MustImplement = "ISelectable")) TSubclassOf<UObject> Selected;
          https://www.casualdistractiongames.com

          Comment


            #6
            Originally posted by OptimisticMonkey View Post
            Update: https://forums.unrealengine.com/deve...ith-interfaces

            You might be able to force a property to get the behavior you want with MustImplement - e.g.

            UPROPERTY(EditAnywhere, meta = (MustImplement = "ISelectable")) TSubclassOf<UObject> Selected;
            Hi OptimisticMonkey,

            This might do what I wanted if I was writing a property in C++... However I was trying to create a variable in the blueprint editor:
            • in C++ define an interface ("Generator") and implement it in an Actor (CubeGenerator)
            • in a blueprint (call it BP_XXX) create a variable ("MyGenerator") whose type is "Generator" (and make it instance-editable...)
            • in the level add instances BP_XXX and CubeGenerator
            • then try to assign the CubeGenerator to "MyGenerator" on the BP_XXX
            "MyGenerator" won't accept the object. I can make the type of "MyGenerator" into an Actor and extract (and null-check) the interface at runtime, but run-time errors are far inferior to design-time type-checking...

            This seems like one of the most-basic uses of an interface, I feel I must be missing something...

            Thanks,

            Ian

            Comment


              #7
              This is because the variable 'MyGenerator' is the reflected UInterface type. Your C++ class inherits from the IInterface type, and therefore they are incompatible.

              Blueprint doesn't know anything about unreflected types - as far as it's concerned, you're trying to plug an 'Actor' into a 'UGenerator' variable.

              Interfaces in Unreal have limitations because of reflection. Another example is that you cannot implement an interface in a Blueprint class, and 'Cast' the object in C++ to the related IInterface class.

              Comment


                #8
                Thanks TheJamsh,

                This is where I thought there would be some metadata that could be added to the UCLASS of CubeGenerator to tell the reflection system "this implements UGenerator..."

                The ability to store the things implementing interfaces in handles typed after the interfaces is a quite a low-level property of interfaces, and while the same can be done via Actor variables and casts, that won't get error checked until somebody runs it, which is inefficient for rapid development...

                Ah... I guess if I can do the cast in a construction script, I wonder if there is a way for a construction script to "throw an error" e.g. say it's been given a bad variable configuration...? I'll look into that...

                Thanks, anyway, my basic question has been answered in that it is correct for this not to work and there is no way to enable it.

                Ian

                Comment

                Working...
                X