Error while debugging list
I have a list which contains 2 variables:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class SlowOrder //holds the values for slows
{
public float Speed;
public float Duration;
public SlowOrder(float speed, float duration)
{
Speed = speed;
Duration = duration;
}
}
public class UnityTest : MonoBehaviour
{
public List<SlowOrder> slowOrder = new List<SlowOrder>();
public float walking;
public float currentSlowDuration;
void SlowEffect(List<float> slowHolder) //sendmessage from projectiles //list [0] = percent [1] = duration
{
float wTemp = walking - (walking * slowHolder [0]); //new slowed walking speed
float dTemp = currentSlowDuration - Time.time; //current slowed duration, left
slowOrder.Add (new SlowOrder (wTemp, slowHolder[1] + Time.time));
for(int i = 0; i < slowOrder.Count; i++) //debugging
{
Debug.Log ("speed = " + slowOrder[i].Speed + " / duration = " + slowOrder[i].Duration);
}
slowHolder.Clear (); //clears this methods list "SlowOrder" for next
}
}
I get this Error:
ArgumentException: does not implement right interface
But only when I add to the list and then debugs. The first fire dose not give errors.
I used this type of list and not a dictionary cause i will have duplicate keys and values.
Still learning scripting, so be nice and simple.
James
Does the list ever call .Sort()? I only ask cause that same error would be thrown since SlowOrder doesn't implement IComparable. I'm not sure why this error is happening.
Yes it does but the .Sort() dose not get called till latter. After the debug. usually 5 secs
I just tested this out and you are right. How would I go about sorting then?
I haven't done this a lot, but I think it would go something like this:
using System;
public class SlowOrder : IComparable<SlowOrder> //holds the values for slows
{
public int CompareTo(SlowOrder obj) {
if (obj == null) return 0;
if (obj.Duration > this.Duration) return 1;
return 0;
}
IComparable is unavailable in mono. it does allow IComparer
Answer by RickyAh · Nov 15, 2015 at 01:32 PM
If you want to sort a List the elements in the list must be comparable in some way. Common types like int, float, and strings are already comparable. However if you define your own type you must also define a way to sort the elements, otherwise the Sort method won't know what to do.
You have two options to define how you want to sort a new type.
Using IComparable Make SlowOrder implements the interface IComparable which requires to define a method named CompareTo. This is basically what @Jessespike suggested. The interface is available on Unity, I've used it several times. If it gives you a compilation error then you must add using System;
to the beginning of the file.
Using IComparer The previous approach can be useful to define a default sorting for SlowOrder elements, the problem is that it only allows sorting in one specific way, and you might be interested in sorting a list in different ways. Maybe you want to sort by Speed, ascending or descending depending on the situation, or maybe you have one case where you want to sort SlowOrder elements by Duration, instead of Speed.
For this situation you can create new classes that implements IComparer. That interface only's purpose is define a method with the algorithm to sort collections containing other types, so you can create several classes implementing IComparer where each class contains a different sorting algorithm:
using System.Collections.Generic;
public class SlowOrderSortByDuration : IComparer<SlowOrder>
{
int Compare(SlowOrder x, SlowOrder y)
{
return x.Duration < y.Duration;
}
}
// Now sort the list using this comparer
slowHolder.Sort(new SlowOrderSortByDuration());
To avoid creating a new object each time that you want to sort a list, I recommend you to just add an static field of the IComparer to the class you want to sort:
public class SlowOrder //holds the values for slows
{
public class SortByDuration : IComparer<SlowOrder>
{
int Compare( SlowOrder x, SlowOrder y)
{
return( x.Duration < y.Duration;
}
}
static public SortByDuration ByDuration = new SortByDuration();
public float Speed;
public float Duration;
public SlowOrder(float speed, float duration)
{
Speed = speed;
Duration = duration;
}
}
So now you can sort your list like this:
slowHolder.Sort(SlowOrder.ByDuration);
Now, if you want to sort SlowOrder elements in different ways, you only need to create another different class implementing IComparer and implementing the new sorting method, for example:
slowHolder.Sort(SlowOrder.BySpeedDescending)
Wow. just simply wow. Great answer and so well explained. Love how you gave me an understanding of how this works. I fully dont but after playing with it I am sure I will.
I have a question: Is this a good way of applying debufs to players/enemies? Each player/enemy will have this in there scripts which also controls other things. By making it static wont it be global? Could I add:
[System.Serializable] //this
public class SlowOrder //holds the values for slows
{
public class SortByDuration : IComparer<SlowOrder>
{
int IComparer.Compare( SlowOrder x, SlowOrder y)
{
return( x.Duration < y.Duration;
}
}
static public SortByDuration ByDuration = new SortByDuration();
public float Speed;
public float Duration;
public SlowOrder(float speed, float duration)
{
Speed = speed;
Duration = duration;
}
}
Above and make it this class specific? Or am I understanding this all wrong?
Also SlowHolder is just used to transfer var amounts. Ill need to Sort() "SlowOrder"
Also getting a error x2:
Assets/Attempt 3/Enemies/Scripts/Enemy$$anonymous$$eleeGrunt.cs(28,31): error CS0540:
for line:
int IComparer.Compare (SlowOrder x, SlowOrder y)
No problem making it static: The class does not contains data, you only need the algorithm Also as it does not contains data it is safe to serialize the class because, there is nothing to serialize! :)
About the error I think you need to remove the IComparer.
from the lines IComparer.Comparer
$$anonymous$$y bad
Thanks. I was reading up on these kinds of lists and came up with:
[System.Serializable]
public class SlowOrder : IComparable<SlowOrder> //holds the values for slows
{
public int CompareTo(SlowOrder other)
{
if (this.Speed > other.Speed)
return 1;
else if (this.Speed < other.Speed)
return -1;
else
return 0; //will add another search camparing the duration
//return this.Speed.CompareTo (other.Speed); //short form
}
public float Speed;
public float Duration;
public SlowOrder(float speed, float duration)
{
Speed = speed;
Duration = duration;
}
}
what do you think? I need something optimaized due to being a bullet hell game.
Seems ok, I don't think you'll get a comparison algorithm more optimized than that. The problem -if you find any- won't be in this Compare method, but probably in the number of times you call Sort. Here's the Sort method doc in case you are interested: https://msdn.microsoft.com/en-us/library/234b841s(v=vs.110).aspx
Sort() will be only called when the enemy current slow runs out and there are more in the SlowOrder due to being a lesser slow then the current one but with a longer duration.
Your answer

Follow this Question
Related Questions
problem with loading list of strings on buttons 2 Answers
add object to list button script in inspector? 0 Answers
How do I properly use List-Vector3-.Contains()? 1 Answer
How would I implement a random spawn timer into a list based spawn system? 2 Answers
List, for loop and removal of items 2 Answers