Announcement

Collapse
No announcement yet.

How to solve instance, archtype component updates for already placed objects?

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

    How to solve instance, archtype component updates for already placed objects?

    Hi,

    i recently added a new ActorComponent to a placable actor that already has instances placed inside the level via a archtype.
    The component is declared with "var() editconst" and added using the DefaultProp block.

    I can see and edit the component properties inside the editor, but if i change a value to a none default value and save/reload the map, the editor complains that the object/archtype don't have such a component.

    Is there a way to "reinitialize" add the missing component to the already placed actors? Do i have to "patch" such changes somehow dynamically inside PostBeginPlay() or is there some kind of "Update" mechanic i can use to have the missing component also created for the already placed versions?

    Code:
    	Begin Object Class=MyComponentClass Name=MyComponent
    		bEnabled=true
    	End Object
    	Components.Add(MyComponent)
    	MyComponentRef=MyComponent
    Now inside PostBeginPlay() i get a "Component_1" reference for "MyComponentRef", but inside the actor's components array i only see a "Component_0"?
    So the "_1" instance has the editor set values, while the version inside the actor is uninitialized?
    Why is the instanced component version inside the actor not the same version i get the MyComponentRef set?

    Thx Andy

    #2
    This has been a bit of a confusion for me as well. You can't add it to the Components list in the defaultproperties, and still have the instance changeable in the editor.

    I think (haven't tried) you can do something like:

    Code:
    var() ActorComponent x;
    
    function PostBeginPlay() 
    {
        if(x != None) AttachComponent(x);
    }

    Comment


      #3
      You both are wery close...

      Function PostBeginPlay() is called from game not from editor.
      AttachComponent(x) will add component to the existing actor components array.

      Possible solution:
      var() ActorComponent MyComponentRef;

      Begin Object Class=MyComponentClass Name=MyComponent
      bEnabled=true
      End Object
      Components.Add(MyComponent)
      MyComponentRef=MyComponent
      Or simply:

      var() ActorComponent MyComponentRef;
      and after (in editor) setup your component.

      Comment


        #4
        VendorX:

        Your "Possible solution" is actually the problem If you set MyComponentRef=MyComponent in the defprops, if you try to use a different component in the editor other than the one that was auto-generated, it results in spitting out errors, and not working.

        I haven't tried it, but i -think- you need to not try to declare a default component for it, if you want the user to be albe to change it to a different component, from within the editor. And you'll probably need to attach said new component to the actor in game from PBP()

        Comment


          #5
          Mhh i was hoping for a "cleaner" solution to this problem. What i don't fully understand is what UDK saves inside the map in regards to the Actor class and its components.

          I'm still confused why i cant find the "Comp_1" that is set for MyComponentRef, inside the actor at all and why there is actually just a default "Comp_0" inside?

          How is the creation flow here?
          To get this result somehow the newly added defaultprop component seems to be the "Comp_0" which is put inside the actor. So we can actually add (also remove?) new components and they will be auto generated even on old actors.
          Now there is this "Comp_1" that is NOT inside the actor and has the editor set properties, while the var() is declared "editconst" which should prevent the editor from allowing to generate new components in the first place and "should" prevent such chaos.

          My question is where the "Comp_1" is instantiated and why its not inside the actor?

          Ah and ofc still how can we correctly work, update the actors in such a case?
          I mean it should be a default case that u place actors inside the level and later by some artist feedback the need arise that u maybe want to add a drawbox component to visualize things? So there should be a default procedure to handle those updates without recreating all archtypes/prefabs and replacing all old objects.

          thx Andy

          Comment


            #6
            ...
            Your "Possible solution" is actually the problem...
            I now... I now... I forget about defaults (probably will generate collision error to), but second i think is right - empty component, that you will declare into editor.

            Comment


              #7
              A other solution for none visible components could be to just declare a array of the component class type and flag this instanced or allow the editor to create new components and than add those from the array to the actor and avoid using the defaultprops at all.

              But than u also wont see any visible feedback or changes inside the editor, since all primitive components need to be instanced using the defaultprops to be seen inside the editor.

              UPDATE: Some more test also shows that the "old" archtype also adds to this component "chaos"..

              Comment


                #8
                Instance functions can't be executed in editor.
                If you use 'AttachComponent', try first 'DetachComponent(OldComponent)' then 'AttachComponent(NewCdomponent)'.

                Comment


                  #9
                  Originally posted by VendorX View Post
                  Instance functions can't be executed in editor.
                  If you use 'AttachComponent', try first 'DetachComponent(OldComponent)' then 'AttachComponent(NewCdomponent)'.
                  With "instanced" i mean the variable flag which allows the editor to build a instance of the given class type and for example put it into a array.

                  Like noted the problem exists because i "need" to use the defaultprop block to "create" the components so resorting to the use of AttachComponent() is more like a hack/patch, since in every derived class u would have to do a logical validation check if all referenced components are inside the actor and if there are any that u don't own a class reference too are "invalid". So DetachComponent(OldComponent) wont work since u don't have the OldComponent reference of this "ghost" component. All u can do is iterate over all actor components and compare the directly hold references to the one inside the actor array and "try" to clean any invalid.
                  This all seems kinda messy to me...

                  Comment


                    #10
                    Originally posted by VendorX View Post
                    ...
                    If you use 'AttachComponent', try first 'DetachComponent(OldComponent)' then 'AttachComponent(NewCdomponent)'.
                    This work only in game and solution for empty component is simple check.
                    If(OldComponent != None)
                    DetachComponent(OldComponent);
                    Make array and try 'editoronly' in 'var()'.

                    Comment


                      #11
                      @VendorX, Oki there is a misunderstanding here. Like noted the problem is that the actor has a invalid "ghost" component inside its component array which u have no reference to. The only way to notice this component is to iterate over the components array and your class has a valid set reference to a other editor created component, which is not inside the actor's comp. array.

                      The trouble starts if u now for example have multiple components of the same class type, or your class simply hold no reference to a "valid" component since its just added but not used by logic, how u exactly determine which component is valid and which is a "ghost". Also dynamically having to "patch" the components array and references seem's strange to me.

                      Comment


                        #12
                        Allover i try to say, that it's no way to do that in editor. With predefined array - Ok, but you can't add to this array custom components, which don't belong to the array class.

                        Let me now if you find way out.

                        Comment


                          #13
                          Oki i fiddled with this problem for a couple of hours and i hope i found a workaround.

                          The actual problem seems to be the same i already reported in the support forum, but in this case results in a different bug.

                          Here are the steps:

                          1) Create a placeable actor and also create a archtype for it.

                          2) Now place a archtype instance and a normal class instance inside your level. Save all and close the Editor.

                          3) Add whatever ActorComponent u like via defaultprops and add a var() editconst reference member to it. Recompile.

                          4) Reload your map, no error will popup and all looks fine on the placed actors, for both the class instanced version and the archtype version.
                          But if u actually debug the game and check the component name closely u will notice that the instanced archtype component name is the same than the one inside the class version. So both seem to reference the same instance? Actually if u try to change a member u will notice that only the name is the same and both actually are 2 different instances. This still is strange since normally each instance has a unique name.


                          5) Now change a property in both placed instances via F4/prop inside the Editor. Save your map and close the Editor.

                          6) Now run your game and debug whats in your actors components array and whats assigned to the member variable!
                          The archtype instance now has a different component instance assigned to the member variable, than whats inside the actor component array. Something like Component_0 and the array has Component_1, where the _0 is the correct changed instance and the _1 instance is a default version inside the array.
                          In comparison the class version has the correct instance assigned as member and also has this instance inside the actor component array.

                          So here we have the actual bug that can cause big problems in your level.


                          7) Now open your map in the Editor again, now UDK will complain about a missing component in the archtype.

                          To actually fix this bug, u need to manually resave your archtype via the content browser even if it is not flagged as changed, don't use "Update AT from Instance" yet, since this will totally bug your AT and instead of a defaultprops named "MyComponent_AT" member, it will assign the instanced "Component_0" from the placed instance as default.

                          So again it seem that archtypes are not correctly saved on changes, so every time a component is added/removed u have to manually resave all your "involved" archtypes to fix this!

                          Hope this is understandable to some of u

                          bye Andy


                          PS: I need to make a bit more tests to ensure this manual save actually fixes all "old" versions in any variation.

                          Comment

                          Working...
                          X