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.”
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.
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.
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.
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?
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
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?
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.
Path finding isn’t that simple 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 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