Announcement

Collapse
No announcement yet.

How to create C++ enum that can have new entries added in blueprint?

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

    How to create C++ enum that can have new entries added in blueprint?

    Hey guys,

    Imagine a list of factions, for example, which designers should be able to change freely in the editor. How can I make an enum of some sort in C++, where I need to use it for some code functionality, but which can be expanded and modified via the editor?

    Thanks.

    #2
    Originally posted by HateDread View Post
    Hey guys,

    Imagine a list of factions, for example, which designers should be able to change freely in the editor. How can I make an enum of some sort in C++, where I need to use it for some code functionality, but which can be expanded and modified via the editor?

    Thanks.
    You can't define an enum in c++ then add more entries from a blueprint.

    A possible solution might go something like this.

    Define a UStruct for your faction definition

    In this case we have a faction name and a faction colour

    Code:
    USTRUCT()
    struct FFaction
    {
    	GENERATED_USTRUCT_BODY()
    	
    	FName FactionName
    	FLinearColor FactionColor;
    };
    Define a UObject to be the faction list container

    Code:
    UCLASS()
    class UGameFactions : public UObject
    {
    	GENERATED_UCLASS_BODY()
    
    	UPROPERTY(EditAnywhere, Category=Factions, meta=(ShowOnlyInnerProperties))
    	TArray<FFaction> Factions;
    };
    Create a UFactory to create a UGameFactions asset.

    Code:
    UCLASS()
    class UGameFactionsFactoryNew : public UFactory
    {
    	GENERATED_UCLASS_BODY()
    
    	// Begin UFactory Interface
    	virtual UObject* FactoryCreateNew(UClass* Class,UObject* InParent,FName Name,EObjectFlags Flags,UObject* Context,FFeedbackContext* Warn) override;
    	// Begin UFactory Interface	
    };
    From here your designers can open the asset and add/modify/remove factions and you can reference that factions asset using a normal UPROPERTY() in any classes that need it. Or use game instances or whatever construct you care to use.

    An alternative method could be to define a UFaction class and create a new asset for each faction. That would allow you to use the property sheet view to bulk edit factions as well as leverage more of the existing editor ui to create alliances between factions.

    Hopefully you find this helpful.

    / Kyle
    @kylerocha
    Luminawesome Games
    http://luminawesome.com/

    Comment


      #3
      That's not a use case for enums. Enums are just human-readable names for byte values, the string representation is stored only for convenience. Like kylawl posted, what you want is an array of FNames.

      Comment


        #4
        Originally posted by kylawl View Post
        You can't define an enum in c++ then add more entries from a blueprint.

        A possible solution might go something like this.

        Define a UStruct for your faction definition

        In this case we have a faction name and a faction colour

        Code:
        USTRUCT()
        struct FFaction
        {
        	GENERATED_USTRUCT_BODY()
        	
        	FName FactionName
        	FLinearColor FactionColor;
        };
        Define a UObject to be the faction list container

        Code:
        UCLASS()
        class UGameFactions : public UObject
        {
        	GENERATED_UCLASS_BODY()
        
        	UPROPERTY(EditAnywhere, Category=Factions, meta=(ShowOnlyInnerProperties))
        	TArray<FFaction> Factions;
        };
        Create a UFactory to create a UGameFactions asset.

        Code:
        UCLASS()
        class UGameFactionsFactoryNew : public UFactory
        {
        	GENERATED_UCLASS_BODY()
        
        	// Begin UFactory Interface
        	virtual UObject* FactoryCreateNew(UClass* Class,UObject* InParent,FName Name,EObjectFlags Flags,UObject* Context,FFeedbackContext* Warn) override;
        	// Begin UFactory Interface	
        };
        From here your designers can open the asset and add/modify/remove factions and you can reference that factions asset using a normal UPROPERTY() in any classes that need it. Or use game instances or whatever construct you care to use.

        An alternative method could be to define a UFaction class and create a new asset for each faction. That would allow you to use the property sheet view to bulk edit factions as well as leverage more of the existing editor ui to create alliances between factions.

        Hopefully you find this helpful.

        / Kyle
        Hey Kyle, thanks a lot for your detailed reply. I'm new to the use of factory objects in UE4, and there isn't much in the documentation as far as I can tell, so I have to ask - what does this actually do? Is there a particular way the FactoryCreateNew method should be implemented?

        Additionally, how would this function in a networked environment? Factions don't really 'exist' (except maybe in a static sense), and are used just to tag certain player starts and players. Eventually the factions may keep track of all owned ships. But even then, they may well only exist server-side. I wonder how that impacts this methodology?

        Any words on the matter would be appreciated.

        Originally posted by pedro_clericuzzi View Post
        That's not a use case for enums. Enums are just human-readable names for byte values, the string representation is stored only for convenience. Like kylawl posted, what you want is an array of FNames.
        I was merely using it to tag player starts and players, so the starts would only spawn the correct faction players Seemed more reliable than straight string comparisons.

        Comment


          #5
          Enums are just byte values: 0, 1, 2, 3... up to 255. The "names" are just convenience, they are not meant to be changed during runtime. The FName type does not person actual string comparisons: FNames are stored in a table of unique FNames and each one gets an ID, so when you compare two FNames you are just comparing the ID. It's not as simple as comparing two bytes, but it's far less complicated than actual string comparison and you can safely do it hundreds (or thousands) of times a frame without penalty.

          Comment


            #6
            Originally posted by HateDread View Post
            Hey Kyle, thanks a lot for your detailed reply. I'm new to the use of factory objects in UE4, and there isn't much in the documentation as far as I can tell, so I have to ask - what does this actually do? Is there a particular way the FactoryCreateNew method should be implemented?
            Take a look at UMaterialFactoryNew. That is the factory that allows you to create new material assets. It's very simple and should help explain how setting up a new factory works.

            Originally posted by HateDread View Post
            Additionally, how would this function in a networked environment? Factions don't really 'exist' (except maybe in a static sense), and are used just to tag certain player starts and players. Eventually the factions may keep track of all owned ships. But even then, they may well only exist server-side. I wonder how that impacts this methodology?
            This method works fine in a networked game. Your client will need to have some knowledge of factions I would imagine, names, colours, faction bios or any other static info you might want to show players about the factions.

            As for associating it all, you're right you just need some FactionID or something still. I mentioned an fname, but you could still just use an enum rather than an FName if you wanted and just use some generic names.

            Code:
            enum class EFactions : uint8
            {
            	Faction0,    
            	Faction1,
            	Faction2,
            	Faction3,
            	...
            }
            You could then do something like this with your faction info struct to tie meaningful info to the generic ids.

            Code:
            USTRUCT()
            struct FFaction
            {
            	GENERATED_USTRUCT_BODY()
            	
                    EFactions FactionID; // Faction
            
            	FName FactionName
            	FLinearColor FactionColor;
            };

            If you don't care about all this extra info I've been adding to your system. Just go with the generic enum and don't worry about the rest of the ****.
            @kylerocha
            Luminawesome Games
            http://luminawesome.com/

            Comment


              #7
              Originally posted by kylawl View Post
              Take a look at UMaterialFactoryNew. That is the factory that allows you to create new material assets. It's very simple and should help explain how setting up a new factory works.



              This method works fine in a networked game. Your client will need to have some knowledge of factions I would imagine, names, colours, faction bios or any other static info you might want to show players about the factions.

              As for associating it all, you're right you just need some FactionID or something still. I mentioned an fname, but you could still just use an enum rather than an FName if you wanted and just use some generic names.

              Code:
              enum class EFactions : uint8
              {
              	Faction0,    
              	Faction1,
              	Faction2,
              	Faction3,
              	...
              }
              You could then do something like this with your faction info struct to tie meaningful info to the generic ids.

              Code:
              USTRUCT()
              struct FFaction
              {
              	GENERATED_USTRUCT_BODY()
              	
                      EFactions FactionID; // Faction
              
              	FName FactionName
              	FLinearColor FactionColor;
              };

              If you don't care about all this extra info I've been adding to your system. Just go with the generic enum and don't worry about the rest of the ****.
              Hey kylawl,

              I'm back to this area of my project, and I've been thinking about your suggestions. I quite like just making an actor for each faction so I can replicate it out - unit counts etc. I would guess putting it in the base GameMode class of mine, and trying to inform the GameState about it so clients can query it too.

              However, I'd like to look further into the Factory idea, but I still don't understand their purpose. What does a factory actually _do_?

              EDIT: Okay, so I've looked even further and experimented. MaterialFactoryNew's FactoryCreateNew method is called when I add a new material to the content browser, and I presume the factory we're discussing would do the same. The problem is that I'd want only 1 copy of each new asset to exist. I'm unsure of how to make a UFactory that spits out unique objects that cannot be spawned more than once. This definitely seems to gel more with your suggestion where the factions are more like a 'type' than an object with dynamic members.
              Last edited by HateDread; 09-03-2014, 04:34 AM.

              Comment

              Working...
              X