You can define an interface and then have the classes exposing a spawn chance implementing it. It is then easy to test whether an object implements it or not.
public interface ISpawnable
{
float SpawnChance { get; }
}
SpawnChance
must be a property. It is not necessary to declare the setter for this use case (because you only need reading it); however, implementations can still provide one.
Then you can test
if (obj is ISpawnable spawnable) {
float w = spawnable.SpawnChance;
...
}
Or with LINQ if you have a list of mixed objects
var weights = mixedTypeObjects
.OfType<ISpawnable>() // Filters objects implementing it and casts to it.
.Select(x => x.SpawnChance);
If you have generic types or methods, you can use this interface as generic type constraint.
public class SpawnService<T>
where T : ISpawnable
{ ... }
This restricts T
to be a type implementing ISpawnable
and allows you to access SpawnChance
without any casting within this class.
Another option is to derive spawnable objects from a common base class exposing a spawn chance. The interface is more flexible since it works for classes deriving from different base classes. This is an advantage if you already have a class hierarchy and you want classes implement it independently from this hierarchy.
You can also simply pass game objects to the method and filter and cast inside:
public static int GetRandomWeightedIndex(this IEnumerable<GameObjects> gameObjects)
{
var weights = gameObjects
.OfType<ISpawnable>()
.Select(g => g.SpawnChance);
...
}
CLICK HERE to find out more related problems solutions.