我一直在学习Unity基础知识,但是想加深我对组件和拥有它们的对象之间的关系的理解。在我观看的教程中,当处理拉入代码的对象时,通常使用或传递Transform组件。例如:
void Explode ()
{
Collider[] colliders = Physics.OverlapSphere(transform.position, explosionRadius);
foreach (Collider collider in colliders)
{
if (collider.tag == "Enemy")
{
Damage(collider.transform);
}
}
}
在找到的对撞机上进行变换后调用“损坏”:
void Damage (Transform enemy)
{
Enemy e = enemy.GetComponent<Enemy>();
if (e != null)
{
e.TakeDamage(damage);
}
}
很明显,这是在拉取所有游戏对象上找到的Component,然后使用“ GetComponent”按名称拉取另一个组件实例,因为“ Enemy”组件不会有自己的方法。为什么不通过collider.gameObject呢?我尝试了此操作(在更改了损害以期望使用GameObject之后),并且工作正常。
对我来说,这似乎更直观,但是我看过的所有教程都使用了transform组件。有人对此有何见解?这将有助于我加深对Unity如何构造其代码的理解。
答案 0 :(得分:1)
我不确定您要遵循哪些教程,但是当我第一次使用Unity时所遵循的教程是使用GameObject而不是Transform。
我同意使用GameObject更直观。变换是GameObject的一部分或Component
,但由于它是强制性的,因此始终存在,因此是公共字段.transform
。但是,由于GameObject从技术上来说是其所有组件的所有者,因此从架构角度来讲,将其作为参数传递是最合乎逻辑的。
最终,由于您可以在两个Transform上调用许多与GameObject相同的方法,因此示例之间的区别不大。
TLDR:
使用您认为最有意义的方式。
答案 1 :(得分:0)
简短答案
您所说的GameObject更直观。
好答案
我认为(我认为)最好通过最具体,最相关的组成部分。
例如,假设您有一个角色可以捡起板条箱:
public void PickUp(Transform crate)
{
crate.SetParent(this.transform);
crate.localPosition = Vector3.zero; // or whatever your attachment point is
}
在我看来,传递Transform是有道理的,因为它是最需要的特定组件。通过在此处传递GameObject只会延迟不可避免的GetComponent<Transform>
或go.transform
。 / p>
另一方面,如果您具有隐藏创建的功能,则传递游戏对象将是您实现这一目标的最低要求:
public void Hide(GameObject crate)
{
crate.SetActive(false);
}
传递其他任何内容只会延迟不可避免的x.gameObject
在爆炸示例中,老实说,我认为我不会通过。我可能会这样做:
void Explode ()
{
Collider[] colliders = Physics.OverlapSphere(transform.position, explosionRadius);
var enemies = colliders
.Select(x => x.GetComponent<Enemy>())
.OfType<Enemy>(); // Or IHealth, IDamageable, ITarget, etc if you have other things that can take damage.
foreach (var enemy in enemies) // If empty, nothing will happen by default
{
enemy.TakeDamage(damage);
}
}
使用这种方法,您可以看到不需要检查标记或空值。可枚举的敌人可以保证完全不包含任何敌人。
通过始终传递gameObject / transforms,您将始终需要担心目标组件真正收到的是什么。您还将对无法确定对GameObjects进行某些更改的情况敞开心situations,因为它可能是系统中进行更改的任何内容。您的ColorChangerComponent
实际上也可能在移动对象,破坏了其他一些组件,等等。通过为组件提供渲染器,它更自然地将组件限制为仅在渲染器上进行更改(尽管您显然会违反此限制,除非您可以针对适当的界面执行操作。
唯一有意义的事情是传递通用组件,是当您将“事件”广播给一堆可能的接收者时,每个接收者将对该对象进行不同的处理。即您不能在编译时确定游戏对象将用于什么,或者您知道它将用于许多不同的事情。
Unity本身为冲突检查返回Collider[]
的事实支持了这种思路,否则它将仅返回GameObject[]
。 OnTriggerEnter(Collider collider)
或OnCollisionEnter(Collision collision)
等也是如此。