2

我正在使用 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--;. 不过,这可能吗?我环顾四周,似乎我不能将接口用作类型参数。

4

4 回答 4

2

事实证明,这并不容易,而且可能不是一个好主意。问题是GetComponent<T>期望类型参数T来自Component(当然,Unity 没有记录这一点)。我需要 make RobotPlayer等都派生自一个抽象类,该类本身继承自Component(通过MonoBehaviour),并包含有关健康和其他领域的信息。我怀疑这是否值得;它可能会在其他地方导致同样多的混乱代码。

于 2012-11-29T00:21:06.430 回答
0

为什么不只是有一个组件Health。然后将其附加到您的游戏对象,RequiresComponent在任何需要健康的脚本上添加注释,然后通过GetComponent<Health>();(将其缓存在私有变量中的同一对象脚本中)

如果您有多个始终在一起的“统计信息”,则可以使其更容易,例如

public class Status : MonoBehaviour
{
    public float health;
    public float armor;
}

我发现团结一致,这是一个令人惊讶的普遍“问题”。不确定这是否是一个问题,因为这种想法确实可以帮助解决一些问题......

于 2012-12-03T14:08:57.207 回答
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--;
于 2012-11-28T20:54:06.093 回答
0

我认为您有一个基本的设计问题,因为您的消费代码需要了解每种类型。如果您无论类型如何都采取相同的操作,那么只需使用良好的多态性:

public class Player: IHealth {}

public class Robot: IHealth {}

而不是一堆if语句,从 GetComponent 中删除通用参数并让它返回一个 IHealth 对象:

public IHealth GetComponent()
{
    // return IHealth object here
}

在您的调用代码中:

obj.GetComponent().DecreaseHealth();
于 2012-11-28T20:54:43.500 回答