#List, Find and Lambda Expressions
1 messages · Page 1 of 1 (latest)
Nice
List.Find() uses something called Lambda expressions
Example:
var found = myList.Find(x => x.name == "Bob");
For advanced cases, multiple variables (x,y) can be used.
I forget what was a good example for that.
So regarding Arrays and Lists, some basics, just to make sure you have it all covered:
Arrays and Lists must be initialized before they can hold items.
An array must be initialized with a fixed number of item slots.
Arrays cannot be resized. They must be reconstructed.
// Initialize empty or with hardcoded values
string[] myStrings = new string[3];
string[] myStrings = new string[] { "Hard", "Coded", "Values" ;}
__A List __ just needs to be initialized with the correct type.
It's size is dynamic, and you just use .Add() .Remove() methods to manage its items.
List<string> myList = new List<string>();
A List can also be initialized with an existing array
string[] myStrings = new string[] { "Hard", "Coded", "Values" ;}
List<string> myList = new List<string>(myStrings);
Finally, you can make a list into an array by myList.ToArray()
Do you know how to loop through a list?
I can also stop overexplaining and get to the point, if you feel that's better.
Well I dont quite know how you mean loop through it, maybe you meant in different context but the only way I know how to loop for now is just to create a bunch of new indexes in lists. If ofcourse this is correct way to insert them into the list, not sure:
In this case I have 31 items and I all inserted them in a list through a loop so I can access them later. Sorry I am really new at this this programming this is really hard for me but I want to learn it
No its okay, I would like to know everything to be honest
That's alright. I felt the same a few years ago.
in Visual Studio, write for and click Tab twice
it should auto-complete a standard for-loop.
Paste the for() -line here, so I can see the expression.
Didnt know about the double tab feature, good to know. This is what you mean right?
The only thing you change in that thing is length
if it's an array: myArray.Length
if it's a List: myList.Count
as long as it is i < length
you don't need to offset the index
(if Count is 10, the highest index is 9, because index starts at 0)
Length or Count = Number of items
_
In the first loop you posted you are using Lista to iterate the loop
But the power of the for-loop is that it comes with a local variable, and it is all defined on a single line.
local variables only exist inside their parent method
and they are faster to access than the other variables, which are called fields
_
fields are stored in the heap
local variables are stored in the stack (faster memory)
private int field = 0; // Heap
private void Awake()
{
int local = 0; // Stack
}
Fixed*
ok so if i understand this correctly local variable in this case would be "i" and its used inside the for loop only? This "i" is what I mean in the picture below:
In this case I dont have to actually assign Lista I can just assign some local variable and use it inside the for loop if I understood everything correctly
Yes, but you only ever need i
You can have 100 for-loops in the same method, all using i
because it is exclusive to themselves
Normally, in a while loop, you couldn't do that, because if you define a local variable inside the while loop it will just reset every round
That is why they made the for-loop, to take advantage of this practicality.
if you nest for loops. you'll need a different iterator identifier
Later on you can explore foreach
As long as you're not doing things that require math working with the value of i
If you need to sort a list, I recommend using the System.Linq namespace to enable Linq extensions.
Then you can do myList.SortBy().ThenBy()
Anyway. That's a lot of information to absorb.
Do you have any other specific questions?
(Fixed some code examples above.
I was making Lists with no names :P)
List<string> = new List<string>(myStrings); // Was wrong
List<string> myList = new List<string>(myStrings); // Correct
Forgot to add this:
// Last index
array[array.Length - 1]
myList[myList.Count - 1]
Yes it indeed is but I wrote it all down so its not wasted knowledge :D.
Well now I understand it better than I did before thats for sure.
So to access the actual item like you said I use .Find() function in this case right? So if I want to for example delete the gameObject tied to the list thats the way to do it?
You can do it either by [index] or Find
Beware you cannot delete multiple items as you are looping through the same list
Because deleting an item will shift the items, and might disturb some other internal logic.
Maybe there is a way 🤔
Use Debug.Log to figure it out as you go along. You got this :)
I'll keep an eye on this thread for a while.
Come back if you get stuck.
(Mind it's Saturday, so anything can happen)
you can sure. but this list is not tied to any game object
its just a list of strings
Perhaps we should take a look at your current example
Oh I see, thats unfortunate that it shifts I guess I will have to figure it out somehow. Maybe then I will just change its color template to invisible from 255 to 0 maybe thats a better solution.
Thanks man, I really appreciate your time. Thats amazing the stuff you told me, its hard to find all that online, only in bits and pieces that you have to connect together yourself. I really really appreciate your help. Cant thank you enough.
Well what im doing at the moment is basically a health bar and a sprint bar. As you can see each bar contains atleast 32 smaller bars (red and green ones). So now im currently just at the health bar and I want to make a list of all those bars which are all game objects manually copy pasted into scene. Now this is around 32 objects and I have to add them to the list and then delete them when the character gets hit. I think I will just change the colors of the bars to invisible in this case not actually delete them because later I will also implement health packs which I will pick up to regain health.
One question. How do you know who to explain stuff so that the knowledge you tell is not wasted. I imagine atleast 90% of the game developers quit in the first week or so because its overwhelming and they dont know how to get to the knowledge properly. Most of them are just watching tutorials which they copy from and learn nothing.
I think a good recipe is just to do some basic tutorials and then start talking with people in Discord as you fix each thing, one by one.
Having a mentor is valuable. Not everyone has one, so Discord and people with free time (who were also helped once) is the next best thing. And you get the benefit of multiple perspectives.
Learning basic C# first is best. You should join the CSharp discord (can't link it here, because spam bots).
Learning to explain things is difficult.
But I found one clue to easier learn things myself, is to think with the correct words, so that the language starts making sense, and my sentences (code ideas) complete themselves.
You can practice this easily by spending time to thoroughly explain your issue from top to bottom, in a single condensed post (as I've seen you do).
Many times this has helped me solve the problem and just deleting my post, or not posting at all.
You're welcome.
I also struggled with Lists in the beginning. It's always nice to help a fellow game dev.
--> Health Bar
Destroying game objects creates garbage (literally, the garbage collector has to clean it up; bad for performance)
And since you will be needing them again, you can just make them invisible, or use gameObject.SetActive(false)
You can have literal tens or hundreds of thousands of game objects in your scene at the same time.
So don't worry about performance until it becomes an issue.
If they were bullets, you would make an object pooling system.
Which means you keep a List of the items as you spawn more (or a set amount), and disable them until needed again.
Do you have an idea for how to get the smaller bars in a list?
Only manually by copy pasting, is there any other better way?
Or do you mean like in a list on script?
The smaller bars are child objects of a parent, right?
you can put a script on the parent
or identify the parent in another script
and use myParent.GetComponent__s__InChildren<GameObject>();
I see. I will try that solution.
There are a couple of things to note
By default, it does not include inactive game objects
but you can make it ...<GameObject>(true)
Plus, an annoying thing about GetComponentsInChildren, is that it will also include the parent 🤦
That is where foreach can be a solution
(You can just code for ignoring or removing the first/parent)
// Inspector drag-n-drop
[SerializeField] private Transform parent;
private List<Transform> children;
private void Start()
{
children = new List<Transform>();
foreach (Transform child in parent)
{
children.Add(child);
}
}
Type fore and Tab twice for auto-complete
It is worth to note that if you are working with more components than just Transform or GameObject,
for example Rigidbody, or a Script, then it is best to Get that component instead.
Because any component on the object can reference both .transform and .gameObject
Thus, if you do GetComponentsInChildren<Rigidbody>();
it will only add the objects that actually have a Rigidbody (often ignoring the parent)
So I figured it out but now I have another problem. Why is it saying this. I am just trying something out if it would work like this but it gives me this error but I dont know why
I am doing it completely different, just found another way of doing it 😛
Make a pastebin link :)
https://gdl.space (CTRL+S and copy URL)
So by this logic it should erase all my bars but it gives me error instead.
And dont mind the Healtbar game object i just have it there since the begining for no reason. Thought I would need it at some point but I didnt
Add this Debug.Log to your first loop
on the Last Line
Debug.Log(gameObject.transform.Find($"Health Bar_Bar ({Lista})"))
let me know what it says
It gives me objects from 1 to 31
From 0, I just said from 1 because I have it named (1) first and so on
But the first one is Null tho
Alright, good. You can remove the debug log.
Make a new one in the second loop:
Debug.Log(HealthBarList[i].GetComponent<Image>());
Doesnt give me other than this, i tried putting it infront and behind the line inside the second for loop and nothing happens just this error.
Hm. Try moving the initialization of your list from the variable declaration, to the beginning of Start()
By the way, if you need another script to access the list, then it should be public.
But since you don't need to expose the list to the inspector, you should add the attribute [HideInInspector]
or make the list private (only private, derp)
[SerializeField] private or just public will expose the field to the inspector
Thats what you mean right?
Ok, noted. I dont need it here tho I believe, nothing to hide or to put in the inspector. Unless you mean GameObject HealthBar. But I didnt know that so its good to know.
Not precisely. That would work for testing.
But you also made the list a local variable, which means you can't access it from outside the script, or other methods.
You can simply declare a list, and initialize it later:
private List<Transform> HealthBarList;
private void Start()
{
HealthBarList = new List<Transform>();
}
Between the loops, do this:
Debug.Log(HealthBarList.Count);
Ah, I think I see the problem
Game Objects in a Canvas have their Transform component swapped out by RectTransform
I believe your list either does not add any items, or it adds items with null values
Change the type of the list from Transform to RectTransform
Oh thats also neat and good to know I thought it had to be written together like that. Looks cool tho that I can see lists in the inspector, will use that feature for sure.
I also noticed it doesnt add anything to list element number 0 so you might be correct that it doesnt add any items. Maybe the element 0 is screwing it up?
I will change it in a second
you were indeed correct. Changed it from 0 to 1
Wait, I'm confused, which 0 ?
This one. I think I had 1 too many items
Yeah silly me its 0 it starts with
no wonder such a stupid mistake
ah, your Object NAMES start with 1
Thanks man, I appreciate sticking with me on this one I would spend ages figuring this out.
Yes before the underlined part was 0, which menas 31 items with 0 included, so now I just moved one number up and it started with 1. I have it on 0-30 right now to make it less confusing but yes the original problem was my stupid mistake of forgeting the list starts with 0 as a number and not 1
Tip: Only use < in the expression, not <= unless logic dictates it is required.
Stick to the standard, and you won't have to remember twice the amount of logic.
(from experience)
Ok, noted
right now it works, so don't break it again lol
this has been long. I've been out and around town, and its still on-going
Will try not to, even tho I dont promise anything. 😛
I am doing backup copies everytime I discover something important just in case if I fuck it up so I think im safe at the moment
Ah no we just started up again :)
Yes I had a silly mistake going on in my script so I asked again. Anyway will try not to bother you guys anymore I feel silly already asking so many questions but to be honest dont know where to go otherwise 😛
Notepad++ is pretty neat for chaotically throwing code somewhere safe
It keeps all open and unsaved documents even if you close the program.
We come here to help people.
Just be glad you're not like some of the other people around here, or we would not have bothered as much
I mean people who are outright non-friendly
Yeah man kindness is the key in society but saddly it lacks in our current society, it used to be better back in the days. I am pretty sure I know what the problem is in terms of why they are not friendly enough.
There are many good people.
The other ones are just louder.