Having trouble using System.Array.Sort, please help!

G’day lads. I’ve just finished writing my first ever A* pathfinding implementation for a project I’m working on, in UnityScript. It returns paths, but rarely the most efficient, because I need to sort the ‘Open List’ by their ‘G Cost’.

At any rate, I’m trying to sort an array of GameObjects by a numeric value in an attached script that they all share. I’ve read all the other threads on using System.Array.Sort, and based my attempt off those, but I get the error “No appropriate version of ‘System.Array.Sort’ for the argument list ‘(Array, function(Object): int)’ was found.”

Here’s the code that calls the sorting function:

openList.Push(neighbor);
System.Array.Sort(openList, Comparison);

…and the sorting function itself:

function Comparison(x) :int  {
	var y = x as GameObject;
	var Sorted = y.GetComponent(Tile).g;
	return Sorted ;   
}

Sorry if the current function looks ridiculous, but I’ve tried just about every possible combination I could think of. If any of you could point out where I’m going wrong, you’d make my Sunday a lot easier.

Cheers,
-Stew

It looks like you are using the JS Array class, which you should not use. It’s slow and obsolete, and can’t work with System.Array.Sort, which is only for .net arrays. e.g., var foo = new int[100];. If you need an array where you can easily add/remove items, use a generic List, which can use List.Sort. Also you must always supply the type for variables in function definitions.

function Comparison (x : GameObject) : int {

–Eric

Interesting. Is there a chance that UT replaces the internal implementation of UnityScript.Lang.Array with one based on System.Collections.Generic.List. ? There is a large amount of projects and libraries based on US, and if parts of the language start becoming obsolete at some point we won’t be able to use US anymore. Javascript-like Arrays are very handy, don’t let them die.

I’ll add this to the wish list.

No, that’s not possible. Just use List.

Most don’t use the JS Array class, since there’s no reason to use it when there are plenty of faster/better collections you can use.

–Eric

Thanks guys, I’d worried that it seemed a little slow. Once I have the openList sorting correctly, I’ll begin replacing all the arrays I use in the project with the right collection for the job. Unfortunately I still haven’t got it working yet. I’ve replaced the array with a generic list, that looks like:

var openList = new List.<GameObject>();

And since I can’t use .Pop, .Push etc. I replaced those instances with .Add and, since there’s no equivalent to Pop, replaced it with:

var length = openList.Count;
var currentNode = openList[length] as GameObject;
openList.RemoveAt(length);

Now the call to Sort and compare function look like:

System.Array.Sort(openList,Comparison);

…and

function Comparison (x : GameObject) : int {
	var sorted = x.GetComponent(Tile).g;
	return sorted;   
}

I still receive the error "No appropriate version of ‘System.Array.Sort’ for the argument list ‘(System.Collections.Generic.List.<UnityEngine.GameObject>,function(UnityEngine.GameObject): int)’ was found.

Should I be using something other than System.Array.Sort now I’m using a Generic List?

Yes, you should use List.Sort.

 openList.Sort(Comparison);

Also, I should have seen this before, and I don’t know what GetComponent(Tile).g returns exactly, but the way sort functions generally work is to compare two items and return -1, 0 or 1. For example, a function used to sort a List of GameObjects by their x positions:

function SortByX (go1 : GameObject, go2 : GameObject) : int {
	if (go1.transform.position.x > go2.transform.position.x) {
		return 1;
	}
	else if (go1.transform.position.x < go2.transform.position.x) {
		return -1;
	}
	return 0;
}

Naturally that would be used in the same way, namely

gameObjectList.Sort (SortByX);

–Eric

Ok, now the console’s returning no errors, and I’m able to execute the code. It crashes Unity, at the moment, which is usually an indication that a loop is fubar. It seems to be my substitute for .Pop (where I return the length of the list - 1 and use that to get the last item). Is there no better alternative to returning (and removing, ideally) the last item in a generic list?

Actually the code you posted above wouldn’t work as a Pop replacement, since you’re using Count instead of Count-1. Also you don’t need to cast, since a List of GameObject is already typed as GameObject.

var currentNode = openList[length];

is fine. If you already fixed the Count-1 thing, perhaps you’re not using Count in the loop?

–Eric

It very well might be the issue, but removing the compare discussed earlier allows me to at least generate a horrible path (first-come-first-serve, lots of zig-zagging). I think it could be how I’m dealing with the List somewhere else even. I’ve thrown the script on a server of mine, as pasting in 100 lines of code is just awful, but I think it’d help to look at it in context.

Please excuse the state of it, I tend to build something horribly until it’s functional, and then rebuild it in iterations as I learn what’s necessary and what isn’t. Expect ugliness of biblical proportions.

http://www.auzart.com/misc/PathFinder_01a.js

Hi Stew,

Path finding isn’t that simple :slight_smile: Anyway, why re-inventing the wheel? Unity has now an goodintegrated path finding system. For Unity Free I strongly suggest to use this one: A* Pathfinding Project. The free version of this is more than enough to solve a lot of pathfinding related problems; the paid version is just great (I actually use that instead of the Unity built-in pathfinding!).

Cheers, you’re spot-on mate! I’m working towards a Turn Based Strategy game, and pathfinding is a critical foundation for this genre, so I should definitely do whatever it takes to make sure the pathfinding is fast, efficient and flexible.

I’ve actually decided to make the switch to C# recently. I’m a front-end web developer by day, so I find it tricky getting out of the ‘real’ javascript mind-state when working in Unity. I’ve been working through my own square-tile implementation of what I’ve learned from an excellent tutorial here.

Glad to help :wink: Switching to C# is indeed an excellent choice, there is nothing better to get professional grade code… US is too limited and anyway implementing an advanced external library to speed up computational tasks means to write C# DLL, so it’s the way to go :wink: