x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Generic Object Creation

I want to implement a generic method to create instance of ItemComponents from Items. Here is my design.

Item Implementation

 class UItemBase : public UObject
 {
     UPROPERTY(...) TSubclassOf<UItemComponentBase> ComponentClass;
 }
 class UItemClassA: public UItemBase;
 class UUtemClassB: public UItemBase;

Component Implementation

 class UItemComponentBase: public UActorComponent
 {
     UPROPERTY(...) UItem* ItemInstance;
 }
 class UItemComponentA: public UItemComponentBase;
 class UItemComponentB: public UItemComponentBase;

Now, I want to instantiate specific component for specific item.

 bool ASomeActor::AddItemComponent(TSubclassOf<UItemBase> ItemClass)
 {
     UItemBase* ItemTemplate = ItemClass.GetDefaultObject();
     UItemComponentBase* ItemComponent = NewObject<UItemComponentBase>(this, ItemTemplate ->Name, EObjectFlags::RF_NoFlags, ItemTemplate ->ComponentClass.GetDefaultObject());
     ItemComponent ->ItemInstance = NewObject<UItemBase>(ItemComponent , ItemTemplate ->Name, EObjectFlags::RF_NoFlags, ItemTemplate);
     ItemComponent ->RegisterComponent();
     return true;
 }

Of course, the code is not instantiating the child classes, they are just instances of UItemComponentBase. How can I achieve this? Is it possible to implement a generic method for that or do I need to check the type and write different code for each class type?

Edit: I can only achieve this by type checking and writing different methods for each UItemComponent subclass.

 bool ASomeActor::AddItemComponent(TSubclassOf<UItemBase> ItemClass)
 {
     UItemBase* ItemTemplate = ItemClass.GetDefaultObject();
     if (ItemTemplate ->IsA<UItemClassA>())
     {
         UItemComponentA* ItemComponent = NewObject<UItemComponentA>(this, ItemTemplate ->Name, EObjectFlags::RF_NoFlags, ItemTemplate ->ComponentClass.GetDefaultObject());
         ItemComponent ->ItemInstance = NewObject<UItemClassA>(ItemComponent , ItemTemplate ->Name, EObjectFlags::RF_NoFlags, ItemTemplate);
         ItemComponent ->RegisterComponent();
     }
     else if (ItemTemplate ->IsA<UItemClassB>())
     {
         UItemComponentB* ItemComponent = NewObject<UItemComponentB>(this, ItemComponentTemplate ->Name, EObjectFlags::RF_NoFlags, ItemComponentTemplate ->ComponentClass.GetDefaultObject());
         ItemComponent ->ItemInstance = NewObject<UItemClassB>(ItemComponent , ItemTemplate ->Name, EObjectFlags::RF_NoFlags, ItemTemplate);
         ItemComponent ->RegisterComponent();
     }
     //... so on
 }
 
Product Version: UE 4.10
Tags:
more ▼

asked Jan 27 '16 at 10:14 AM in C++ Programming

avatar image

cahitburak
89 7 10 16

(comments are locked)
10|2000 characters needed characters left

1 answer: sort voted first

checking for the type of class in a switch case, is a sign that your breaking encapsulation and not properly delegating tasks. your design makes ASomeActor a high-maintenance, all-knowing class, that needs new code for every new item subclass you create.

instead, you should put a virtual function in the item base class that returns its corresponding component. then, when you add a new item subclass, you just need to set the ItemComponentClass variable in the default properties.

each item should be responsible for knowing its own related parts. external objects that communicate with items, should not know anything about specific items or their related parts, they should just know how to communicate with the interface of the base item.

https://en.wikipedia.org/wiki/Separation_of_concerns

more ▼

answered Jan 27 '16 at 02:30 PM

avatar image

ScottSpadea
9.6k 318 205 449

avatar image cahitburak Jan 28 '16 at 08:16 AM

So I done this with the virtual functions. Any other / better approach will be welcomed. Thanks Omnicypher.

 class UItemBase : public UObject
 {
     virtual UItemComponentBase* CreateComponent(AActor* Owner) { return nullptr; }
 }
 class UItemClassA: public UItemBase
 {
     virtual UItemComponentBase* CreateComponent(AActor* Owner) override;
 }
 
 UItemComponentBase* UItemClassA::CreateComponent(AActor* Owner)
 {
     UItemComponentA* ItemComponent = NewObject<UItemComponentA>(Owner, "Name");
     // ...
     return ItemComponent;
 }

And just called the "CreateComponent" method for any "Item".

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question