Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
4
Question by laoril · Mar 19, 2013 at 01:00 PM · gameobjectlistinterfacesort

Problem using IComparer to sort list of GameObjects

Hello everyone,

I've been trying to understand how to sort a list of GameObjects by a custom attribute, but without success so far. I must be doing something wrong. I'm trying to do this for a* pathfinding. I have a list of tiles, each with F, G and H scores. Now I want to sort them by F score, so, in my class TileStatus attached to the Tile GameObject I have this :

 using UnityEngine;
 using System;
 using System.Collections;
 
 
 public class TileStatus : MonoBehaviour,IComparable {
     
     public double F;
     public double G;
     public double H;
     public GameObject parent = null;
     
      int IComparable.CompareTo ( object obj)
     {
         TileStatus tile = ( TileStatus )obj;
         if ( this . getFScore()< tile . getFScore() )
         {
         return -1;
         }
         if ( this . getFScore() > tile . getFScore() )
         {
             return 1;
         }
         else
         {
         return 0;
         }
     }
     
     public void setParent(GameObject parentTile)
     {
         parent = parentTile;
     }
     
     public GameObject getParent()
         
     {
         return parent;    
     }
     
     public double getFScore ()
     {
         return F;    
     }
     
     public void setFScore (double x)
     {
         F = x;    
     }
     
     public double getHScore()
     {
         return H;
     }
     
         public double getGScore()
     {
         return G;
     }
     
     public void setGScore (double x)
     {
         G = x;    
     }
     
     public void setHScore (double x)
     {
         H = x;    
     }
         
     }    
     void Start () {
     
         if (gameObject.tag == "Free square")
         {
             isOccupied = false;
         }
         else 
         {
             isOccupied = true;
         }
         
         setFScore(0);
         setGScore(0);
         setHScore(0);
         
     }
     
     // Update is called once per frame
     void Update () {
     
     }
     
     
     
     
 }

but for some reason when it comes to the sorting itself Unity sends me this error :

"ArgumentException: does not implement right interface System.Collections.Generic.Comparer`1+DefaultComparer[UnityEngine.GameObject].Compare (UnityEngine.GameObject x, UnityEngine.GameObject y) (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System.Collections.Generic/Comparer.cs:86) System.Array.compare[GameObject] (UnityEngine.GameObject value1, UnityEngine.GameObject value2, IComparer`1 comparer) (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System/Array.cs:1744) System.Array.qsort[GameObject,GameObject] (UnityEngine.GameObject[] keys, UnityEngine.GameObject[] items, Int32 low0, Int32 high0, IComparer`1 comparer) (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System/Array.cs:1721) System.Array.Sort[GameObject,GameObject] (UnityEngine.GameObject[] keys, UnityEngine.GameObject[] items, Int32 index, Int32 length, IComparer`1 comparer) (at /Applications/buildAgent/work/b59ae78cff80e584/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, IComparer`1 comparer) (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System/Array.cs:1677) System.Array.Sort[GameObject] (UnityEngine.GameObject[] array, Int32 index, Int32 length, IComparer`1 comparer) (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System/Array.cs:1623) System.Collections.Generic.List`1[UnityEngine.GameObject].Sort () (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System.Collections.Generic/List.cs:568)"

I'd be very happy if anyone could help me out because I don't see what's wrong here. Thanks !!

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Landern · Mar 19, 2013 at 01:25 PM 0
Share

I dorked around with this for a little bit in Visual Studio(not mono) as it would seem like everything is implemented correctly. They way you have that code right now is explicitly implemented, i found explicitly to be not forgiving with accessors(public) and a couple other quirks. When i implicitly implemented it, there seemed to be more of a forgiving nature of the compiler.

Explicit:

 int IComparable.CompareTo(object obj)
 {
     throw new NotImplementedException();
 }

Implicit(more forgiving):

 public int CompareTo(object obj)
 {
     throw new NotImplementedException();
 }


Test your code with an implicit implementation and see if mono is more loving. Otherwise it seems buggy, also note that it seems to be trying to use IComparable which is odd. Anyways, just stabs in the dark.

avatar image laoril · Mar 19, 2013 at 01:35 PM 0
Share

Unfortunately I first tried with public int CompareTo and it gav me the same error. It is trying to use IComparable because it's the way you can define a "custom" sort for lists in c#, although I do not master that aspect, and that's probably where my error is, but i don't get where even if I've read dozens of threads about IComparable.

2 Replies

· Add your reply
  • Sort: 
avatar image
3

Answer by whydoidoit · Mar 19, 2013 at 01:33 PM

I think you want to implement an object using the IComparer interface rather than IComparable. However, normally you can just do the sort using the lambda version of Sort:

E.g:

   children.Sort((c1, c2) => (int) (c1.topLeft.x - c2.topLeft.x));

Comment
Add comment · Show 15 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image whydoidoit · Mar 20, 2013 at 08:40 PM 1
Share

Sure you can do that - if it's an array of GameObject you can do this:

   children.Sort((c1,c2)=> (int) (c1.GetComponent<TileStatus>().getFScore() - c2.GetComponent<TileStatus>().getFScore()));
avatar image whydoidoit · Mar 20, 2013 at 10:45 PM 1
Share

@laoril - only when you have 15 karma (which you do now because I upvoted your question - seemed like a sensible one to me :)

You can upvote comments (but that awards no karma, just indicates the ones that are relevant). You can upvote answers (15 karma) and you can tick answers.

You can accept an answer (20 karma) and you can post your own answer and tick that (no karma for that I'm afraid) if you feel you did something different.

avatar image Bunny83 · Mar 20, 2013 at 11:02 PM 1
Share

I would also suggest to use an array / List of TileStatus and not GameObject. The IComparable interface would only work when you compare two objects of this type. When you have a list of GameObjects the sort function will compare GameObjects and not a component that might be attached to it.

Also there's a generic version of IComparable so you don't need to type-cast manually. Also inside the CompareTo function you usually use the CompareTo function of the variable type you want to compare.

eg:

 public int CompareTo(TileStatus aOther)
 {
     return getFScore().CompareTo(aOther.getFScore());
 }
avatar image whydoidoit · Mar 20, 2013 at 11:23 PM 1
Share

Good point @Bunny83!

I would also point out, for completeness that you can also use Linq:

   using System.Linq;

   ...
   var tileStatusSortedByFscore = gameObjectArray.Select(g=>g.GetComponent<TileStatus>()).OrderBy(ts=>ts.getFScore()).ToList();  //Or ToArray

   var gameObjectSortedByFscore = gameObjectArray.OrderBy(g=>g.GetComponent<TileStatus>().getFScore()).ToList();

Or perhaps

   foreach(var tile in tileStatusArrayOrList.OrderBy(ts=>ts.getFScore())
   {
      //Do something
   }
avatar image whydoidoit · Mar 21, 2013 at 12:00 PM 1
Share

@laoril we were talking techy sorry - that's pretty advance stuff.

The practical upshot is that using Linq is actually not a good idea in an Update loop because it allocates memory that will be reclaimed causing a garbage collection performance spike (until I release my version of Linq as an asset that doesn't do that!)

To summarise our suggestions:

  • $$anonymous$$eep your TileStatus in a List< TileStatus> to remove the need for continual GetComponent calls.

  • Use Linq in a setup phase as it's faster than the IComparer versions that require the execution of the comparison O(log(n)) times.

Show more comments
avatar image
0

Answer by vexe · Jul 07, 2014 at 01:15 PM

I ran into the same issue with IComparable - Here are the workarounds.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

14 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Sorting a list of GameObjects by accessing their int values 2 Answers

Object Association in a List 1 Answer

[C#] Sorting a List of Gameobjects Alphabetically 2 Answers

sort a List of GameObjects by distance? 1 Answer

Ordering an array of GO based on interfaced variables using linq. 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges