# 物体

LLMS 索引： [llms.txt](/dvw/llms.txt)

---

虚拟世界里处理物体的准则是：把一切都整合起来。

实现一个虚拟世界时，构成它的那些实体就是它的对象。这些实体之间的关系就是它们的属性。对象与属性合在一起，构成了虚拟世界中可触摸的部分，而物理赋予这部分以生命。事情并不非得如此——理论上你可以设计出这样一种系统：对象只是基本方程之间相互作用的产物，就像数字那样。你要是打算那么做，祝你好运。

设计者必须认识到：虽然他们的虚拟世界里许多对象与另一些对象在特性上千差万别，但从根本上说它们是同一回事。它们可以被归入一些在概念上有用的分组——玩家角色、活动生物、容器、房间、可携带物体、固定景物，等等——但把这些分组当成互不相干、彼此隔绝的集合，是一个大错。如果你把它们看作一个通用抽象对象的特化，而不是各自抽象层级的根，你会得到好得多的一致性（也对自己这个世界理解得好得多）。

举例来说，假设你决定让自己的玩家角色拥有一个 “health”（生命值）属性。那么用这同一个属性来记录活动生物的生命值，就是很自然的一步。你也许还想给普通物体一个 “wear”（磨损）评分，用来追踪它们离散架还有多远。那么你就应当想到，“wear” 衡量的东西和 “health” 是同一类，因此你该用 “health” 而不是 “wear” [^81]。

这也许显得相当显而易见，但很多时候它偏偏不是 [^82]。早期，MUD 设计者同时也都是程序员。直到他们接触了面向对象编程语言的思想之后，其中一些人才愿意承认：嘿，也许房间和玩家角色说到底就只是对象而已？这有点讽刺，因为事实证明，虚拟世界的对象与 C++ 这类面向对象编程语言里的对象对应得并不好。要解释为什么，我得先岔开一段（不过我会尽量说得短些）。

在面向对象编程语言里，有一个对象类的层级。单个对象是某个类的实例。因此，你可以说达布隆是一种硬币，硬币属于财宝这一类，财宝是一种可携带物体，可携带物体是一种（根）对象。虽然我在这里用了 “object” 这个词，但在编程的意义上，这些应当叫类。Doubloon33 可能是 “doubloon” 这个类的一个实例，那样它才是一个对象。面向对象编程的威力在于它能消除重复：我不必去定义 “get doubloon1”、“get doubloon2” 等等，只需要定义 “get doubloon”。

如果对象可以是多个类的实例，或者类可以是多个超类的子类，你拥有的就是多重继承系统。否则就是单继承系统。对虚拟世界设计来说，多重继承系统极为便利。如果一个房间里有达布隆、一便士和一只明代花瓶，那么当我发出 “get coin” 命令时，我想要的是把达布隆和便士捡起来；如果我试着发 “get antique”，我想要的是达布隆和那只花瓶。达布隆既是硬币又是古董，但并不是所有硬币都是古董，也不是所有古董都是硬币。这种情况很常见：并非所有哺乳动物都是食肉动物，也并非所有食肉动物都是哺乳动物；并非所有流行歌手都是男性，也并非所有男性都是流行歌手。方块皇后主要是一张方块，还是主要是一位皇后？

遗憾的是，程序员很可能想用 C++ 或它的某个衍生品（例如 Java），而这些语言只支持单继承<em>{勘误：C++ 其实确实有某种形式的多重继承，用的（说来有点讽刺）是 `virtual` 关键字。}</em>。他们看到虚拟世界里有 “对象”，就把它们对应到自己那套面向对象系统里的 “对象” 上，然后在编码进行到 95% 的时候撞上麻烦。在单继承系统里伪造多重继承是可能的，正如在扁平系统里伪造单继承也是可能的。这要花很多工夫，里面还有大量重复；不过仍然办得到。

办不到的是命令的继承。面向对象编程会把一段段代码（称为方法）关联到对象类上。这些方法本身不是对象；它们不存在于继承树里。换句话说，我不能说 “punch” 方法是 “hit” 方法的子类。如果我想要 30 种不同的打东西方式，就必须把它们一一实现。如果我想让效果随被打对象的软硬而不同，每一种都得把这套逻辑重写一遍。对大型或复杂的虚拟世界来说，这很快就会变得令人抓狂地枯燥，无论实现还是维护都是如此。面向对象编程的目的是消除无谓的重复，不是制造重复。

出现这种局面，是因为虚拟世界的 “对象” 对编程语言里的 “对象” 来说是个糟糕的选择。应当把命令当作对象才对。如果把 “hit object” 和 “hit soft_object” 定义成（面向对象的）类，那么像 “slap cushion” 这样的命令就是某个命令类（在这里就是后一个）的实例，据此就能找到并运行对应的代码。这本质上是个编程问题，而不是设计问题，但由于虚拟世界的历史包袱，它已经进入了设计范式。设计者往往按对象和方法来思考，而他们本该思考的是多重继承的层级和命令。

好，题外话到此为止。

所以，虚拟世界里的对象类通常会被组织成某种层级。这样可以共享属性，共享属性会促成整合，整合又带来一致性。那种因为 “hit” 这个名字已经被 “hit creature” 占用、只能改用 “ring bell” 的日子已经过去了 [^83]。

如果去问，大多数设计者大概都会赞成整合是好事这个想法。可惜的是，他们往往并不怎么考虑这件事。比如说，法术与技能有很多共同之处——它们都是把某项专门任务做到某一水准的能力，而这种能力是必须学来的。但很少有虚拟世界认为这两者有任何关联。同样，器物也能以效果或附魔的形式，拥有玩家角色靠技能或法术拥有的那种东西。如果我能学会施放闪电箭法术，那为什么不能教会一根魔法法杖也这么做？这种思路已经在单人角色扮演游戏里用过，例如拉瑞安工作室（Larian Studios）的《神界》（Divine Divinity），但在虚拟世界里并不常见。

关于物体的这一大段讨论，虽然大多讲的都是文字世界，但它同样适用于图形世界。

图形世界在功能上一般远不如文字世界丰富，但差距正在缩小；迟早有一天，用单继承来组织虚拟对象类会成为一个问题。没有多重继承、也没有对动作进行量化的能力，你能走完 95% 的路程，但到了那最后的 5%，这两样东西就会变得很重要。


[^81]: 只是要确保不会有人跑去铁匠铺治伤，或者找治疗师给剑重新开刃。
[^82]: 至今还有很多虚拟世界认为，把物体丢在地上与把物体放进背包是完全不同的两种动作。
[^83]: 你注意到那处讽刺了吧？
