Sorting an array based on position
Hey guys, This has been bothering me for a while now so I finally decided that it was time to ask for some help.
I'm making a game where the goal is to stack up shapes the highest possible without them falling down, and at the moment I'm working on the score system. My idea is to use the array that holds all of the shapes(Once instantiated), sort the array based the the GO's position on the Y-axis, and get the position of the last object in the array. But the problem is that I can't figure out how to sort the array.
Here is what I've got so far(not the full code, but this is the only part of the script that is relevant):
public GameObject[] quads;
void Update(){
quads = GameObject.FindGameObjectsWithTag("quad");
}
Edit I've also tried this:
public GameObject[] quads;
public GameObject[] quadPos;
void Update(){
quads = GameObject.FindGameObjectsWithTag("quad");
quadPos = quads.OrderBy(quads => quads.transform.position.y).ToArray();
}
But that gives me an error:
error CS0135: `quads' conflicts with a declaration in a child block
If you guys have any ideas I would really appreciate it!
Answer by fafase · Jun 23, 2014 at 06:15 AM
So you can use the Sort method but here is your error.
First, you need to add
using System.Linq;
You might have it already or the error is about to show once you fix your error.
The compiler tells you you have a conflict in a child block. The child block happens to be the inner methods run by Linq.
quads.OrderBy(quads => quads.transform.position.y).ToArray();
the OrderBy method will declare a variable that you tell to be called quads and this is conflicting with your previous quads declaration.
So you need to change that new naming:
quads.OrderBy(quad => quad.transform.position.y).ToArray();
And that should do it. Nonetheless, Linq is not recommended in the Update, Linq is handy but it also uses more memory and computation that a sort method.
You could limit the computation by only calling the method every x second with InvokeRepeating for instance and if you do not add any new quad then no need to call the FindObjectsWithTag other than in the Start.
void Start(){
quads = GameObject.FindGameObjectsWithTag("quad");
InvokeRepeating("OrderQuad", 1f, 1f);
}
void OrderQuads(){
quads = quads.OrderBy(quad => Vector3.Distance(transform.position, quad.transform.position)).ToArray();
}
This will call every second, also, the OrderBy method is using the distance between the object holding the script and the objects from the quads array. Change the Distance if it is not what you needed.
Answer by Jeff-Kesselman · Jun 22, 2014 at 08:46 PM
Googling "C# Array Sort" quickly finds you your answer
Like this
private int CompareYPos(GameObject a, GameObject b) {
return $$anonymous$$ath.Sign(a.transform.position.y - b.transform.position.y);
}
void Update() {
quads = GameObject.FindGameObjectsWithTag("quad");
Array.Sort(quads, CompareYPos);
}
It would probably easier to iterate over the array only once and just return the GameObject
with the highest transform.position.y
, though.