Announcement

Collapse
No announcement yet.

4.7 C++ Transition Guide

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

    4.7 C++ Transition Guide

    Dear Community,

    Here is a thread where we can all compare our notes as we upgrade projects to 4.7!

    Please post the compile errors you encountered and then resolved to help others along!

    Also you are welcome to post questions here about compile errors you cant resolve.

    Again this is a thread where everyone is welcome to contribute!

    ~~~

    Generated Body

    Time to switch over every .h file you have to use GENERATED_BODY !

    Also note you will probably want to add public: if you put your BP vars at the top of the class.

    Also note you need to include your class constructor now as well.

    this

    Code:
    UCLASS()
    class AJoyMechPower : public AJoyMechFire
    {
        GENERATED_UCLASS_BODY()
    becomes this

    Code:
    UCLASS()
    class AJoyMechPower : public AJoyMechFire
    {
        GENERATED_BODY()
    	
    public:
        AJoyMechPower(const FObjectInitializer& ObjectInitializer);
    ~~~

    RPCs in 4.7

    You will likely encounter errors with your function calls like

    Code:
    UFUNCTION(Server,Reliable,WithValidation)
    void YourServerFunc();
    
    UFUNCTION(Client,Reliable,WithValidation)
    void YourClientFunc();
    Please see this note from Epic Ryan G.

    Originally posted by Ryan Gerleve View Post
    Hey everyone,

    Sorry for the confusion about this. The automatic generation of _Implementation and _Validate function declarations has been deprecated in 4.7, and will likely be removed in 4.8, so you should update your RPCs and add these declarations.

    Some of you may not be seeing the warning because it will only be emitted if the class containing the RPC function uses the GENERATED_BODY macro, and not if the class uses GENERATED_UCLASS_BODY.
    Full details in this thread

    ~~~

    Code Sample

    this

    Code:
    UFUNCTION(Reliable,Server,WithValidation)
    void SERVER_UpdateArmorMorph(FName Name, float Value);
    becomes this

    Code:
    UFUNCTION(Reliable,Server,WithValidation)
    void SERVER_UpdateArmorMorph(FName Name, float Value);
    bool SERVER_UpdateArmorMorph_Validate(FName Name, float Value);
    void SERVER_UpdateArmorMorph_Implementation(FName Name, float Value);


    Rama
    Last edited by Rama; 02-26-2015, 11:18 AM.
    100+ UE4 C++ Tutorials on the UE4 Code Wiki, including UE4 Multi-Threading!

    UE4 Marketplace: Melee Weapon Plugin & Compressed Binary Save System Plugin | Rama's C++ AI Jumping Videos | Vertex Snap Editor Plugin

    Visit www.ue4code.com to see lots of videos about my C++ Creations! ♥ Rama

    #2
    Nice one Rama

    Comment


      #3
      ACharacter::OnJumped_Implmentation() is not virtual

      ACharacter::OnJumped() has been changed to a BlueprintNativeEvent and the new explicitly declared ACharacter::OnJumped_Implmentation() is not marked as virtual.

      There was already a bug logged here https://answers.unrealengine.com/que...ual-47-p4.html and the issue has been resolved in github master.

      Make OnJumped_Imlementation() in Character.h virtual and you should be sorted.

      Code:
      virtual void OnJumped_Implementation();
      Last edited by kylawl; 02-24-2015, 09:31 PM.
      @kylerocha
      Luminawesome Games
      http://luminawesome.com/

      Comment


        #4
        Set Sound Class Volume

        FAudioDevice::SetClassVolume does not exist



        I had to change my Victory BP Library node for Setting the volume of any class from this:

        Code:
        bool UVictoryBPFunctionLibrary::VictorySoundVolumeChange(USoundClass* SoundClassObject, float NewVolume)
         {
        	FAudioDevice* Device = GEngine->GetAudioDevice();
        	if (!Device || !SoundClassObject)
        	{
        		return false;
        	}
        	    
        	bool bFound = Device->SoundClasses.Contains(SoundClassObject);
        	if(bFound)
        	{ 
        		Device->SetClassVolume(SoundClassObject, NewVolume);
        		return true;
        	}
        	return false;
         }
        to this:

        Code:
        bool UVictoryBPFunctionLibrary::VictorySoundVolumeChange(USoundClass* SoundClassObject, float NewVolume)
         {
               if(!SoundClassObject) 
               {
                 return false;
               }
        
        	SoundClassObject->Properties.Volume = NewVolume;
        
        	return true; 
         }
        Quite the improvement! Thanks Epic!

        ~~~

        More info

        Check out SoundClass.h and in particular:

        FSoundClassProperties

        Enjoy!

        Rama
        Last edited by Rama; 02-24-2015, 09:08 PM.
        100+ UE4 C++ Tutorials on the UE4 Code Wiki, including UE4 Multi-Threading!

        UE4 Marketplace: Melee Weapon Plugin & Compressed Binary Save System Plugin | Rama's C++ AI Jumping Videos | Vertex Snap Editor Plugin

        Visit www.ue4code.com to see lots of videos about my C++ Creations! ♥ Rama

        Comment


          #5
          Controller ID

          ULocalPlayer::ControllerID is private now, so this

          Code:
          LP->ControllerId
          becomes this

          Code:
          LP->GetControllerId()


          Rama
          100+ UE4 C++ Tutorials on the UE4 Code Wiki, including UE4 Multi-Threading!

          UE4 Marketplace: Melee Weapon Plugin & Compressed Binary Save System Plugin | Rama's C++ AI Jumping Videos | Vertex Snap Editor Plugin

          Visit www.ue4code.com to see lots of videos about my C++ Creations! ♥ Rama

          Comment


            #6
            Originally posted by Unreal C++ Programming Improvements
            • No special constructors needed! Your class constructors no longer need to take an Object Initializer argument.
            Header.h
            Code:
            #pragma once
            #include "GameFramework/Actor.h"
            #include "Euclib.generated.h"
            
            UCLASS()
            class GAMEPROJECT_API AEuclib : public AActor
            {
                GENERATED_BODY()
                
            public:    
                // Sets default values for this actor's properties
                AEuclib();
            
                // Called when the game starts or when spawned
                virtual void BeginPlay() override;
            
            };
            Source.cpp
            Code:
            #include "GameProject.h"
            #include "Euclib.h"
            
            // Sets default values
            AEuclib::AEuclib()
            {}
            
            // Called when the game starts or when spawned
            void AEuclib::BeginPlay()
            {
                Super::BeginPlay();  
            }
            Youtube
            Machine Learning C++ Plugin
            Lindenmayer System C++ Plugin

            Comment


              #7
              Setting or clearing timers have to be done with TimerHandlers now

              Code:
              FTimerHandle HitHeadFalse;
              GetWorldTimerManager().ClearTimer(HitHeadFalse);
              GetWorldTimerManager().SetTimer(HitHeadFalse, this, &ABM_EnemyPawn::HitHeadFalse, 0.65f, false,-1.0f);
              To play sounds, you have to do it this way now as well

              Code:
              UGameplayStatics::PlaySoundAtLocation(this,HurtSound, this->GetActorLocation(), 1.0, 1.0);
              Last edited by TheAgent; 02-24-2015, 11:31 PM.
              Bacon Man : An Adventure (UE4)

              Comment


                #8
                Not a transition guide on its own, but still related and very important to note (also very awesome):

                New: Greatly improved the quality of C++ IDE code completion and error checking with Unreal Engine C++ projects
                Xcode and Visual Studio projects will now have more reliable IntelliSense results
                We now emit compiler definitions and include paths for editor targets (instead of runtime targets), which are much more inclusive
                Fixed project targets "infecting" IntelliSense definitions of other target's project files
                [Submitted] Advanced Data Validation

                Comment


                  #9
                  FTimerHandle / Timers in 4.7

                  Originally posted by TheAgent View Post
                  Setting or clearing timers have to be done with TimerHandlers now

                  Code:
                  FTimerHandle HitHeadFalse;
                  GetWorldTimerManager().ClearTimer(HitHeadFalse);
                  GetWorldTimerManager().SetTimer(HitHeadFalse, this, &ABM_EnemyPawn::HitHeadFalse, 0.65f, false,-1.0f);
                  Thanks for sharing TheAgent!

                  To expand on this new use of FTimerHandle, you have to store a var in your .h file in order to clear a timer outside of the scope in which it was declared.

                  See ShooterGame for example:

                  ShooterAIController.h

                  Code:
                  /** Handle for efficient management of Respawn timer */
                  00064: FTimerHandle TimerHandle_Respawn;
                  .cpp
                  Code:
                  void AShooterAIController::BeginInactiveState()
                  {
                  	Super::BeginInactiveState();
                  
                  	AGameState* GameState = GetWorld()->GameState;
                  
                  	const float MinRespawnDelay = (GameState && GameState->GameModeClass) ? GetDefault<AGameMode>(GameState->GameModeClass)->MinRespawnDelay : 1.0f;
                  
                  	GetWorldTimerManager().SetTimer(TimerHandle_Respawn, this, &AShooterAIController::Respawn, MinRespawnDelay);
                  }
                  
                  
                  //~~~
                  
                  
                  void AShooterAIController::GameHasEnded(AActor* EndGameFocus, bool bIsWinner)
                  {
                  	// Stop the behaviour tree/logic
                  	BehaviorComp->StopTree();
                  
                  	// Stop any movement we already have
                  	StopMovement();
                  
                  	// Cancel the repsawn timer
                  	GetWorldTimerManager().ClearTimer(TimerHandle_Respawn);
                  
                  	// Clear any enemy
                  	SetEnemy(NULL);
                  
                  	// Finally stop firing
                  	AShooterBot* MyBot = Cast<AShooterBot>(GetPawn());
                  	AShooterWeapon* MyWeapon = MyBot ? MyBot->GetWeapon() : NULL;
                  	if (MyWeapon == NULL)
                  	{
                  		return;
                  	}
                  	MyBot->StopWeaponFire();	
                  }
                  ~~~

                  Timer Macros For You

                  I've created (and have been using) four macros you can use if you like!

                  SETTIMER passes in a dummy TimerHandle, you cannot clear a timer started this way (this is done even in the ue4 code base if you look)

                  SETTIMERH lets you pass in a FTimerHandle that you can then use with CLEARTIMER

                  Remember that the FTimerHandle must be declared in your .h if you want to clear the timer in a different function than the one in which it was started.

                  Enjoy!

                  Code:
                  #define SETTIMER(param1,param2,param3) FTimerHandle TimerHandle; (GetWorldTimerManager().SetTimer(TimerHandle, this, &param1, param2, param3))
                  
                  
                  #define SETTIMERH(handle, param1,param2,param3) (GetWorldTimerManager().SetTimer(handle, this, &param1, param2, param3))
                  
                  #define CLEARTIMER(handle) (GetWorldTimerManager().ClearTimer(handle))
                  
                  #define ISTIMERACTIVE(handle) (GetWorldTimerManager().IsTimerActive(handle))
                  
                  
                  _
                  Example Use:

                  .h
                  Code:
                  FTimerHandle TH_CreateApexCreationPieces;
                  .cpp
                  Code:
                  void AStructureCreation::CreationProcess_Phase1()
                  {	
                  	CreationCount = 0; 
                  	
                  	SETTIMERH(TH_CreateApexCreationPieces,AStructureCreation::T_CreateApexCreationPieces,0.23,true);
                  } 
                  void AStructureCreation::T_CreateApexCreationPieces()
                  {
                  	//how many of the apex rocks are we creating?
                  	AStructureCreationApex* DefaultObj = StructureCreationApexBP->GetDefaultObject<AStructureCreationApex>(); 
                  	if(!DefaultObj)
                  	{
                  		UE_LOG(Joy,Error,TEXT("AStructureCreation::CreationProcess_Phase1()>> NO DEFAULT OBJ!!!!!!"));
                  		CLEARTIMER(TH_CreateApexCreationPieces);
                  		return;
                  	} 
                  ///....
                  }
                  Last edited by Rama; 02-25-2015, 12:26 AM.
                  100+ UE4 C++ Tutorials on the UE4 Code Wiki, including UE4 Multi-Threading!

                  UE4 Marketplace: Melee Weapon Plugin & Compressed Binary Save System Plugin | Rama's C++ AI Jumping Videos | Vertex Snap Editor Plugin

                  Visit www.ue4code.com to see lots of videos about my C++ Creations! ♥ Rama

                  Comment


                    #10
                    Don't forget, the official release notes (not the forum announcement) spell out a lot of the breaking changes affecting C++ code.
                    Last edited by ngrts; 02-25-2015, 12:33 AM. Reason: s/all/a lot/g

                    Comment


                      #11
                      Originally posted by SaxonRah View Post
                      Header.h
                      Code:
                      #pragma once
                      #include "GameFramework/Actor.h"
                      #include "Euclib.generated.h"
                      
                      UCLASS()
                      class GAMEPROJECT_API AEuclib : public AActor
                      {
                          GENERATED_BODY()
                          
                      public:    
                          // Sets default values for this actor's properties
                          AEuclib();
                      
                          // Called when the game starts or when spawned
                          virtual void BeginPlay() override;
                      
                      };
                      Source.cpp
                      Code:
                      #include "GameProject.h"
                      #include "Euclib.h"
                      
                      // Sets default values
                      AEuclib::AEuclib()
                      {}
                      
                      // Called when the game starts or when spawned
                      void AEuclib::BeginPlay()
                      {
                          Super::BeginPlay();  
                      }
                      As I learned the hard way, not only are you not required to add a call to Super() in the constructor, but if you do, your editor will crash on startup.
                      [Submitted] Advanced Data Validation

                      Comment


                        #12
                        Originally posted by SaxonRah View Post
                        Header.h
                        Code:
                        #pragma once
                        #include "GameFramework/Actor.h"
                        #include "Euclib.generated.h"
                        
                        UCLASS()
                        class GAMEPROJECT_API AEuclib : public AActor
                        {
                            GENERATED_BODY()
                            
                        public:    
                            // Sets default values for this actor's properties
                            AEuclib();
                        
                            // Called when the game starts or when spawned
                            virtual void BeginPlay() override;
                        
                        };
                        Source.cpp
                        Code:
                        #include "GameProject.h"
                        #include "Euclib.h"
                        
                        // Sets default values
                        AEuclib::AEuclib()
                        {}
                        
                        // Called when the game starts or when spawned
                        void AEuclib::BeginPlay()
                        {
                            Super::BeginPlay();  
                        }
                        With PCIP gone, how do I now create components?
                        July's GameJam Entry: https://forums.unrealengine.com/show...l=1#post341226

                        Comment


                          #13
                          Just remove the OI. (or PCIP.) from your code.
                          [Submitted] Advanced Data Validation

                          Comment


                            #14
                            In AiController the GetFocalPoint is not virtual anymore.
                            PHP Code:
                            FVector GetFocalPoint() const; 
                            Instead, you can now inherit from:
                            PHP Code:
                            virtual FVector GetFocalPointOnActor(const AActor *Actor) const; 
                            Edit: Also, after upgrading to 4.7 I had to re-tick the Environment Query System in the Editor Preferences/Experimental.
                            Last edited by _neo_; 02-25-2015, 02:22 PM. Reason: EQS Tick

                            Comment


                              #15
                              So, I tried to convert my project to 4.7. I have cleaned up the constructor of my player controller, and get the following error:

                              Code:
                              Error	7	error C2512: 'APlayerController' : no appropriate default constructor available	C:\Users\Christian\Documents\Unreal Projects\SurvivalSim\Source\SurvivalSim\SurvivalPlayerController.cpp	8	1	SurvivalSim
                              Code:
                              ASurvivalPlayerController::ASurvivalPlayerController()
                              {
                              	
                              	PrimaryActorTick.bCanEverTick = true;
                              	bShowMouseCursor = true;
                              
                              }
                              Im not sure, if I am even on 4.7 yet, since I cannot convert it without buidling. When I right click on my projectfile and try to switch versions, I only get the message "Failed to generate Project files". When I try to open my project from the 4.7 editor, it wants to rebuild the project, but then failes. When I now go to VS, I get the above error during compile.
                              July's GameJam Entry: https://forums.unrealengine.com/show...l=1#post341226

                              Comment

                              Working...
                              X