ArgumentException:Does not implement right interface (List.Sort error)

Hey. Guys. I’ve been working on a script to access each GameObject enemy in the scene and store their initiative rolls to sort for a turn order. I made a script here and have been working on this issue for around a week and am very stuck. InitHolder script is attached on each GameObject enemy I have in the scene and InitMasterCs is attached to one empty gameobject in the scene. It all compiles, but when I run the game, it throws this error:

ArgumentException: does not implement right interface
System.Collections.Generic.Comparer1+DefaultComparer[UnityEngine.GameObject].Compare (UnityEngine.GameObject x, UnityEngine.GameObject y) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Collections.Generic/Comparer.cs:86) System.Array.compare[GameObject] (UnityEngine.GameObject value1, UnityEngine.GameObject value2, IComparer1 comparer) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System/Array.cs:1744)
System.Array.qsort[GameObject,GameObject] (UnityEngine.GameObject[ ] keys, UnityEngine.GameObject[ ] items, Int32 low0, Int32 high0, IComparer1 comparer) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System/Array.cs:1721) System.Array.Sort[GameObject,GameObject] (UnityEngine.GameObject[ ] keys, UnityEngine.GameObject[ ] items, Int32 index, Int32 length, IComparer1 comparer) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System/Array.cs:1674)
Rethrow as InvalidOperationException: The comparer threw an exception.
System.Array.Sort[GameObject,GameObject] (UnityEngine.GameObject[ ] keys, UnityEngine.GameObject[ ] items, Int32 index, Int32 length, IComparer1 comparer) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System/Array.cs:1677) System.Array.Sort[GameObject] (UnityEngine.GameObject[ ] array, Int32 index, Int32 length, IComparer1 comparer) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System/Array.cs:1623)
System.Collections.Generic.List`1[UnityEngine.GameObject].Sort () (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Collections.Generic/List.cs:568)
InitMasterCs.Start () (at Assets/Scripts/InitMasterCs.cs:21)

ALSO: When there is only one enemy in the scene, no error is thrown and the single initiative roll is indeed visible in the console log.

Here is the InitHolder Script:

using UnityEngine;
using System.Collections;
using System;

public class InitHolder : MonoBehaviour, IComparable<InitHolder> {

	public string name;
	private int intBonus = 3;
	public int initRoll;

	public InitHolder()
	{

	}
	
	// Use this for initialization
	void Awake () {
		initRoll = intBonus + UnityEngine.Random.Range (1,20);
	}
	
	// Update is called once per frame
	void Update () {
	
	}

	public int CompareTo(InitHolder other)
	{
		if(other == null)
		{
			return 1;
		}
		
		//Return the difference in power.
		return initRoll - other.initRoll;
	}
}

And here is the InitMaster Script:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;


public class InitMasterCs : MonoBehaviour {
	private InitHolder initHolder;

	// Use this for initialization
	void Start () {

		GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
		List<GameObject> badguys = new List<GameObject>();

		foreach(GameObject guy in enemies){
			badguys.Add(guy);
		}

		badguys.Sort ();

		foreach(GameObject guy in badguys){

			print(guy.GetComponent<InitHolder>().initRoll);
		}
	}
	
	// Update is called once per frame
	void Update () {
	
	}

}

GameObject doesn’t seem to implement any usable sorting interfaces.
I see you have implemented a sorting interface for InitHolder but you are not sorting a list of InitHolder.

Is this what you were trying to do in InitMasterCs?

public class InitMasterCs : MonoBehaviour {
	void Start () {
		GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
		List<InitHolder> holders = new List<InitHolder>();
		
		foreach(GameObject enemy in enemies){
			InitHolder holder = enemy.GetComponent<InitHolder>();
			if (holder != null) holders.Add(holder);
		}
		holders.Sort ();
		
		foreach(InitHolder h in holders){
			Debug.Log (h.initRoll);
		}
	}
}

Hey! I actually realized this, as well. I hate to make a post and then figure out myself later - but seriously I waited a week to do this I just kinda finally figured it out.

Yes - I realized that error that you are saying and you are completely right.

Then I realized that to fix this - I’m going to need to write a custom sort method (manual code sort).

So I stole an algorithm I found, tweaked it - and now here is the successful script.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;


public class InitMasterCs : MonoBehaviour {
	private InitHolder initHolder;
	InitHolder temp;

	// Use this for initialization
	void Start () {

		GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");

		selectionSort(enemies);

		for(int x = 0; x < enemies.Length; x++){
			Debug.Log("enemy[" + x + "] InitRoll: " + enemies[x].GetComponent<InitHolder>().initRoll);
		}



	}
	
	// Update is called once per frame
	void Update () {
	
	}
	
	public GameObject[] selectionSort(GameObject[] data){
		int lenD = data.Length;
		int j = 0;
		GameObject tmp;
		for(int i=0;i<lenD;i++){
			j = i;
			for(int k = i;k<lenD;k++){
				if(data[j].GetComponent<InitHolder>().initRoll<data[k].GetComponent<InitHolder>().initRoll){
					j = k;
				}
			}
			tmp = data[i];
			data[i] = data[j];
			data[j] = tmp;
		}
		return data;
	}
}

The Important part here is that my final array contains the enemy gameobjects themselves - SORTED by their initiative rolls.

This script does indeed log in my console correctly with multiple enemies in the scene - sorted from highest roll first (gameObject[0]) and lowest roll last.

Now I can send events to each enemy in the array in sequence when it’s their turn.

Hooray.

I figure this might be a good reference for a lot of people though - as I find sorting a gameobject array by a value on each gameobject’s script quite frustrating/brutal/difficult/extensive/rewarding.

Agh, so happy now.

Thanks for the reply.