Create C++ component in 1.10

0

I have to clarify that I don't know to much of C++ I come from Unity and UnrealEngine, how with the version 1.10 can create a component like in this question? The folder in dev/Component/MyProyect isn't there.

In the answer they put a NOTE: This answer is deprecated in favor of putting your component in a Gem, not in your Game DLL. The procedure is similar except you register the descriptor for your component in your Gem's AZ::Module code.

I don't even know what does that mean, it's that the path I have to follow or it changed I don't know what to do and in the documentation I couldn't find anything.

asked 7 years ago162 views
6 Answers
0
Accepted Answer

The path to Gems is usually something like "/Lumberyard/1.10.0.0/dev/Gems/[GemName]/" but that may vary in the future due to features the devs have mentioned are in the works like custom Gem paths. The example you initially referenced was over a year old and most of the current Gem functionality didn't get released until after that example was provided which is why the author said its somewhat deprecated.

Generally when creating a Gem you have a Module Class, a System Component Class and potentially additional Component classes within the Gem. The Module class is generally only used to specify any system components contained in the Gem. The System Components tend to be singletons or Components that are automatically attached to a System Entity and there's probably only one of these and never more as they tend to provide a global service or Gem initialization and aren't meant to be attached to a typical Component Entity such as an Actor in the game world. That System Component would have dependencies such as the MemoryService, NavigationService, etc provided by the Engine that need to be initialized before your Gem can properly initialize. It's possible your System Component class will be largely empty if your Gem is only meant to add Components that get attached to a Component Entity.

The example you referenced showed how to create a System Component but the typical Component you add to a custom Component Entity in the Editor will have different Attributes in the Reflect function. The dependencies will be normal Components like a SpawnerComponent, Physics related Components, Mesh Components, Light Components, etc that most typical Entities in the game world might require when you're creating a Slice. The Slice is sort of a prefab representing a tree of Component Entities that represent what gets Spawned by a SpawnerComponent to represent an Actor, Projectile, etc. These are the types of Components your generally creating and adding to a Component Entity in the Editor.

answered 7 years ago
0

In essence, if you want to create a component, you create a gem and it will create a template for the gem that includes a component template.

To add new components, you modify the gem module source and add in a descriptor of the component.

Example Gem Module

    namespace Example
{
class ExampleModule
: public CryHooksModule
{
public:
AZ_RTTI(ExampleModule, "<guuid>", CryHooksModule);
AZ_CLASS_ALLOCATOR(ExampleModule, AZ::SystemAllocator, 0);
OpenDivaModule()
: CryHooksModule()
{
// Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
m_descriptors.insert(m_descriptors.end(), {
ExampleSystemComponent::CreateDescriptor()
});
}
/**
* Add required SystemComponents to the SystemEntity.
*/
AZ::ComponentTypeList GetRequiredSystemComponents() const override
{
return AZ::ComponentTypeList{
azrtti_typeid<ExampleSystemComponent>()
};
}
};
}

As you can see from above, to add a component to the gem you add the descriptor (which is a static function) to the m_descriptors.

answered 7 years ago
0

Now for the component itself.

Header:

    #pragma once
#include <AzCore/Component/Component.h>
#include <ExampleGem/ExampleGemBus.h>
namespace Example
{
class ExampleSystemComponent
: public AZ::Component
, protected ExampleRequestBus::Handler
{
public:
AZ_COMPONENT(ExampleSystemComponent, "<guuid>");
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
protected:
////////////////////////////////////////////////////////////////////////
// AZ::Component interface implementation
void Init() override;
void Activate() override;
void Deactivate() override;
////////////////////////////////////////////////////////////////////////
};
}

Source:


#include "StdAfx.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include "ExampleSystemComponent.h"
namespace Example
{
void ExampleSystemComponent::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
serialize-ExampleSystemComponent::ReflectAZ::Component>()
->Version(0)
->SerializerForEmptyClass();
//use the serialize context to save/load data that the component uses.
if (AZ::EditContext* ec = serialize->GetEditContext())
{
ec-ExampleSystemComponent::Reflect("ExampleGem", Example System Component.")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
// ->Attribute(AZ::Edit::Attributes::Category, "") Set a category
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System"))
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
;
//use the edit context to add in editor interfaces.
}
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext) {
//Add in behavior context based stuff here.
//Behavior contextes allow for lua and visual scripting interfaces.
}
}
}
void ExampleSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("ExampleService"));
//add in what services the component provides
}
void ExampleSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC("ExampleService"));
//add in what services are incompatable with the component
}
void ExampleSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
(void)required;
//add in what services are required by the component
}
void ExampleSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
(void)dependent;
//add in what services are dependent on the services
}
void ExampleSystemComponent::Init()
{
//initialize data here
}
void ExampleSystemComponent::Activate()
{
//Connect to EBuses here.
//functions the same as a lua scripts "Activate" function.
}
void ExampleSystemComponent::Deactivate()
{
//Disconnect from EBuses here.
//functions the same as a lua scripts "Deactivate" function.
}
}

Components are like the lua scripts you would use but are more in depth than what you can do with a lua script.

answered 7 years ago
0

You can use either.

To create a gem, you use the project configurator. When you have selected a project, there should be "Enable Gems" on the left of the project. All gems are shared between all projects. They are not used unless they are enabled for the project. From here, there's a button that says "Create a new Gem". That is where you will create a gem.

Like the person above, they are in the Gems folder with the name you have given them.

Be sure to enable it for the project so that you can see it in visual studio under the "Gems" sub directory in the solution explorer when you run "lmbr_waf configure".

The flow for components and entities is like this:

-Beginning of Entity lifespan (entity creation)
-Attach component to entity
-Entity Initialized (Entity::Init())
-each component in the entity are initialized (Component::Init())
-Entity is Activated (Entity::Activate())
-each component in the entity are activated (Component::Activate())
--this is where the lua's Activate function is called
--this is where most if not all ebuses are connected
-Entity is Deactivated (Entity::Deactivate())
-each component in the entity are deactivated (Component::Deactivate())
--this is where the lua's Deactivate function is called
--this is where most if not all ebuses are disconnected
-End of entity lifespan (entity destruction)<br>

As to create a component, you can copy the system component and modify it to how you'd like with adding it's descriptor to the gem module. To make it show up in the editor, change the AZ_CRC("System") to AZ_CRC("Game") in the Reflect method's editor context. This is important.

Sorry if this is hard to follow, more used to showing how it works than typing it out.

answered 7 years ago
0

The answer in https://forums.awsgametech.com/t/adding-a-component-and-enable-it-for-the-editor-bar/1171/1 is still valid. You mix up folders as dev/component never existed.

Also see my answer in the post from the 12th January as I updated the answer to changes in the engine.

answered 7 years ago
0

@OneOfManyCoders Thanks!!, yes now I see it more clearly. What i want to do is create a Component not a System Component reading more the documentation i saw the difference and with this I can complete what i'm learning: With blind steps I´m trying to make a simple component with no success, the first answer just confused me more because I didn't know what I was asking for. I don't know the workflow of this, the gems are created, where?, is in VS? in the Project Configurator? Where do you know all this things? Is there a diagram of how the Gems work and the supposed Gem workflow goes? I don't know if in the documentation any of this questions are documented. I'm so frustrated with this Engine but seems to good to left it behind because of ignorance.

Could you explain me how you make a Component to attach in a Entity? additionally, do you use the Lua Scripts for that behavior or you make a C++ component? For what I was reading in the doc, the Component Entity is the future of LY leaving behind the Object Entity so seems they want to use the Lua Scripting as the base of component creation, what you think?

answered 7 years ago

This post is closed: Adding new answers, comments, and votes is disabled.