我目前正在创建一个小型植物护理游戏(Unity Engine 2022.3.40f1)。它的属性(基因)作为基因组传递到它的各个部分。这些属性可以是浮点数、整数或颜色。
为此目的,我创建了一个抽象
Gene<T>
类(见下文),从中创建了 GeneFloat : Gene<float>
、GeneInt : Gene<int>
...
我遇到了一个问题:这个 Gene 类似乎并不像我希望的那样通用。
Gene<T>
班级
public abstract class Gene<T> {
public abstract T value { get; set; }
public abstract T randomRange { get; set; }
}
遗传基因的示例(此处
GeneFloat
):
public class GeneFloat : Gene<float> {
public override float value { get; set; }
public override float randomRange { get; set; }
}
但是,我似乎无法使用
Gene
类作为泛型!这是我的问题。
以下代码使 Unity 在控制台中记录一条错误消息:“the generic type 'Gene<T>' requires 1 type arguments
”
public struct Genome {
public Gene[] genes; // <- a message for this line
public Gene GetGeneNyName(string name) { // <- and for this one
foreach(Gene gene in this.genes) { // <- but not for this one ?????
if (gene.GetName() == name) return gene;
}
Debug.LogError($"It seems that the gene '{name}' couldn't be found in the genome. Maybe it does not exist or the spelling is wrong.");
}
}
你能帮我找出问题所在吗?
老实说,我并没有尝试一切,因为我只是一个临时程序员,这是我第一次如此彻底地使用泛型。我在这里搜索了一些想法,但似乎没有任何内容可以帮助我弄清楚。
我尝试用
Gene
替换 Gene<int, float, Color>
,但显然,这并没有让我走得太远。
您需要一个非泛型的基类,其中包含具有具体类型的所有成员:
public abstract class Gene
{
public string Name { get; set; }
public abstract void Mutate();
}
此类可用于基因集合。
现在,创建一个通用类并添加值:
public abstract class Gene<T> : Gene
{
public virtual T Value { get; set; }
public virtual T RandomRange { get; set; }
}
然后创建具体的类
public class GeneFloat : Gene<float>
{
// You can override the virtual members or leave them as is.
}
public class GeneColor : Gene<Color>
{
// You can override the virtual members or leave them as is.
}
...
现在,您可以使用类型模式来处理具体类型的事情
public Gene[] genes;
...
var gene = genes.FirstOrDefault(g => g.Name == "leafColor");
if (gene is GeneColor c) {
Color color = c.Value;
...
}
我最近做了类似的事情,其中范围由
Min
值加上 Range
给出。随机部分由 Fraction
值(介于 0 和 1 之间)给出,值本身由(以 float
为例)给出:
public float Value => Min + Fraction * Range;
您可以将拥有一系列基因以便更容易突变和拥有单个基因的属性的想法结合起来:
public class Genome
{
public Gene[] Genes { get; }
public GeneFloat LeafWidth => (GeneFloat)Genes[4];
// or, alternatively, return the value directly
public float LeafWidth => ((GeneFloat)Genes[4]).Value;
...
}