Custom LyShine Components causing LNK2001 error in 1.9

I have made several custom UI components using the LyShine system, some of which are general components, and some of which directly interface with other parts of my project code, because of this; I need the code to be included within my project rather than in the LyShine project. This was all working fine in previous versions, however, as LyShine is now a Gem in 1.9 things no longer work in the same way.

I have updated and changed everything required to fix the initial compile errors as to be expected with a normal version update, and I have added the LyShine Gem to my project, however, I am now receiving the following error:

UiInventorySlotComponent.cpp.136.obj : error LNK2001: unresolved external symbol “public: __cdecl UiInteractableComponent::UiInteractableComponent(void)” (??0UiInteractableComponent@@QEAA@XZ)

As well as a few hundred other similar ones for different functions of the UiInteractableComponent. The problematic classes are the ones that inherit directly from the UiInteractableComponent, which is what I worked from by copying the UiButtonComponent code and working from there, as it had most of the functionality I require. It seems to be an error linking the LyShine library to my project.

I have tried multiple steps to attempt to fix this, but have not been successful as of yet. I’m not sure if there is a step I’m missing in linking the LyShine Gem to my project, or if I’m going about the custom UI components in the wrong way altogether. In any case, if anyone has any advice it would be greatly appreciated.

Hi @Humungo,

Sorry to hear of your issues. As you mention LyShine has changed to be a gem and with the introduction of UI slices and the UI canvas resource compiler some changes were required which have affected custom UI components.

First, prior to v1.9 there was an LyShine static library that included UiInteractableComponent. This allowed custom components outside of LyShine to derive from UiInteractableComponent. In v1.9 LyShine is now a gem and does not have a static library, so it is no longer possible to derive from UiInteractableComponent. In part this is because we are trying to avoid exposing base classes to derive from as part of our API because it is hard to maintain backward compatibility long term with that kind of API. Instead we recommend that you create your own base class that implements the same buses (e.g. make your own copy of UiInteractableComponent and customize it how you wish).

Second, all components should now be implemented in gems. This is so that tools such as the dynamic slice compiler (ResourceCompilerSlice) and the UI canvas compiler (ResourceCompilerUiCanvas) can access the component definitions. So you will need to create a new gem (using the ProjectConfigurator) and move your custom UI components into the gem. Without this step you will see errors in the asset processor when it tries to compile your UI canvases that use your custom components.

Thirdly, (you may have already encountered this), the registration of new UI components is now more consistent with how other component entities are registered. There is no longer a UiComponentFactory. See how the UI components are registered in the LyShine gem in the LyShineModule constructor. Then, each UI component’s Reflect function tells the component to appear in the UI Editors Add Component menu. (search for “AZ::Edit::ClassElements::EditorData” in UiButtonComponent.cpp) for example.

So, apologies again for the inconvenience, the intention is that this will make for a more stable API going forward.

Please let us know if you encounter any other issues or any suggestions for improvements.