Download

4.6 Transition Guide

Dear Community,

As usual, I wanted to create a place for people to discuss their findings, questions, and solutions about upgrading to 4.6 !

So if you have any solutions to compile errors, info to share, or questions, feel free to post here!

Community participation is highly encouraged!


**#1 ~ Constructor Change**

To avoid lots of deprecation warnings, you should open up every .cpp file in your project and replace the old constructor 



```


(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{


```



with



```


(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{


```



#2 ~ Creating Subobjects

In all of your constructors for every class where you were making subobject components:

replace



PCIP.CreateDefaultSubobject


with



ObjectInitializer.CreateDefaultSubobject


so for example,



UpgradeMesh1 = PCIP.CreateDefaultSubobject<USkeletalMeshComponent>(this, TEXT("UpgradeMesh1"));


becomes



UpgradeMesh1 = ObjectInitializer.CreateDefaultSubobject<USkeletalMeshComponent>(this, TEXT("UpgradeMesh1"));


Tip: This one is easy to search and replace!


**#3 ~ No more TSubObjectPtr**


Replace all TSubObjectPtrs with regular ptrs

For example



```


UPROPERTY(VisibleDefaultsOnly, Category = "Upgrade Meshes")
**TSubobjectPtr<USkeletalMeshComponent>** UpgradeMesh1;


```



becomes



```


private: 

UPROPERTY(VisibleDefaultsOnly, Category = "Upgrade Meshes")
**USkeletalMeshComponent*** UpgradeMesh1;

//restore public context below here or put private at the bottom.
//public:




```



**Epic Recommendation: Const Accessor**

Epic also recommends you make this pointer private and create a GetUpgradeMesh1() accessor.

This provides a degree of safety against you losing your core component by changing the pointer to something else, or if someone extends your class and does not understand that this pointer should never be messed with.



```


//.h
public:
   USkeletalMeshComponent* GetUpgradeMesh1() const




```





```


//.cpp
USkeletalMeshComponent* AYourClass::GetUpgradeMesh1() const
{
   return UpgradeMesh1; //note this function is const
}


```



By making this pointer **const** you prevent people from changing it to point to something else, and causing the Character or other class to lose the ability to find a core component by your established pointer.

See Character.h for examples, at the very bottom. I chose to use FORCEINLINE but Epic is defining in the .cpp.

#4 ~ Mesh to GetMesh()

Replace



YourCharacter->Mesh


with



YourCharacter->GetMesh()


everywhere in your code base!

I recommend doing search and replace for



Mesh->


and replacing it with



GetMesh()->


to avoid replacing the word “Mesh” when it is used in other ways.

**Same for CharacterMovement and all other pre-existing components!
**

Rama

The release notes state that

does anyone know what they mean by parameterless constructors? For example when I try to remove all parameters from my own GameMode class I get the following compiler error “Constructor for ‘AOwnGameMode’ must explicitly initialize the base class ‘AGameMode’ which does not have a default constructor”. Since the GameMode constructor obviously has parameters like


AGameMode::AGameMode(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer.DoNotCreateDefaultSubobject(TEXT("Sprite")))

does this only count for classes with parameterless constructors, even if we don’t need an ObjectInitializer?

Not sure if it helps but according to another thread where an Epic guy explained it the correct way to provide constructors is now

.h


class Um2uFbxFactory : public UFbxFactory
{
	GENERATED_BODY()

	Um2uFbxFactory(const FObjectInitializer& ObjectInitializer);

};

.cpp



Um2uFbxFactory::Um2uFbxFactory(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}


Landscape is in its own module now!

You need to add it to your Build.cs file:

PublicDependencyModuleNames.AddRange(new string] { “Core”, “CoreUObject”, “Engine”, “InputCore”,“AIModule”,“RenderCore”,“Landscape” });

:slight_smile:

I’ve started adding lots of updates to my original post.

So far this process of upgrading to 4.6 is quite smooth!

I’m explaining everything I am having to do in my original post, and so far it is mostly copy paste, yay!

Rama

Slate Focus Changes

Focusing of input has been generalized to include all controller types as well as the keyboard and mouse, yay!

this function needs to be changed everywhere

from



DEPRECATED(4.6, "SWidget::OnKeyboardFocusReceived() is deprecated, implement SWidget::OnFocusReceived() instead.")
virtual FReply OnKeyboardFocusReceived(const FGeometry& MyGeometry, const FKeyboardFocusEvent& InFocusEvent);


to



virtual FReply OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& InFocusEvent) override;


same for these others!



/**
 * Called when this widget loses focus.  This event does not bubble.
 *
 * @param InFocusEvent The FocusEvent
 */
virtual void OnFocusLost(const FFocusEvent& InFocusEvent);

DEPRECATED(4.6, "SWidget::OnKeyboardFocusLost() is deprecated, implement SWidget::OnFocusLost() instead.")
virtual void OnKeyboardFocusLost(const FKeyboardFocusEvent& InFocusEvent);

/** Called whenever a focus path is changing on all the widgets within the old and new focus paths */
virtual void OnFocusChanging(const FWeakWidgetPath& PreviousFocusPath, const FWidgetPath& NewWidgetPath);

DEPRECATED(4.6, "SWidget::OnKeyboardFocusChanging() is deprecated, implement SWidget::OnFocusChanging() instead.")
virtual void OnKeyboardFocusChanging(const FWeakWidgetPath& PreviousFocusPath, const FWidgetPath& NewWidgetPath);



Victory!

I’ve successfully upgraded one of my UE4 projects (Abatron) to 4.6!

It’s a pretty smooth process folks!

Just ignore the 300-1000 compile errors that you will get each time you compile and keep doing search and replace as I describe in first post and you will be set!

:slight_smile:

Thank you for 4.6 Epic!

Rama

thanks Rama
should make it a bit easier for people, good work as always :slight_smile:

Dort forget to add that GENERATED_BODY replaces GENERATED_CLASS_BODY and the default visibility is now private.
Also you have to declare your constructors in the header!

Example posted here:

Rama you have a mistake in #3, I don’t think the method should be private…

Can you explain how to use GENERATED_BODY? I always get an error with my constructor after that, that it is already implemented.

This is still going to catch things like SkeletalMesh-> and turn them into SkeletalGetMesh()->.

Use whole word search instead.

Header is also now available here instead.



#include "Runtime/Landscape/Classes/Landscape.h"

Seems 4.6 hates some of my macros (that I use everywhere) and my project crashes when compiling any blueprint. This will be a long day…

– EDIT –
Found the problem: 4.6 seems to have a lower tolerance for circular class references, replacing class names with “REINST_” and “SKEL_” everywhere, which causes crashes. So far it seems to only happen when specifying classes directly in function call nodes on the graph. Promoting them to variables with the class as the default value works around the problem.

– EDIT 2 –

Nope, the crashes are back. “Invalid Object in GC”. FML.

Good find, I have fixed that now!


TO GENERATED_BODY OR NOT TO GENERATED_BODY ?

Regarding the GENERATED_BODY part, I am deliberately delaying doing that as I read in the 4.6 notes that waiting till 4.7 was a viable option worthy of consideration.

**Quoting Epic**
"GENERATED_BODY replaces GENERATED_UCLASS_BODY and provides additional UObject improvements. More changes are planned for GENERATED_BODY with the 4.7 release and users with existing code may wish to delay switching existing classes until then."

Since my code bases are so large I opted to do this, for now, I may make the change later, but I have to get a whole bunch of code bases up and running still.

You can be up and running in 4.6 without ding the the GENERATED_BODY change.



Nice to hear from everyone! Please do keep sharing your findings!

Rama

Oh, does someone know what happens in the following case?

I have a class (derived from Actor) ABaseClass. It has a constructor with an ObjectInitializer as parameter, because it needs to create subobjects.

Now I derive from it and have ADerivedClass. It needs only a default constructor, but since I cannot call Base(), because there is no default constructor in ABaseClass, ABaseClass’s constructor remains uncalled and that is not good.

So do i have to use ObjectInitializer constructors in each subclass of other classes using it, so I can reach the call upwards?

Thanks a lot Rama ! :slight_smile:

Nice work Rama :), this is exactly the kind of stuff people need :slight_smile:

Rama doing what Rama does.
Thank you for the layman’s change-list. It really is helpful.
Also, thanks for the help on answers.unreal.

So does the GENERATED_BODY change apply to everything, or just UCLASSes?

Thanks for the list, btw.

EDIT:
Also: For me, I noticed that after the update, all actors were moved to origo. All actors that had a scaled mesh, also had their scale reverted…