我目前正在用Unity3D制作游戏,并在学习游戏时尝试将SOLID的单一职责原则实施到我的游戏中。
我想知道是否有人可以解释一下SRP的良好实现是什么样子,因为我感觉自己正在打破它。
我将课程分为基础部分:
当我开始时,我觉得我正在遵循SRP,但是现在游戏变得越来越复杂。上面列出的每个类都有对其他类的引用,这似乎是不必要的。我在每个类中都使用了5个GetComponents,但由于它们都在同一对象上,因此似乎是重复的。换句话说,SRP似乎需要更多工作,并且使其效率降低。
例如,PlayerController和PlayerMovement脚本都引用了AnimationController,而AnimationController也引用了两者。所有脚本都引用了PlayerInput。 (请记住,为了简化起见,我省去了其他与玩家相关的脚本,例如工艺和设备,但是我的Start和Awake方法中充满了许多GetComponent调用)
谁能更好地向我解释SRP,也许可以向我指出正确的方向,所以我在同一个GameObject上使用的不是GetComponent。
谢谢
答案 0 :(得分:2)
您已经正确识别了问题,无论理论原理如何,显然都需要解决该问题。但是,让我们首先讨论SRP:
SRP引用了两个较旧的概念,即 coupling 和 cohesion 。不幸的是,名称“ SRP”令人困惑,模棱两可,并且仅包含等式的一侧,即拆分内容。它没有提到属于一起的东西实际上应该在一起。
因此,所有这些的重点是启用 maintainability ,这是减少以后工作量的捷径。为此,相互参照的事物实际上应该在一起是合理的。这意味着使用某些数据的方法应与该数据位于同一位置(即在同一对象中)。松散相关的资料(即互相很少提及)应该分开。
在实践中,如何执行此操作取决于业务案例,并不总是很明显。我建议做运动。将这些内容放在一个类中,例如,称为Player
。简化它,删除所有的setter / getter和间接方法。然后尝试查看是否存在仅松散地互相引用或仅在一个方向上引用的区域。这些将是很好的候选人。
尝试将有意义的事物而不是技术性的事物分解开来,例如Movement
,Attack
,Player
都很好,Controller
,Animation
值得怀疑(虽然并不总是很糟糕)。
答案 1 :(得分:1)
听起来您所指的与SRP无关。从最基本的意义上讲,SRP意味着您拥有的任何班级仅应对一件事情“负责”。您的PlayerInput
负责跟踪玩家通过其界面设备提供的内容,PlayerController
根据多种因素提供有关玩家的状态信息,等等。
您似乎要指的是与DRY(不要重复自己)原理有关。 DRY很棒,它为抽象和代码重用提供了很好的主干,但是这不是福音。实际上,SOLID原则之一-依赖项倒置原则-在某种程度上积极鼓励人们以灵活性为名重复自己。
如果您认为要调用的方法过多,则可以考虑将对该方法的调用以及任何中间逻辑包装在另一个方法中,然后调用该方法。当然,这取决于需要在多个地方调用的同一组指令。
现在,我要说的是,您的帖子中跳出的一部分是您的AnimationController
和PlayerController
和PlayerMovement
类之间的循环引用。实际上,这实际上违反了SRP和一些其他好的设计原则,因为封闭的类现在负责分配的任务,至少要跟踪正在发生的事情在AnimationController
中,最多只能调用AnimationController
本身的方法。
您应该考虑重构您的更精细的类,以使他们无论AnimationController
中发生了什么都能够执行其工作,反之亦然。封闭类应该处理告诉封闭类做什么的逻辑,本质上是为封闭类做出决定。