解决解耦组件中的冲突功能

Posted

技术标签:

【中文标题】解决解耦组件中的冲突功能【英文标题】:Resolving conflicting functionality in decoupled components 【发布时间】:2016-10-24 09:59:01 【问题描述】:

我一直在研究 Unity3D 中更严格的基于组件的设计。我一直在使用太空入侵者克隆作为练习项目。在我的播放器对象上,它具有以下组件:PlayerInput、Horizo​​ntalVelocity 以及渲染器等常见的嫌疑犯。

我正在使用中介系统进行通信,因此当按下箭头键时,PlayerInput 类会创建一个事件,然后通过中介将其广播到速度。

现在我想添加一个 Horizo​​ntalBounds 类来阻止它向左或向右移动太远。但是有一个冲突:速度和水平边界都试图同时以不同的方式移动变换。我可以想到解决这个冲突的几个选项:

bounds 组件不断检查变换,如果超出边界,它会将其推回边界内。这太可怕了,因为我们让速度组件将其单向移动,而边界组件将其向后移动,每一帧。

创建一个从 Velocity 派生的 VelocityWithBounds 组件(如果我们试图避免继承,或者实现一个速度接口?)。这里的问题是您将两个组件放在一起。如果你想删除边界,你不能只是摆脱那部分(你可以将它设置为边界,但它仍然会存在)。您将不得不销毁所有内容并用新的速度组件替换它。我不确定这是否会导致任何重大问题,但这似乎不太优雅。

给 bounds 组件一些在运行时覆盖速度组件功能的方法。 这似乎是最优雅的解决方案,但可能最难实现。您必须以这样一种方式将它们解耦,以使速度不知道它被覆盖了。 这只是一个示例问题。此类问题是否有任何最佳实践,或者是否应逐案解决?

【问题讨论】:

您是否尝试过使用 Mathf.Min(float a, float b); 设置动态限制位置(如果不是速度) ?你能解释一下,为什么你对只玩速度如此感兴趣,即给予反速度或负速度来阻止船移动? 在许多组件设计中,其传统的做法是使用“速度”组件来控制对象的运动。如果你喜欢你可以把它想象成一个“movementController”组件。我不太清楚“动态设置”是什么意思,但根本问题是我们基本上有两个独立的组件试图产生相反的效果。一种不可阻挡的力量/不可移动的物体场景。速度/边界只是这类问题的一个例子。也可能是两个单独的组件试图将精灵更改为不同的颜色。 我有一个解决方案,但在此之前我需要询问您是否可以选择在项目的此时重构这两个组件的代码? 【参考方案1】:

除非您有能力重构代码设计,否则请考虑以下选项:

叠加原理:

F(v1+v2)=F(v1)+F(v2)  Additivity <= should apply better in your case
y ( x , t ) = y m sin ( k 1 x - w1 t ) + y m sin ( k 2 x + w 2 t ) 

w1 = velocity component 1
w2 = velocity component 2
x = phase 

创建一个空间或函数 y(x,t) 直接驱动你的船的速度

细化解决方案(我的版本):

当您有两个相互定义的身份/空间(在您的情况下是组件)时,最好创建第三个身份/空间,以便第三个身份/空间依赖于前两个。 换句话说,将空间 [s0] 分解为子空间 [s1 和 s2],同时这样做的结果是 [s1 和 s2] 将有一个共同的输入和输出类型(非常重要)。

将你的船的功能分成两部分,一个限制你的船 和其他控制加速度的。将需要两个不同的游戏对象。

由于您有 2 个解耦组件定义实体的速度,我建议使 bounds 与该受控实体一起移动。因此,这意味着例如:您的船在接近边界时会以指数方式损失速度和 acceleration,但是如果您允许更大的加速度,它会开始沿着 bounds 标记。听起来很激烈,但这会给你额外的控制。事实上,您所要做的就是将 MAX 加速度设置为不超过移动边界所需的加速度。

【讨论】:

如果您需要进一步澄清,对于 Refinement Solution,我需要一些时间。 我一直在做的事情有点像你建议的那样。每个可能影响速度的组件都有一个优先级。效果将全部发送到一个中间组件,该组件将整理所有优先级,然后只允许该组件直接更改变换。 只要你对结果满意,你的方法就是好的!但是,作为一个好心人,我仍然会提出以下建议:1)在谨慎的情况下使用连续函数非常适合您的情况 2)在您的情况下,应避免直接更改变换(即位置和旋转),使用Rigidbody.Velocity 是惯用的。 我会将这些考虑在内。与其他人交谈时,他使用 ECS 找到了一个很好的解决方案。基本上,您有一个可以改变转换的系统。在此系统中,您将具有检查您正在更改的实体是否具有边界组件的功能。这或多或少是我想要的。您现在可以覆盖行为,因为这些行为不再存在于组件中。这实际上非常类似于我的中介者的想法,它是唯一允许改变转换的东西,它从其他人那里获取值

以上是关于解决解耦组件中的冲突功能的主要内容,如果未能解决你的问题,请参考以下文章

“控制反转”、“依赖反转”和“解耦”之间的区别

JetpackLifecycle 架构组件 ( 系统组件与普通组件解耦 | Lifecycle 解耦系统组件与普通组件 | 解耦服务组件与普通组件 | 监听应用程序生命周期 )

使用Spring AOP实现业务依赖解耦

如何使用解耦的 symfony 组件?

我可以在 React 组件中解耦布尔状态吗

Vue Router:使用 props 将组件和路由解耦