Unity - 使用枚举属性检测物体碰撞
Unity - using enum properties to detect objects colliding
昨晚我正在做一个 C-Sharp 项目,试图围绕 GameObjects 相互碰撞进行编码。我想要不同类型的门(例如木头、石头、金属),它们可以被不同的武器(例如棍棒、剑、斧头)分解。
为了检测 GateManager 上的碰撞,我为每个门使用了标签。例如:
void OnTriggerEnter(Collider collider) {
switch (gameObject.tag) {
case "WoodenGate":
...
case "StoneGate":
...
上面的代码并不准确,但应该可以提供一个思路。将每个门类型设置为不同的标签感觉不对(如果每个门类型都有不同的标签,每个 material 类型都有不同的标签,等等,那么我最终会得到数百个标签)。
所以我想出了一个替代方案。我设置了一个 GateType 枚举并创建了 3 个值(WoodenGate、StoneGate、MetalGate)。然后我将 public GateType 属性 附加到 GateManager class。这让我可以 select 在统一的 'Inspector' window 中,哪个枚举与每个预制件相关。非常整洁,我真的很开心。
然后出现了一个问题:我在列表的中途添加了第 4 个枚举(例如 GlassGate)。因为枚举只是 int 值,所以第三项不再是 MetalGate,而是现在的 StoneGate。这意味着金属门预制件的门类型突然变成了石门。这打破了我的游戏。
抱歉,对于这个冗长的问题,但我的问题是我应该如何最好地标记和识别许多不同类型的项目?我不想使用标签(因为我需要太多)而且我不想使用枚举(因为它们在与统一检查器结合使用时会形成脆弱的问题。
我想这一定是许多游戏的共同要求(例如,在游戏中,您可以在许多不同的游戏对象上使用您的镐来收集不同的资源)所以只是想知道最佳实践?
枚举是最方便的方式。向枚举值添加索引并手动递增它。
public GateType gateType;
public enum GateType
{
Wood = 0,
Stone = 1,
Brick = 2
}
现在,如果您想在 'list' 中间添加另一个,请按以下步骤操作:
public GateType gateType;
public enum GateType
{
Wood = 0,
Metall = 3,
Stone = 1,
Brick = 2
}
Unity 应该在您的对象上保留正确的值,因为您添加了索引。
1。您可以声明并使用许多接口来完成此操作,但缺点是您需要声明其中的许多接口并在许多脚本中实现它们附加到每个对象:
public interface IDestroyable { }
public interface IOpenable { }
然后你在你的脚本中继承它:
public class MyScript : MonoBehaviour, IDestroyable{}
public class MyOtherScript : MonoBehaviour, IOpenable{}
碰撞时检查是哪一个:
void OnTriggerEnter(Collider collider)
{
if (collider.GetComponent<IOpenable>() != null)
{
}
else if (collider.GetComponent<IDestroyable>() != null)
{
}
}
2。您也可以使用您提到的枚举。
public enum GateType
{
WoodenGate,
StoneGate,
MetalGate
}
将描述此对象的门类型的单个脚本附加到所有 Gate 对象预制件,然后从编辑器或脚本中为每个预制件选择枚举
public class GateDescription : MonoBehaviour
{
public GateType gateType;
}
碰撞时检查是哪一个:
void OnTriggerEnter(Collider collider)
{
GateDescription gateType = collider.GetComponent<GateDescription>();
if (gateType != null)
{
switch (gateType.gateType)
{
case GateType.StoneGate:
break;
case GateType.WoodenGate:
break;
case GateType.MetalGate:
break;
}
}
}
您可以按照spawn/init事件进行设置。如果你打算使用枚举方法,你可以在生成对象时定义它。这显然取决于您的游戏机制。但是,我可能会将此外包给专门针对您想要的 material 行为的单一行为。这样,如果您想更改木拱门的行为方式,您只需更新一个脚本,它是独立的。如果您使用 2017.3 允许您定义哪些文件进入哪些程序集的功能,这将有助于您的代码库变大并缩短编译和加载时间
昨晚我正在做一个 C-Sharp 项目,试图围绕 GameObjects 相互碰撞进行编码。我想要不同类型的门(例如木头、石头、金属),它们可以被不同的武器(例如棍棒、剑、斧头)分解。
为了检测 GateManager 上的碰撞,我为每个门使用了标签。例如:
void OnTriggerEnter(Collider collider) {
switch (gameObject.tag) {
case "WoodenGate":
...
case "StoneGate":
...
上面的代码并不准确,但应该可以提供一个思路。将每个门类型设置为不同的标签感觉不对(如果每个门类型都有不同的标签,每个 material 类型都有不同的标签,等等,那么我最终会得到数百个标签)。
所以我想出了一个替代方案。我设置了一个 GateType 枚举并创建了 3 个值(WoodenGate、StoneGate、MetalGate)。然后我将 public GateType 属性 附加到 GateManager class。这让我可以 select 在统一的 'Inspector' window 中,哪个枚举与每个预制件相关。非常整洁,我真的很开心。
然后出现了一个问题:我在列表的中途添加了第 4 个枚举(例如 GlassGate)。因为枚举只是 int 值,所以第三项不再是 MetalGate,而是现在的 StoneGate。这意味着金属门预制件的门类型突然变成了石门。这打破了我的游戏。
抱歉,对于这个冗长的问题,但我的问题是我应该如何最好地标记和识别许多不同类型的项目?我不想使用标签(因为我需要太多)而且我不想使用枚举(因为它们在与统一检查器结合使用时会形成脆弱的问题。
我想这一定是许多游戏的共同要求(例如,在游戏中,您可以在许多不同的游戏对象上使用您的镐来收集不同的资源)所以只是想知道最佳实践?
枚举是最方便的方式。向枚举值添加索引并手动递增它。
public GateType gateType;
public enum GateType
{
Wood = 0,
Stone = 1,
Brick = 2
}
现在,如果您想在 'list' 中间添加另一个,请按以下步骤操作:
public GateType gateType;
public enum GateType
{
Wood = 0,
Metall = 3,
Stone = 1,
Brick = 2
}
Unity 应该在您的对象上保留正确的值,因为您添加了索引。
1。您可以声明并使用许多接口来完成此操作,但缺点是您需要声明其中的许多接口并在许多脚本中实现它们附加到每个对象:
public interface IDestroyable { }
public interface IOpenable { }
然后你在你的脚本中继承它:
public class MyScript : MonoBehaviour, IDestroyable{}
public class MyOtherScript : MonoBehaviour, IOpenable{}
碰撞时检查是哪一个:
void OnTriggerEnter(Collider collider)
{
if (collider.GetComponent<IOpenable>() != null)
{
}
else if (collider.GetComponent<IDestroyable>() != null)
{
}
}
2。您也可以使用您提到的枚举。
public enum GateType
{
WoodenGate,
StoneGate,
MetalGate
}
将描述此对象的门类型的单个脚本附加到所有 Gate 对象预制件,然后从编辑器或脚本中为每个预制件选择枚举
public class GateDescription : MonoBehaviour
{
public GateType gateType;
}
碰撞时检查是哪一个:
void OnTriggerEnter(Collider collider)
{
GateDescription gateType = collider.GetComponent<GateDescription>();
if (gateType != null)
{
switch (gateType.gateType)
{
case GateType.StoneGate:
break;
case GateType.WoodenGate:
break;
case GateType.MetalGate:
break;
}
}
}
您可以按照spawn/init事件进行设置。如果你打算使用枚举方法,你可以在生成对象时定义它。这显然取决于您的游戏机制。但是,我可能会将此外包给专门针对您想要的 material 行为的单一行为。这样,如果您想更改木拱门的行为方式,您只需更新一个脚本,它是独立的。如果您使用 2017.3 允许您定义哪些文件进入哪些程序集的功能,这将有助于您的代码库变大并缩短编译和加载时间