我正在使用统一构建一个简单的自上而下的胭脂游戏。我有开发经验,但我是Unity框架和c#的初学者。是否有一种干净而优雅的方式来处理玩家对象与场景中其他各种类型的对象的交互?
例如,场景将充满墙壁,敌人和阻挡路径的其他物体,玩家可以通过尝试向他们的方向移动来与之交互。站在胸前靠近它的方向不会移动玩家,而是打开胸部。如果进入墙壁,会损坏墙壁等。
目前我正在使用raycast2d获取阻塞路径的对象,但无法找到如何与之交互的解决方案,而无需检查它是什么类型的对象(是一个Wall;是胸部等;等等。我创建了一个接口,所有可交互对象都使用方法interact()实现,但不同类型的对象需要不同的信息。墙需要它应该承受的伤害量(取决于玩家类别中的玩家统计数据),胸部不会占用。因此,所有人都难以实现相同的接口。让墙壁询问玩家他的伤害是什么也是糟糕的编程习惯。
我刚才发现了一个类似的问题on stackowerflow。它建议使用观察者模式,但我无法想象场景中的每个对象都订阅了玩家移动事件,并且在每次移动后检查天气是否被击中。
这种互动是否有标准解决方案?一个松散耦合,干净并遵循良好的编程习惯的人?
答案 0 :(得分:1)
如果我在你的情况下,我会向对象(墙,胸部等)添加一个带有Collider2D
的空游戏对象,并切换isTrigger
的框。 (请注意,这将要求对象派生自Monobehaviour
,并且可能并不总是需要。)
从那里我将使用专门函数OnTriggerStay
,OnTriggerEnter
和OnTriggerExit
的某种组合:
//in Chest.cs
void OnTriggerEnter() //http://docs.unity3d.com/ScriptReference/Collider.OnTriggerEnter.html
{
OpenChest();
}
//in Wall.cs
void OnTriggerStay() //http://docs.unity3d.com/ScriptReference/Collider.OnTriggerStay.html
{
DamageWall();
}
从这里开始,您有两种选择来确保某些游戏对象不会触发错误的对撞机。一种方法是使用代码:
//in Chest.cs
void OnTriggerEnter(Collider other)
{
//notice this won't be very efficient
if(other.gameObject.GetComponent<PlayerScript>() != null) OpenChest();
//if(other.name == "The Player") OpenChest(); //probably less efficient at runtime
}
另一种解决方案使用图层并且效率更高。要向Unity添加图层,请浏览edit
- &gt; project settings
- &gt; tags and layers
(左上角的标签)并添加一些图层名称(例如Wall,Chest,Player,Enemy)。接下来找到触发器(最好是触发器的父级),并通过从Inspector
层切换到所需的标签(例如Wall),将对象标记为Default
中该层的一部分。 / p>
从这里开始,您可以通过edit
- &gt;使用另一种技巧,即层之间的选择性碰撞。 project settings
- &gt; physics
并查看Layer Collision Matrix
。如果两个物体需要碰撞,请将复选框填满;如果他们不应该碰撞,取消选中框;如果它们应该在情境上发生碰撞,要么将图层拆分为两个或更多,要么添加确定是否发生碰撞的代码。
另一个提示:如果一个玩家在拿着电锯时只能砍下一棵树,你可以这样做,所以抓住电锯会产生一个特殊的触发器来摧毁树木。
编辑:其他陷阱:
1) two triggers cannot collide (one must be a trigger and the other must be a collider)
2) triggers can move (they do not need to be stationary)
3) if one collider-trigger pair seems illogical, switching which object is the trigger and which is the collider might make the code simpler.
edit2:删除耦合:
每个实例都会调用{p>OnTriggerStay(Collider other)
,如果所有怪物和玩家都造成相同的伤害,那么效果会很好,但事实并非如此。如果每个实例造成不同程度的伤害,您可以执行以下操作:
void OnCollisionEnter(Collision other)
{
addSelfDPS(other.gameObject.GetComponent<WallDamager>().getDPS());
}
void OnCollisionExit(Collision other)
{
addSelfDPS(-1*other.gameObject.GetComponent<WallDamager>().getDPS());
}
但是,如果使用此方法,则在触发器中生成和销毁对象时会出现问题,因此您可能需要在任何构造函数(Awake / Start)或析构函数(OnDestroy)中解决该问题。