Unity如何与C#类一起工作

7

我之前学习了纯C#,但我认为Unity中(使用C#)的脚本编写有点不够直观。

例如,似乎大多数人(尤其是初学者)在Unity中使用脚本的最常见方式是创建一个“单次使用”类型的脚本,并将其附加到实际的游戏对象上(通过点击并将其拖动到脚本组件)。这种情况下,继承的使用似乎非常少。或者我可能弄反了。我应该在Game Objects外部创建类/继承,然后仅将引用这些外部类的脚本附加到Game Objects上吗?我确信你们中的一些人可能会说“做任何你想做的!”或“做有效果的事情”,但我不想从不良的编码方法开始,最终在以后进行重构。

另一件让我困惑的事情是Unity中的类实例。出于某种原因,似乎我可以使用内置的类(如Animator)而无需对其进行实例化[我几乎从未看到a = new Class();],但这些类并不是静态的。这是如何工作的呢?如果我构建自己的类,并且这些类被我的游戏对象引用,那么我是否必须创建实例才能使用它们,或者引擎在幕后自动处理所有这些内容?

那么,在所有这些脚本编写中,游戏对象(在编辑器中的实际项目)在哪里?是否为每个Game Object都创建了一个类?如果是这样,我该如何找到它并查看其中发生的情况?


6
翻译:请了解一下组件化设计(游戏)。每个脚本都是继承自MonoBehaviour的组件。实际上很少需要对组件进行子类化,从类层次结构的角度来看,平面设计更为可取和推荐,适用于游戏编程。 - CodeSmile
必须同意上面的评论。我曾经试图强制使用层次结构和基于继承的模型,结果自己给自己带来了很大麻烦。不仅在Unity中实现起来很麻烦,而且在保存游戏(序列化)方面也变得更加困难。 - Jens
扁平化设计对游戏有益?我之前没有听说过。在我的游戏《Goin' Mental》中,当我的敌人从基础敌人类派生时,继承层次结构对我很有用。 - Kyle Delaney
3个回答

2
继承在Unity中与其他框架一样非常重要。假设你想实现两种类型的敌人,它们都有一些共同的行为(行走、攻击),也都有特定的行为(A可以飞行,但B使用路径查找攻击)。你需要设计一个抽象的Enemy类,该类继承自MonoBehaviour(顺便说一句,脚本继承自MonoBehaviour,而MonoBehaviour又继承自Behaviour,因此继承就在这里了),然后每个敌人都从Enemy继承而来。这样做更易于维护,也更方便使用你的敌人。FlyingEnemy和PathEnemy可以存储在类型为Enemy的集合中,以便你可以对其进行迭代以执行共同的敌人动作(比如死亡)。
接口也非常有用,因为你可以拥有一个可以命中关卡中任何物体的投射物。投射物会检查被击中的GameObject是否包含IDamageable组件,如果是,则调用接口的Damage方法。这样可以命中任何物体,无需知道它是玩家、敌人还是墙壁。每个物体都在自己的脚本中实现接口,并且该方法只执行相关的操作。
如果没有这个功能,你的投射物将不得不经过一长串的检查,才能知道它是哪个物体。

1
我在Unity中制作了一些游戏,根据我的经验,继承几乎从未有用过。这是因为Unity不是以面向对象编程为主要考虑因素,而是以组件导向编程为主要考虑因素,即您制作小型、单一目的的组件(脚本),并将它们粘合在一起以创建游戏对象。
当您将脚本添加到游戏对象中时,引擎将为您完成new Class(); 的工作。这意味着每个游戏对象都有与其附加的每个脚本实例。这对所有脚本都适用,包括您创建的脚本和Unity中已经存在的脚本,如Transform和Animator。当然,这仅适用于从MonoBehaviour继承的Unity脚本,因为它们是您可以添加到游戏对象中的唯一内容。
您在场景层次结构中看到的游戏对象是GameObject类的实例。要了解其工作原理,建议只需阅读文档,但如果您想深入了解游戏对象,则需要使用类似于Telrik JustDecompile或Reflector的工具进行反汇编。

1
你也可以使用.gameObject属性从任何组件/MonoBehaviour实例中访问GameObject实例。 - Dan Puzey
“继承几乎从来没有用处”这种说法是完全错误的,可能是最糟糕的建议之一。Unity是组件驱动的,当然,但这并不意味着它不是面向对象编程(OOP)。组件还意味着可重用性,设计武器时,您会将所有通用信息存储在Weapon抽象类中,并使子类从中继承。然后您的霰弹枪将执行特定的霰弹枪操作,而您的机枪将执行MG操作。此外,它将使用某些接口进行伤害或其他行为。这就是OOP和继承。 - Everts

0
在Unity中,继承是以一种简单的方式进行的,因为Unity试图使用组件模型而不是层次结构模型。但是说它很简单并不意味着它不存在。
当您创建一个新类时,它会从MonoBehaviour中继承,这是一个具有对象在引擎中工作所需功能的类。
如果您想使用脚本创建层次结构模型,则可能需要将所有基类创建为MonoBehaviour的子类,然后从中继承。请参阅@Everts示例 > 假设您想要实现两种类型的敌人,它们都具有某些共同的行为(行走、攻击),并且都具有特定的行为(A可以飞行,但B使用路径查找攻击)。您应该设计一个抽象的Enemy类来继承自MonoBehaviour,然后每个敌人类型都继承自Enemy。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接