Is it possible to add a unit to a list more than once? and if the answer is yes, how can I prevent it, or instead of add, override it?
Thanks in advance
Is it possible to add a unit to a list more than once? and if the answer is yes, how can I prevent it, or instead of add, override it?
Thanks in advance
Yes
myList [i] = myValue ;
Prevent:
List<Whatever> list = new List<Whatever>();
[...]
Whatever newItem = blabla;
if (!list.Contains(newItem))
{
list.Add(newItem);
}
Or just use HashSet, that does not accept duplicate values.
@ ,
thx for reply bro reply, is this how you mean? Dont think I am doing it right, my list size is getting exponentially larger
if (!SelectionManager.SelectedUnitList.Contains(myUnit))
{
SelectionManager.SelectedUnitList.Add(myUnit);
count = SelectionManager.SelectedUnitList.Count;
}
@Mortalanimal are you positive that checked myUnit is same, as existing one?
Can you show more of your code?
void LoadList1()
{
if (Input.GetKey("left shift")) // I have a problem with shift... WHY????
{
foreach (Unit myUnit in SelectionManager.ctrlGroup1)
{
if (myUnit.tag == "UnSelected")
{
myUnit.SetSelector(true);
myUnit.tag = "Selected";
//SelectionManager.SelectedUnitList.Add(myUnit);
//count = SelectionManager.SelectedUnitList.Count;
if (!SelectionManager.SelectedUnitList.Contains(myUnit))
{
SelectionManager.SelectedUnitList.Add(myUnit);
}
count = SelectionManager.SelectedUnitList.Count;
}
}
}
else
{
foreach (Unit myUnit in SelectionManager.SelectedUnitList)
{
count = SelectionManager.SelectedUnitList.Count;
}
if (count > 0)
{
for (int i = 0; i < count; i++)
{
LoadList1B();
Debug.Log("Second count test ammount saved" + " " + count);
}
}
foreach (Unit myUnit in SelectionManager.ctrlGroup1)
{
myUnit.SetSelector(true);
SelectionManager.SelectedUnitList.Add(myUnit);
myUnit.tag = "Selected";
}
}
}
void LoadList1B()
{
foreach (Unit myUnit in SelectionManager.SelectedUnitList)
{
// if (myUnit.tag == "Selected")
{
myUnit.SetSelector(false);
myUnit.tag = "UnSelected";
SelectionManager.SelectedUnitList.Remove(myUnit);
break;
}
}
}
The Code works Fine, Unless I press Shift.
@Antypodish , This is for an RTS game, if I press “1”, it will deselect all units and load all the units saved in group 1, this is the same with any other number. However, if I press “Shift+1”, It will not Deselect and thus I will just make my selection bigger.
Truth is, this code is almost 1500 lines, and I am thinking Maybe I should Just skip the “shift” option, Btw the shift option actually works perfectly, but the list.count starts to get massive, after 500 units per list it starts to get leggy. I am sure I am doing something wrong. Usually I purge the lists before I add to them. So I never had this problem, but I dont think I can purge before adding 2 lists together. Thats why I needed a method to prevent me from adding duplicates in the first place which would solve the issue, if I do it right that is.
@Antypodish , I just Noticed if I press shift, it doubles the value of what is currently in the list + whatever else I add to it… hmmmm which means that this line of code is not working for sure.
if (!SelectionManager.SelectedUnitList.Contains(myUnit))
{
SelectionManager.SelectedUnitList.Add(myUnit);
}
Can you put debug log after?
foreach (Unit myUnit in SelectionManager.ctrlGroup1)
and print myUnit hash code?
I think you want to use GetKeyDown, or GetKeyUp instead Input.GetKey
But I am holding down shift?
I think I fixed the Problem, Let me just change the code one sec
You most likely don’t want to run
foreach (Unit myUnit in SelectionManager.ctrlGroup1)
every frame, when holding shift.
I fixed it, Problem was, I have been working on this for 3 days and I was just doing something stupid, the problem was with adding to the list, and yet I was trying to fix it when I call the list. LOL so god damn stupid lol
Anyway its fixed now, and this was the fix.
foreach (Unit myUnit in SelectionManager.SelectedUnitList)
{
if (myUnit.tag == "Selected")
{
if (!SelectionManager.ctrlGroup9.Contains(myUnit))
{
SelectionManager.ctrlGroup9.Add(myUnit);
}
}
}
@Antypodish @ Thx so much for your help, I believe I have now fully finished Selecting and grouping units for my RTS game. I cant believe for the life of me that this script is Almost 2000 lines. Btw I am a noob, so sorry for the trouble, you will likely see me asking more questions every day lol.
btw I dont even know what this is “and print myUnit hash code?” lol
For example
transform.GetHashCode () ;
Is Unique reference for the object. In this case transform of GameObject. It returns int. Technically no other object should have same HashCode. At least not for the same type.
AHH!! interesting, though tbh, I only had like 10 units in my scene, and in my list it was growing to over 500 lol, so it was obviously adding lol. the thing is, I never noticed this before because visually the game was working well and doing exactly what I wanted it to do. I just noticed it due to lagg, so I started investigating.
First of all, glad you got it working. A few notes though.
So you say you only had 10 for testing, yet it already started lagging with the bug which led to hundreds of entries in the list…
What if you actually want hundreds of units later?
One thing is that you should use the method .CompareTag when you compare tags, because unlike direct comparison using .tag == “xyz”, it does not need to allocate a new string each time.
Next, when lists grow, the “Contains” function can be suboptimal, as it has a time complexity of O(N). That is, in the worst case, it has to do N comparisons where N is the number of entries.
Taking this into account, the complexity of the whole selection logic ends up being even worse, because you will need to compare every currently selected unit against the ones that exist in the list.
Instead, you can take a look at hashsets. They’re a collection type with a lookup time complexity of O(1), because they work much differently.
This is especially important when you have many units in your game.
Also, i suspect that you’ve written that code for all your control groups, in which case I’d highly recommend to take a look at arrays and I’d build a custom type for such control groups. These types would encapsulate the actual collection and everything else that logically belongs to them, so that your calling code only calls “add” without doing all the detailed work on its own.
Generally speaking, 2000 lines for that sort of thing is quite a lot.
Yeah, use Sets if you don’t want duplicates. That’s what they’re designed for. And HashSet is fast.
Thank you for all the tips, Might take me a while to learn everything you suggested. However, I was wondering what you think of using Enums instead of Tags? in terms of performance. But on all of the other points you made, I would have to do a lot of research to understand what you mean and how to implement it. I am still very new at all this.
never the less, I highly appreciate your guidance
Using enums is less error prone.
With tags, you need remember to set objects’ tags.
If you do it programatically maybe not that big deal.
But if you do manually set tags, then is easy to forget add relevant tag. Specially when you move asset to new project, or you decide come back to project few months / year later.
You can have also only limited number of tags.
Enum is just int representation. Is easy to search references rather than searching for strings, if decide to look for tags by string, rather than index. But that is another can of worms to be opened.
Personally I use only tags at prototyping stage, if at all. Then trying to remove any reference to them, as soon as possible.
Maybe for tiny projects tags are convenient.
GameObject components could be used as tagging mechanics as well.