No announcement yet.

Array not indexing items

  • Filter
  • Time
  • Show
Clear All
new posts

    Array not indexing items

    I'm working on one of my first projects and I've hit my first big stopping block.
    I will do my best do describe this, but I'm no expert and I am most likely just doing it all wrong.
    But I gotta figure this out.
    My Goal:
    Click image for larger version

Name:	inputplayerswidget.png
Views:	1
Size:	183.5 KB
ID:	1224609
    10 Text boxes that the player can input names into. Along with buttons to add or remove players. When Play is clicked, it casts to ThirdPersonCharacter, and adds the texts into an array (under the condition that that player button is enabled)
    Here is a part of that mess:
    Click image for larger version

Name:	WidgetBlueprint.png
Views:	1
Size:	309.5 KB
ID:	1224610
    And, here is my logic for the add/remove buttons
    Click image for larger version

Name:	AddorRemoveButtons.png
Views:	1
Size:	381.9 KB
ID:	1224611
    Now, I want these Array items to to be visible in this widget, but for example if the player only input 4 players, I want the other ones to be hidden
    Click image for larger version

Name:	PlayerNamesDisplay.png
Views:	1
Size:	153.0 KB
ID:	1224612
    Click image for larger version

Name:	GetPlayerNameText.png
Views:	1
Size:	220.3 KB
ID:	1224613
    Click image for larger version

Name:	GetVisibility.png
Views:	1
Size:	233.6 KB
ID:	1224614
    But the problem is, the text saves character names
    Click image for larger version

Name:	NameInput.png
Views:	1
Size:	805.4 KB
ID:	1224615
    Click image for larger version

Name:	NameInput2.png
Views:	1
Size:	774.0 KB
ID:	1224616
    But if there are less than 10 players it's not hidden
    Click image for larger version

Name:	NameInputFail.png
Views:	1
Size:	776.8 KB
ID:	1224617

    So I attatched a find array to my Player blueprint on event tick every 5 seconds.

    Click image for larger version

Name:	FindArray.png
Views:	1
Size:	302.7 KB
ID:	1224618

    But that just prints a bunch of -1s
    which means there is no item for that index #
    But if there are no items, why is the text that was entered in the box still showing up?

    That's a lot of repeated code. You may want to look into creating a User widget to use for each field.

    your last image, the find node in this case looks for the string (in this case 0, 1,2 etc I believe? bit hard to see) and returns -1 if it does not find it. So your claim "which means there is no item for that index #" is incorrect, you are looking for the wrong thing. if you want to look at an index, use the "get" node.
    It won't fix your problem but maybe helps in your attempt to debug it.

    There's also the "Get player 2name visibility" function that I don't understand what you expect from. The "Get last index" returns the last index of the array, not the string if that's what you were trying to check. So because the get last index is probably always going to return greater than 0, it will always return visible. But I'm not seeing where that is used.

    Another minor thing is that you're going to run into problems if a user skips name index.
    For example,
    Player 1
    Player 3
    But because of the setup, "player 3" will end up in "player 2"s index.
    That's of course for later but just be aware of it.
    Last edited by ste1nar; 06-29-2017, 05:24 PM.


      So first off.. Thank you so much for the quick response. The "GET" Function is definitely what I was looking for, not "FIND". This is definitely going to help me with debugging.
      I haven't been able to find any tutorials for making this type of game with blueprints, so this is all off the top of my head. Also, I've never used arrays before.
      So the reason I made all these functions (I made one for every "text" component) was because I didn't want the other texts to show up if the player doesn't choose all 10 players. My idea was that if the index only had 2 items, I would check to see if the last index was more than 1 (because unreal uses 0 as it's first number) and if it wasn't greater than 1 it would display the name that was entered for player 2.
      Click image for larger version

Name:	VisibilityFunctions.png
Views:	1
Size:	281.1 KB
ID:	1130435
      And the branch I added in the gamestart event graph was meant to fix the skipping name index.
      If the player has disabled that box, it will just add the next one to the array in its place.
      But it's definitely not working. And I'm kind of in the middle of getting used to this program and having no idea what I'm doing.
      Also, I see what you mean about the repeated code. This got out of hand very quickly, lol.
      Click image for larger version

Name:	ThisHasGoneTooFar.png
Views:	1
Size:	250.6 KB
ID:	1130436
      I'm still confused about how the last index is always over whatever number I put in there. But the thing that confuses me the most is this:
      Click image for larger version

Name:	oh no.png
Views:	1
Size:	839.4 KB
ID:	1130437
      Click image for larger version

Name:	oh no.png
Views:	1
Size:	742.1 KB
ID:	1130438
      For some reason this works just like I wanted.
      Click image for larger version

Name:	nope.png
Views:	1
Size:	773.6 KB
ID:	1130439
      Click image for larger version

Name:	nope.png
Views:	1
Size:	757.9 KB
ID:	1130440

      I don't get how it reads all the way to player 10, but there haven't been that many items added to the array
      Last edited by mabdog; 06-29-2017, 06:42 PM.


        What seems the most interesting are:
        - OnClicked Play event. It checks if the N's textbox is enabled or not and adds to the array or not.
        -And the buttons toggles the enabled state.
        That should work, even if it might be an odd way to do it. Print the array after all that stuff is done on the OnClicked Play event to see if it in fact does not add the unwanted players.

        The issue being that the text on the right side of the screen appears even if they shouldn't, but what determines what shows up there? Is it the "get player name visibility"? If so, I would guess that it is something there that is the problem.


          I was going to simply check to see if it was visible or hidden, but since visibility is an Enum, I needed an integer for the check. I tried getting that to work but it broke the game, so I tried finding a boolean I could use instead (Is Enabled).
          And yes, the set visibility functions that I binded for every text is supposed to determine whether or not you can see the text or not. I will go through all of it to look for a mistake, but it's hard because these graphs don't seem to fire pulses for me as I'm simulating.
          Maybe I should set this up in a way so that the text doesn't even exist unless there is a corresponding index in the array. I'm not sure how to do this.
          And I shutter at the thought of actually getting these turns to play out in a proper rotation driven by how many items are in the index.
          Also, how do I print a whole array?


            Iterate through the array and print each member. It will be in reverse since new print strings appear at the top of the screen.
            I suspected there would be some turn rotation. I suggest a redesign, which I can help with a bit but it will have to wait till tomorrow.
            Practically I suggest instancing each player field, by designing a widget and just setting data inside it.

            But to show what can be done using other widgets with less code, here's an example:

            Click image for larger version

Name:	Fields.png
Views:	1
Size:	252.4 KB
ID:	1130448

            Note that while designing the field widget, you'll want to delete the canvas panel which makes it look strange, but then looks all right once the field widgets gets added to the vertical box inside the main widget.
            Note that making it look pretty is not something I am good at.


              hm.. could I possibly see the designer hierarchy for your main widget?
              Did you set up a vertical box beforehand in there that you're adding Field Widget to as a child?
              I suppose they would just be created on top of one another if you didn't do this..
              And any help is appreciated. You've already helped a whole lot !


                The main widget is just a canvas panel with that vertical box.
                Let me know what you think the next step should be. To go from the input fields, save valid player names to the players array inside the third person character and then add those to the right-side?

                Something to note here is that we will not be relying on "getting the children of the 'input fields vertical box' ". Rather, as we create the field widgets, they are saved to an array. It's this array we will be working with if we want to add or remove, or get the current player fields. We will just tell the vertical box to update visually, based on the order of that array.
                This is something I recommend doing in general since it gives better control, reduces casting (since "get child" of vertical box returns a User Widget) and generally makes coding easier.

                Updated main widget:
                Click image for larger version

Name:	Updated mainwidget.png
Views:	1
Size:	135.4 KB
ID:	1130465

                Now for sorting the valid players and passing them to the third person character. First of all, you're getting the controlled character and casting it to third person character. If you want to get the third person character again, you'll have to do the same thing again. It's not that it's some expensive operation, it's that it adds clutter the blueprint. There are two ways to do simplify this; if your thirdpersonchar is creating the widget, then:
                Inside the widget create a new variable. Make it type third person character (reference) check the boxes "instance editable" and "expose on spawn". Then go to the thirdpersonchar where you create the widget, and input a "self" node into the new input.
                The other way, is to do the "get controlled character -> cast to thirdpersoncharacter" and save the return value to the variable, or right click it and "create variable". This could be done on the construct event of the widget.

                So, when the play button is pressed, add the valid players to the character array. Looping through the array of player fields, check their player valid and add the name to the array. But how do we get the name from the field? We could "get editable text box" from the array and "get text". Or we can create a new function inside the field widget that returns the name. That way, if you ever want to change how the text is stored, you don't have to go to the main widget and find all the places that you did this, but instead just update what the function returns.

                Click image for larger version

Name:	add player names.png
Views:	1
Size:	110.9 KB
ID:	1130466

                As a last note, there are a lot of improvements that could be done to the above. This is really just to show some methodology. Like the "make literal string". It works, but it may be better to replace it with a string variable so you can easily change what is displayed, rather than diving into the blueprint setup, looking for where this literal string could possibly be. (all variables can be seen in the "class defaults" tab). Or, instead of cluttering the event graph with nodes, put those nodes into functions with good names. Speaking of good names, "update vertical box" is not exactly a good name, we will probably need another vertical box. So name the functions something descriptive.


                  your 'update vertical box'
                  is that a function, macro or event?
                  or something else?

                  edit: oh wait it's a function

                  I'm gonna work on this today so I'll get back to you on my progress


                    so in your first picture I'm a bit confused about "Initial Set Player Name". Is this an event? If so, what does it do?
                    And where is your variable "Player Char" coming from?

                    edit: I found the answer to my first question, I just missed that picture at first

                    edit2: figuring it out, ignore the attached image. When I create a "Players" array, there is no "target"

                    also now I'm at the point where I need to display the valid player names in my main widget. How do I get the array "players" from main widget into the new game widget for them to display? I tried casting, but I couldn't get the array

                    edit3: I figured it out. the array was set to "private".

                    edit4: well, I tried to figure it out. I basically copied what you had done earlier again. It's just not working and I'm not sure what I'm doing wrong. I just want to display the text from the Players array in this widget.

                    Click image for larger version

Name:	1.png
Views:	1
Size:	305.4 KB
ID:	1130632
                    Click image for larger version

Name:	2.png
Views:	1
Size:	252.6 KB
ID:	1130633
                    Click image for larger version

Name:	3.png
Views:	1
Size:	238.8 KB
ID:	1130634
                    Last edited by mabdog; 07-05-2017, 11:09 AM.


                      On the construct event of the "ATFYCR" class, I am creating a widget inside a loop that loops 10 times, creating each input field.
                      You are looping through an array, why is that? It should be empty, or have you added members to it manually?

                      My "play char" var was supposed to represent the third person character var that originally had the player names array. But it doesn't matter where it is located.
                      What results are you getting? Is nothing displaying? Put a print string after the cast failed, and a print string before the loop and check the length of the array. If it either fails, or the array is 0 length, no widgets will be created. I suggest you remove the cast and just use a "for each loop in range" or what it's called, the one where you put an int range like in my example.


                        I'm really just trying to get the array items from "Players" in the other widget. But I don't know how to get a reference to that.
                        I just want to display the player names on the right side of the screen. I used the foreachloop hoping that it would only create text if there is an index item in that array


                          The setup I have done, does not yet have logic for the right-side names. It's for the initial displaying of text field of player names and determining what players are valid when pressing the "play" button.
                          I thought that adding all of it may have been a bit much.
                          But sure, then the method is correct, once you are ready to display the names on the right side, loop through the array and create a new widget for each player. You may want to create a new widget class for these names, since they shouldn't be input fields. just to be clear, when you say "it isn't working", just what is not working? Nothing, or the right-side text specifically?

                          "But I don't know how to get a reference to that." I guess you mean a reference to the "other widget". You seem to already have a variable of type "other widget" reference. If you check the instance editable and expose on spawn options, go to the place where the "other widget" creates "ATFYCR" and pass in a self and that's it.
                          Or is the "ATFYCR" widget added directly to "other widgets" designer view?


                            no, your system works great for adding the characters and indexing the ones that are valid. I added a print string and it's totally great. The "Players" array has the information I want (exactly how many players there are, and all of their names)

                            I'm not exactly sure what you mean by "pass in a self". Or which variable I am supposed to check "instance editable" and "expose on spawn".

                            The reason I have a reference is because I used cast. But the compiler makes a note that I don't understand, and I'm pretty sure it's not working.
                            I just really haven't done much communicating from widget to widget so I really don't know what I'm doing here. And I can't find a single tutorial on making a turn based board game kind of game.

                            So.. when I want to get a variable (the very important "Players" array) from a different widget , what do I do? I tried casting, and "create widget" And I don't think either are working right
                            Click image for larger version

Name:	working3.png
Views:	1
Size:	193.8 KB
ID:	1130669
                            Click image for larger version

Name:	working4.png
Views:	1
Size:	221.5 KB
ID:	1130670
                            Attached Files
                            Last edited by mabdog; 07-05-2017, 11:42 AM.


                              You can right click in any blueprint and type "self", which will create a node of itself. I think it will make sense once you have the setup working.
                              You're casting a "gamestartfixed" as "gamestartfixed", which is reduntant - it is already a "gamestartfixed". What you need to do is set the variable with a reference. Which you can do like so:

                              Click image for larger version

Name:	widgetinput.png
Views:	1
Size:	47.1 KB
ID:	1130671

                              So you have that setup on construction, where I was adding player fields. So is this a new widget or what? Or is it the same place, modified. Because if it's the same place, then the array hasn't been modified yet.
                              The idea was to divide it up into three parts: one where the fields were created, left side. Then clicked play, which sorted out the invalid players adding only valid players to the array. The third part which I didn't add yet would be a new event that was called after the play algorithm was completed and created new widgets to the right side.