Announcement

Collapse
No announcement yet.

migrate code based blueprint?

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

    migrate code based blueprint?

    hello

    i have a blueprint based on custom code in 1 project and would like to migrate it to another project.
    the blueprint took a long time to get how i want and im unable to reproduce it.
    i have successfully copied the code over with a single change in the game api reference, but when i migrate the blueprint it says the base class does not exist.

    is it possible at all?

    thanks
    tegleg.co.uk - indie electronic music label
    Android + HTML5 WIP Physics Game
    PC Games - Android Apps

    #2
    It is possible. It involves a little work, though. From looking at the generated C++ from a 4.6 project, it looks like this may have changed for 4.6, but in 4.5 and earlier, the C++ classes have a project-specific Macro. For example, for one test project I have, it looks like this:

    Code:
    UCLASS()
    class REPUBLICSNIPERAI_API AEnemyCharacter : public ABaseNPCCharacter
    {
    	GENERATED_UCLASS_BODY();
    The REPUBLICSNIPERAI_API was auto-generated by UE4 based on the name of my project (RepublicSniperAI). In the project settings, it is defined as an empty string, so it has no effect on the generated code. I don't know the full affect of this macro or how it's used by UE4's build system. With 4.6, it appears to no longer be used, but I'm not sure if something else takes its place.

    So, to migrate the code, you copy the .h and .cpp files to your new project's source folder, then you need to change this macro to the class-specific macro for your project. If the project you're migrating to is a 4.6 project, it looks like you would simply remove the macro altogether, but maybe someone more familiar with the 4.6 engine changes can confirm that.

    After that, there's one more step you need to take. The blueprints that subclass or reference your migrated classes will have a reference based on the name of your old project. In order to deal with that, you need to put Active Class Redirects into your project's DefaultEngine.ini file in your project's Config folder. For each class that is used in Blueprints, you need to do something like this at the end of the DefaultEngine.ini file:

    Code:
    [/Script/Engine.Engine]
    +ActiveClassRedirects=(OldClassName="EnemyCharacter",NewClassName="/Script/RepublicSniper.EnemyCharacter")
    +ActiveClassRedirects=(OldClassName="EnemyController",NewClassName="/Script/RepublicSniper.EnemyController")
    +ActiveClassRedirects=(OldClassName="BaseNPCCharacter",NewClassName="/Script/RepublicSniper.BaseNPCCharacter")
    +ActiveClassRedirects=(OldClassName="BaseNPCController",NewClassName="/Script/RepublicSniper.BaseNPCController")
    +ActiveClassRedirects=(OldClassName="FriendCharacter",NewClassName="/Script/RepublicSniper.FriendCharacter")
    +ActiveClassRedirects=(OldClassName="FriendController",NewClassName="/Script/RepublicSniper.FriendController")
    +ActiveClassRedirects=(OldClassName="NavigationMarker",NewClassName="/Script/RepublicSniper.NavigationMarker")
    +ActiveClassRedirects=(OldClassName="BTTask_MoveToward",NewClassName="/Script/RepublicSniper.BTTask_MoveToward")
    +ActiveClassRedirects=(OldClassName="BTTask_SelectRandomLocation",NewClassName="/Script/RepublicSniper.BTTask_SelectRandomLocation")
    +ActiveClassRedirects=(OldClassName="BTTask_StopMoving",NewClassName="/Script/RepublicSniper.BTTask_StopMoving")
    +ActiveClassRedirects=(OldClassName="BTDecorator_IsMoving",NewClassName="/Script/RepublicSniper.BTDecorator_IsMoving")
    OldClassName is the unmodified name of the C++ class without the prefix character (e.g. EnemyCharacter, not AEnemyCharacter). NewClassName takes the form /Script/ProjectName.classname.

    Once you've done that, you should be able to migrate the blueprints from the editor to your new project the way you would any other blueprint.

    Hope that helps.
    Last edited by Kneebiter; 12-09-2014, 10:17 AM.

    Comment


      #3
      that worked thanks jeff
      tegleg.co.uk - indie electronic music label
      Android + HTML5 WIP Physics Game
      PC Games - Android Apps

      Comment


        #4
        You're welcome. This was really hard to discover when I encountered it initially. I should probably take my answer and turn it into an Unreal Wiki posting.

        Comment


          #5
          it would be a great bit of info for the wiki, i would never have found that without you saying.
          cheers
          tegleg.co.uk - indie electronic music label
          Android + HTML5 WIP Physics Game
          PC Games - Android Apps

          Comment


            #6
            WOW it really works!
            Does it work also for structures? I have a few and editor changed it to "unknow struct"
            I tried +ActiveStructRedirects=(OldStructName="sectorX",NewStructName="/Script/CleanThirdPerson.sectorX") with no luck.

            Click image for larger version

Name:	struct.png
Views:	1
Size:	424.2 KB
ID:	1087199
            Last edited by Tefel; 09-07-2015, 07:39 PM.

            Comment


              #7
              Hmm it has to be a way to redirect structs. I want to use Struct from migrated c++ actor inside migrated MyController.

              Comment


                #8
                This was so helpful! This method not so obvious because of "/Script/" part (answers in AnswerHub didn't mention this).

                I achieved some succes with autoreplacing in .uasset files but only with same string length, because of many many offsets that could be affected according to Asset file structure.

                Now I can even rename project* or migrate code based Blueprints!

                Worked in Engine Version 4.10.2

                DefaultEngine.ini file:

                Code:
                [/Script/Engine.Engine]
                +ActiveClassRedirects=(OldClassName="OldProjectName",NewClassName="/Script/NewProjectName")
                +ActiveClassRedirects=(OldClassName="MyBlueprintBaseClass",NewClassName="/Script/NewProjectName.MyBlueprintBaseClass")
                +ActiveClassRedirects=(OldClassName="MyEnumE",NewClassName="/Script/NewProjectName.MyEnumE")
                Actually after recompiling and resaving all blueprints and maps these redirects can be removed!

                * - renaming project requires next steps:
                1. Rename ProjectName.uproject (and Module name in it)
                2. Rename folder Source/ProjectName/
                3. Generate VS project files (project file context menu)
                4. Open generated VS solution file (with new project name)
                5. Autoreplace (Ctrl+H) in whole project ProjectName to NewProjectName (case sensitive!)
                6. Autoreplace (Ctrl+H) in whole project PROJECTNAME_API to NEWPROJECTNAME_API
                7. Rename ProjectName.Target.cs
                8. Rename ProjectNameEditor.Target.cs
                9. Rename ProjectName.Build.cs
                10. Rename ProjectName.[cpp,h]
                11. Probably you want to rename some files like ProjectNameGameMode.[cpp,h] if any present, but you should add right redirections for it (old class name to new one)
                12. Fix DefaultEngine.ini as above.
                13. Compile


                First time there will be errors in message log, but if all dependencies are redirected, then blueprints can be opened, recompiled and resaved.
                Last edited by MorskoyZmey; 01-21-2016, 07:17 AM.

                Comment


                  #9
                  The class/enum/function/struct redirects were modified a bit, and the only docs I can find on it are in the 4.16 Upgrade Notes

                  When I migrated content from one code project to another, I used the new "MatchSubstring" feature in the new project's DefaultEngine.ini:


                  Code:
                  [CoreRedirects]
                  +ClassRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                  +EnumRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                  +FunctionRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                  +StructRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                  When I opened the migrated maps/objects that used C++ classes that were copied over to the new project, the editor still gave me warning/errors, but a save quickly resolved the issue.

                  Comment


                    #10
                    Originally posted by LouDilbert View Post
                    The class/enum/function/struct redirects were modified a bit, and the only docs I can find on it are in the 4.16 Upgrade Notes

                    When I migrated content from one code project to another, I used the new "MatchSubstring" feature in the new project's DefaultEngine.ini:


                    Code:
                    [CoreRedirects]
                    +ClassRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                    +EnumRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                    +FunctionRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                    +StructRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                    When I opened the migrated maps/objects that used C++ classes that were copied over to the new project, the editor still gave me warning/errors, but a save quickly resolved the issue.
                    I was trying to copy an entire plugin's content folder to a new plugin's content folder, and this is the only method that worked for me.
                    I also had to add lines for:

                    Code:
                    +PackageRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                    +PropertyRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                    +ObjectRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")

                    Comment


                      #11
                      I just wanted to say thank you for this post, it saved me countless hours.

                      Comment


                        #12
                        Hello!

                        I'm trying to migrate some BP classes from a project where parent classes are defined on the project source to a project where parent classes are defined in a plugin and I'm quite stuck, I have tried different [CoreRedirects] formats, with and without /Script/, but nothing:
                        Code:
                        [CoreRedirects]
                        +ClassRedirects=(OldName="/Script/OldProjectModuleName",NewName="/Script/NewPluginModuleName",MatchSubstring=True)
                        +PackageRedirects=(OldName="/Script/OldProjectModuleName",NewName="/Script/NewPluginModuleName",MatchSubstring=True)
                        also:
                        Code:
                        [CoreRedirects]
                        +ClassRedirects=(OldName="/Script/OldProjectModuleName.ClassName1",NewName="/Script/NewPluginModuleName.ClassName1")
                        +ClassRedirects=(OldName="/Script/OldProjectModuleName.ClassName2",NewName="/Script/NewPluginModuleName.ClassName2")
                        If you have any idea to point me in the right direction will be appreciated!

                        Comment


                          #13
                          Thanks everyone. I had to add a couple of things to the solution to #9 to get it to work for me:
                          From

                          Code:
                          [CoreRedirects]
                          
                          +ClassRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                          
                          +EnumRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                          
                          +FunctionRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                          
                          +StructRedirects=(MatchSubstring=True,OldName="/OldProjectName",NewName="/NewProjectName")
                          to

                          Code:
                          [CoreRedirects]
                          
                          +ClassRedirects=(MatchSubstring=True,OldName="/Script/OldProjectName",NewName="/Script/NewProjectName")
                          
                          +EnumRedirects=(MatchSubstring=True,OldName="/Script/OldProjectName",NewName="/Script/NewProjectName")
                          
                          +FunctionRedirects=(MatchSubstring=True,OldName="/Script/OldProjectName",NewName="/Script/NewProjectName")
                          
                          +StructRedirects=(MatchSubstring=True,OldName="/Script/OldProjectName",NewName="/Script/NewProjectName")
                          
                          +PackageRedirects=(OldName="/Script/OldProjectName",NewName="/Script/NewProjectName")

                          just matching /OldProjectName would match and rename references to classes if class name contains OldProjectName, for example if you had a c++ class you were migrating named OldProjectNameGameMode, you would end up redirecting references to that class by blueprints that use it as a parent to NewProjectNameGameMode which you don't want.

                          Also added PackageRedirects

                          If you check BaseEngine.ini in the UE4 build's config folder there is helpful info there and you can see how they use these redirects with every new build of UE4.

                          In there it says

                          [Core Redirects]

                          ; All redirects prior to UE 4.10 are now in FCoreRedirects::RegisterNativeRedirects, new ones should be added to the bottom of this section
                          ; Redirects can now go in any ini file, including Plugin inis
                          ; This new redirect format has replaced the old ActiveClassRedirects/K2FieldRedirects format, and the syntax is the same for every type
                          ;
                          ; +ClassRedirects=(OldName="OldClass", NewName="/Script/Module.NewClass")
                          ; +ClassRedirects=(OldName="/Script/Module.OldClass", NewName="/Script/Module.NewClass")
                          ;
                          ; Those two will do the same thing, assuming OldClass was in Module. It uses as much of the name as you give it. You can also add options or add a value change map:
                          ;
                          ; +ClassRedirects=(OldName="OldClass", NewName="/Script/GameName.GameSpecificClass", bInstanceOnly=true)
                          ; +PackageRedirects=(OldName="/OldPlugin/", NewName="/NewPlugin/", MatchSubstring=true)
                          ; +PackageRedirects=(OldName="/Game/DeletedContentPackage", Removed=true)
                          ; +EnumRedirects=(OldName="/Script/Core.EEnumType", NewName="/Script/NewModule.ENewEnumType", ValueChanges=(("OldValue", "NewValue"), ("OldValue2", "NewValue2")) )
                          and then if you open the BaseEngine.ini and look at all the following lines you can see how they use core redirects for objects in the engine to provide compatibility with new engine releases.
                          Last edited by tomotor; 09-10-2019, 04:09 AM.

                          Comment

                          Working...
                          X