我正在Unity中开发一款游戏,我有多个对象(苹果、橙子、香蕉等)可以与多个碰撞器对象(网、盒子、环等)碰撞。每一场比赛都有特定的功能。假设有10个物体和10个对撞机物体,那就是100种方法。如果可能的话,我希望避免使用switch/if-else语句。
目前,碰撞是在对撞机对象上触发的,然后我将其发送给调度:
public class NetCollision : BaseCollider {
CollisionDispatch dispatch;
void OnCollisionEnter (Collision coll)
{
Fruit obj = coll.gameObject.GetComponent<Fruit> ();
dispatch.RegisterCollision (obj, this, coll);
}}
在CollisionDispatch中,我有这样的switch语句:
public void RegisterCollision(Fruit obj, BaseCollider collider, Collision collision) {
if (obj is Banana) {
BananaDispatch (obj as Banana, collider, collision)
} else if (obj is Apple) {
AppleDispatch (obj as Banana, collider, collision)
} ...
}
public void BananaDispatch (Banana obj, BaseCollider coll, Collision collision) {
if (coll is NetCollider) {
// Banana-NetCollider method
} else if (coll is BoxCollider) {
// Banana-BoxCollider method
} ...
}
这是使用泛型的情况吗?我尝试过对泛型进行重构,但它似乎并不能清理代码。
您可以使用多态性和策略或状态模式。例如:
public class CollisionDispatch : MonoBehaviour
{
public void RegisterCollision(Fruit obj, BaseCollider collider, Collision collision)
{
obj.Dispatch(collider, collision);
}
}
public interface ICollisionableFruit
{
//add method for each collision type
void HandleNetCollision(Collision collision);
void HandleElseCollision(Collision collision);
}
public abstract class Fruit : ICollisionableFruit
{
public virtual void Dispatch(BaseCollider collider, Collision collision)
{
collider.HandleCollision(this, collision);
}
//declare all of interface's methods as abstract
public abstract void HandleNetCollision(Collision collision);
public abstract void HandleElseCollision(Collision collision);
}
public class Banana : Fruit
{
//override all methods
public override void HandleNetCollision(Collision collision)
{
Debug.LogFormat("HandleNetCollision for {0}", this.GetType());
}
public override void HandleElseCollision(Collision collision)
{
Debug.LogFormat("HandleElseCollision for {0}", this.GetType());
}
}
public abstract class BaseCollider
{
CollisionDispatch dispatch;
void OnCollisionEnter(Collision coll)
{
var obj = coll.gameObject.GetComponent<Fruit>();
dispatch.RegisterCollision(obj, this, coll);
}
public abstract void HandleCollision(ICollisionableFruit fruit, Collision collision);
}
public class NetCollision : BaseCollider
{
public override void HandleCollision(ICollisionableFruit fruit, Collision collision)
{
Debug.LogFormat("NetCollision HandleCollision");
fruit.HandleNetCollision(collision);
}
}
public class ElseCollision : BaseCollider
{
public override void HandleCollision(ICollisionableFruit fruit, Collision collision)
{
Debug.LogFormat("NetCollision HandleCollision");
fruit.HandleElseCollision(collision);
}
}
您只需为Fruit
的所有继承重写Dispatch
方法,为BaseCollider
的所有继承覆盖HandleCollision
方法。此外,您还可以为每个BaseCollider
继承的Fruit添加特定于抽象的方法,如果它意味着不同的冲突处理依赖的Fruits类型,则可以从HandleCollision
调用它。
如果您需要使用更多的碰撞器,只需要向ICollisionableFruit
、Fruit
和每个继承器添加新方法。
它不是一个明显灵活的解决方案,但它比if
的许多解决方案都要好。
据我所知,有一堆Fruit
对象,当类型为FruitObstacle
的特定对象与它们碰撞时,它们都必须做出不同的反应。
为此,我将使用继承:
- 创建一个基类
Fruit
,该基类将具有OnCollisionEnter
方法 - 创建所有
CollideWithNet
、CollideWithBox
。。。如CCD_ 16方法 - 在
OnCollisionEnter
方法中运行switch
来检测碰撞对象的类型(有很多方法可以检测,例如,可以在FruitObstacle
上使用tags
)并调用相应的方法 - 创建继承
Fruit
类(Banana : Fruit
、Apple : Fruit
…)的所有水果子级 - 为您的
CollideWithBox
、CollideWithNet
。。。每种水果的方法
如果每个水果都有相同的逻辑,那么可以使用virtual
方法而不是abstract
方法,并在Fruit
类中添加逻辑(不要忘记用base.MethodName
调用继承类中的基类)。