因此,我将CombatController
绑定到一个名为"godObject"的对象。在Start()
方法中,我在其他类上调用init()
函数。我这样做是为了控制对象的初始化顺序,因为,例如,字符控制器依赖于正在初始化的网格控制器。
快速图表:
-------------------- calls
| CombatController | ----------> CameraController.init();
-------------------- |
| ---> GridController.init();
|
| ---> CharacterController.init();
所以,现在我有一个小问题。我在每个控制器中都需要多个属性。目前,我已经将所有内容绑定到战斗控制器本身。这意味着,在每个控制器中,我都必须通过GameObject.Find("godObject).GetComponent<CombatController>()
获取战斗控制器的实例。老实说,我不认为这是好的设计。
我现在的想法是创建一个扩展MonoBehavior
的BaseCombatController
,然后让所有其他类(如GridController
、CharacterController
等)扩展BaseCombatController
。它可能看起来像这样:
public class BaseCombatController : MonoBehaviour
{
public GameObject activePlayer;
public void setActivePlayer(GameObject player) {
this.activePlayer = player;
}
... more stuff to come ...
}
这样,我可以在任何地方访问activePlayer
,而无需创建CombatController
的新实例。但是,我不确定这是否没有可能的副作用。
那么,一个简单的问题有很多文字,这样做安全吗?
我一直在 Unity 中使用继承。诀窍,就像你在问题中一样,是允许基类从单行为继承。例如:
public class Base Item : Monobehavior
{
public string ItemName;
public int Price;
public virtual void PickUp(){//pickup logic}
//Additional functions. Update etc. Make them virtual.
}
此类设置项应执行的操作。然后在派生类中,可以更改和扩展此行为。
public class Coin : BaseItem
{
//properties set in the inspector
public override void PickUp(){//override pickup logic}
}
在过去的一年里,我经常使用这种设计模式,目前正在零售产品中使用它。我会说去吧!Unity 似乎更喜欢组件而不是继承,但您可以轻松地将它们相互结合使用。
希望这有帮助!
据我所知,这应该是安全的。如果您查看 Unity 实习生甚至Microsoft脚本,它们都会相互扩展/相互关联。
您可以尝试的另一件事是使用接口,这是它们的 Unity 文档:如果您想查看它,https://unity3d.com/learn/tutorials/topics/scripting/interfaces。
你说得对,GameObject.Find 是纯粹的代码气味。
您可以通过继承树(如前所述)甚至更好地通过接口(如 Assasin Bot 所述)或通过静态字段(又名 Singleton 模式)完成(我很惊讶之前没有人提到它)。
根据经验要补充的一件事 - 必须以特定顺序调用 Inits() 对您的设计来说是一个黄旗 - 我自己去过那里,发现自己被 init 订单管理淹没了。
作为一般建议:Unity 为您提供了两个有用的回调 - Awake() 和 Start()。如果你发现自己需要 Init(),你可能没有按照设计的方式使用这两个。
所有 Awakes() 都保证(对于 acvie 对象)在第一个 Start() 之前运行,因此在 Awake() 中进行所有内部对象初始化,并在 Start() 上绑定到外部对象。如果你发现自己需要更精细的控制 - 你应该简化一点设计。
根据经验:所有对象都应该在 Awake() 结束时按顺序具有其内部状态(getcomponents<>、list inits 等),但它们不应根据 Start() 之前准备好的其他对象进行任何调用。以这种方式拆分它通常有很大帮助