Hello,
My first post here
I’m doing a RTS game as a project for my college and I’ve had really hard time (and still have) finding tutorials that are good and up to date (at least for 4.5 even though I work with 4.6). Any good up to date tutorials you know I’d like to know too.
Anyways here are some problems that I had and my solutions to them. Of course these are my versions to some unresolved or poorly resolved solutions I’ve found online. I hope my insights could help other programmers in the future. In no particular order:
Problem 1: Like in Blizzard’s and Westwood’s (RIP) games among other, the player have the option take select at least 1 unit or building and assign them to a group with CTRL+# and then he can make quick selection by pressing said number.
Solution: Contrary to advices I’ve been given, I will not save the current selection nor the groups with Lists or Arrays but with HashSets. The class handling this should have:
//holds the currently selected units
//used everywhere. HashSet is better than list in performance and prevents duplicate selections and other future unsafe operations
public static HashSet<GameObject> selectedUnits = new HashSet<GameObject>(); //currently selected
public HashSet<GameObject>[] groups = new HashSet<GameObject>[10]; //saved selections
Then in OnGUI (no use to use in Update when it could be better to run this only when a number is pressed):
private void OnGUI()
{
DrawRect(); //draws the rectangle
GroupHandler(); //saves selections to numbers and selects groups by numbers
}
void GroupHandler()
{
//group selection
//better performance to call the method only when a relevant key is pressed and not on every OnGUI call
Event e = Event.current;
if (e.isKey)
{
if (e.ToString().Contains("Alpha")) //true only if 0-9 above the letters are pressed
{
int groupNum = int.Parse(e.keyCode.ToString().Substring(5)); //gets the number that was pressed
//if (Input.GetKey(KeyCode.LeftControl)) ///////////////////////&&&&&&&&&&&&&&&&&&&&&&&&&&&&&///////////////////////// not working in the editor
if (Input.GetKey("a")) //form group mode. saves current selected units to the number press if CTRL is held with the number
groups[groupNum] = new HashSet<GameObject>(selectedUnits);
else //select group mode. if CTRL is not pressed then discard current selection and select group at number instead;
RePopulateSelection(groupNum);
}
}
}
void ClearSelection() //safely(!!!) deselects all units in current selection
{
HashSet<GameObject> oldSelection = new HashSet<GameObject>(selectedUnits);
foreach (GameObject unit in oldSelection)
{
unit.GetComponent<unit2>().SetUnselected();
}
}
void RePopulateSelection(int groupNum) //change current selection to the selected group
{
ClearSelection();
foreach (GameObject unit in groups[groupNum])
{
unit.GetComponent<unit2>().SetSelected();
}
}
void KillUnit(GameObject unit)
{
for (int i = 0; i < 10; i++) //to prevent exceptions while selecting or ordering a non-existant unit
{
groups*.Remove(unit); //no exception thrown upon trying to remove item that was not in the hash set*
}
// check info
// update scores
// preform aditional operations here or in its script
unit.GetComponent().SetUnselected();
//kill unit now;
}
Why Hashset?
PROS: At worst case at adding and removing units from the selection/group is like list or array with the pro of a list (against array) that there’s the almost minimum of memory alloction (I don’t know for certain how Unity deals with it but it’s still better than allocting array and slightly worse than list at worst case). Both actions amortized are O(1).
CONS: When deselecting safely all the units you can’t use iterator that can remove and move on like in list so additional memory is required (unless you know a trick that won’t throw run time errors).
Other improvements can still (and will be) made. That file is only for prototyping.