我正在使用C#开发Unity3d游戏,我们在很多情况下需要访问int health
的特定成员(例如GameObject
)。我们使用以下代码执行此操作:
GameObject obj;
if(obj.GetComponent<Player>() != null) {
obj.GetComponent<Player>().health--;
}
else if(obj.GetComponent<Robot>() != null) {
obj.GetComponent<Robot>().health--;
}
// more painful code
我想要做的是让所有这些类实现IHealth
之类的接口,然后执行obj.GetComponent<IHealth>().health--;
。这可能吗?我环顾四周,看起来我不能将接口用作类型参数。
答案 0 :(得分:2)
事实证明这并不容易,也许不是一个好主意。问题是GetComponent<T>
期望类型参数T
派生自Component
(当然,Unity不会记录此内容)。我需要使Robot
,Player
等等都来自一个抽象类,它本身继承自Component
(通过MonoBehaviour
),并包含有关健康和其他的信息。领域。我怀疑这是值得的;它可能导致其他地方的代码混乱。
答案 1 :(得分:0)
正如SLaks所指出的那样,接口作为泛型类型参数是完全可以接受的。如果您的问题是通过界面访问某个字段,那么我建议您只需将字段更改为属性即可。如果由于某种原因你绝对必须保留该字段,只需提供一个隐式实现接口的包装属性。如果问题是字段和属性具有完全相同的名称(包括大小写),则可以显式实现接口:
public interface IHealth { int Health { get; set; } }
// Change to a property
public class Ogre : IHealth { public int Health { get; set; } }
// Casing is different, so interface can be implemented implicitly
public class Player : IHealth {
int health;
public int Health { get { return health; } set { health = value; } }
}
// Name collision with Pascal casing, so implement explicitly
public class Robot : IHealth {
int Health;
int IHealth.Health { get { return Health; } set { Health = value; } }
}
// Later
GameObject obj;
var o = obj.GetComponent<IHealth>();
if (o != null) o.Health--;
答案 2 :(得分:0)
我认为您有一个基本的设计问题,因为您的消费代码需要了解每种类型。如果你采取相同的行动,无论类型如何,那么只需使用好的'多态:
public class Player: IHealth {}
public class Robot: IHealth {}
取代一堆if
语句,从GetComponent中删除泛型参数并让它返回一个IHealth对象:
public IHealth GetComponent()
{
// return IHealth object here
}
在您的主叫代码中:
obj.GetComponent().DecreaseHealth();
答案 3 :(得分:0)
为什么不只有一个组件Health
。然后将其附加到GameObject,在任何需要运行状况的脚本上都有RequiresComponent
注释,然后通过GetComponent<Health>();
获取它(将其缓存在私有变量中的同一对象脚本中)
如果您有多个“统计信息”始终在一起,您可以更轻松地使用
public class Status : MonoBehaviour
{
public float health;
public float armor;
}
我发现团结一致,这是一个令人惊讶的常见“问题”。不确定这是否是一个问题因为这个想法可以真正帮助解决一些问题...