Using C# classes from Javascript

I’m attempting to write a Race script (which has been written in Javascript), which needs a sorted list of RaceStat objects, a custom class I wrote. The simplest way to do this is through Array.Sort(), which requires that <> operators be overridden (I assume).

So in order to accomplish that goal, I wrote RaceStats in C#. However, no matter what I do, Race.js refuses to accept RaceStats as a valid type. Is there some inter-language issue happening here? (If so, the fact that I have always been able to use Mathfx.cs functions from Javascript would now confuse me.)

  1. To my knowledge Javascript does not have the ability to override operators; is this correct?
  2. Is it possible to use C# classes within Javascript?

You can use your user-created C# classes from JavaScript, you just need to make sure the C# script is compiled before the JS script trying to it.

The compilation order is here: http://unity3d.com/Documentation/ScriptReference/index.Script_compilation_28Advanced29.html

So basically you need to put the C# classes you’d like to use from JavaScript in the Standard/Pro Assets folder or the Editor folder.

Unity Javascript can. You basically need to define a static function called op_NameOfOperator. Example:

class myNum {
	var i : double;
	function myNum(j : int) {
		i = j;
	}
	function myNum(j : double) {
		i = j;
	}
	static function op_Multiply(x : myNum, j : int){
		return new myNum(x.i * j);
	}
	static function op_Multiply(x : myNum, y : myNum){
		return new myNum(x.i * y.i);
	}
	static function op_Addition(x : myNum, j : int){
		return new myNum(x.i + j);
	}
	static function op_Equality(x : myNum, y : double){
		return x.i == y;
	}
	static function op_UnaryNegation(x : myNum){
		return new myNum(-x.i);
	}
	function ToString(){
		return i.ToString();
	}
}

var a=new myNum(8);var b=new myNum(2);
Debug.Log((a+2)*b);

The available operator function names are:

op_Addition
op_Subtraction
op_Multiply
op_Division
op_Modulus
op_Exponentiation
op_Equality
op_LessThan
op_LessThanOrEqual
op_GreaterThan
op_GreaterThanOrEqual
op_Match
op_NotMatch
op_Member
op_NotMember
op_BitwiseOr
op_BitwiseAnd
op_UnaryNegation

When you overload a binary arithmetic operator such as op_Addition, the corresponding assignment operator ( += ) is overloaded too.

Thanks freyr. The operator methods do (seem to) work; I compare the RaceStats of the most recent run to that of the best run without any errors.

Unfortunately, when I try to sort an array of them, it throws:
Cannot cast from source to destination type

I’ve overridden all the operators that would be needed for sorting, I think. Are there any more that need to be overloaded? Or is Array.Sort just broken for nonstandard types?
Race.js snippet:

	var orderedStats = new Array();
	orderedStats.Add(lastRunStats);
	
	for (o=0; o < opponentNames.length; o++) {
		if (o < opponentLapTimes.length) {
			opponentStats[o] = GenerateRandomStats(opponentNames[o], opponentLapTimes[o], opponentLapVariation);
			orderedStats.Add(opponentStats[o]);
		}
	}
	orderedStats.Sort();//error here

RaceStats.js snippet

static function op_Equality (x : RaceStats, y : RaceStats) {
	return (x.raceTime == y.raceTime);
}

static function op_LessThan (x : RaceStats, y : RaceStats) {
	return (x.raceTime == y.raceTime);
}

static function op_LessThanOrEqual (x : RaceStats, y : RaceStats) {
	return (x.raceTime == y.raceTime);
}

static function op_GreaterThan (x : RaceStats, y : RaceStats) {
	return (x.raceTime == y.raceTime);
}

static function op_GreaterThanOrEqual (x : RaceStats, y : RaceStats) {
	return (x.raceTime == y.raceTime);
}

Actually implementing the comparison operators will not help you. For Sort to work, you need to make your class implement the IComparable interface, which consists of a single method, CompareTo:

class RaceStats extends IComparable {
  
  var raceTime : float;
  
  // ...

  function CompareTo(obj: Object) : int {
     var other :MyClass = obj; // Typecast to own class
     return raceTime.CompareTo(other.raceTime);
  }
}

If you for some reason can’t make your custom class implement IComparable (f.ex. if it’s a MonoBehaviour), an alternative is to create a helper class that implements IComparer and pass an instance of it to the Sort function.

class RaceStatsComparer extends IComparer {
  function Compare(x : Object, y : Object) : int {
      x.raceTime.CompareTo(y.raceTime);
  }
}

...
myArray.Sort(new RaceStatsComparer ());

It wooooooooooooooooooooooooooooooooooorks! :smile:

ahem Er. Yeah. Thanks. :slight_smile:

More info on this here.