Zh/Entity Hierarchy (parenting): Difference between revisions

From Valve Developer Community
< Zh
Jump to navigation Jump to search
No edit summary
m (obsolete language category)
 
(11 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{otherlang2
{{LanguageBar|title = 实体层级(依赖关系)}}
|title=实体层级(依赖关系)
 
|en=Entity_Hierarchy_(parenting)
|ru=Entity_Hierarchy_(parenting):ru
|jp=Entity_Hierarchy_(parenting):jp
}}
本简体中文页面由 [[User:GlrWere|Gloria]] 汉化。
本简体中文页面由 [[User:GlrWere|Gloria]] 汉化。
{{toc-right}}
当一组实体“绑定(Parented)”到一起时,所有层级的实体就能严格一致地运动,表现得如同一个单独的物理对象。每个下层实体(child-entity)都会跟随上层实体(parent)的运动。
举个简单的例子,将一个 {{L|light_dynamic}} 实体绑定到一个实体类型为{{L|prop_physics|物理实体}}的台灯模型上,当台灯运动时,光源就会随台灯一起运动。
绑定关系始终都在'''下层'''实体的{{L|HammerObjectPropertiesDialog|对象属性}}中设定,上层实体无法控制绑定关系。(对英语用户来说)这种形式导致了文档中不得不使用反身动词(Parented)的形式进行说明,例如“必须被绑定到”“绑定下层实体到上层实体上”“实体可以有上层实体”这类神奇的表述。
*注:原文“parented”直译为“以xxx为双亲”。个人建议翻译成“绑定”,符合原意且易于说明和理解。


所有的实体都可以设置 parent 属性,尽管其中的一些{{L|Non-FGD features|在FGD中并不包含这个属性}},而且通常它们即便设置了 parent 也不一定能正常生效。例如,将 {{L|prop_physics}} 绑定到其他实体上时会表现得很奇怪,因为它们的运动是物理系统负责的;而对于一个 {{L|logic_relay}} 实体来说,它们既不会自己运动,也不可见,因此绑定它也没什么意义。对于物理实体来说,建议用 {{L|prop_dynamic}} 或 {{L|prop_dynamic_override}} 作为替代,或是使用{{L|constraint|物理约束系统}}。


当一组实体“绑定(Parented)”到一起时,整个层级的实体就能严格一致地运动,表现得如同一个单独的物理对象。每个子实体(child-entity)都会跟随父实体(parent)的运动。
{{Warning| 单组/单串嵌套的实体层级中最多允许 '''512''' 个实体 {{Todo|如果超过上限会怎么样?}}}}


最简单的例子是,将一个 [[light_dynamic]] 实体绑定到一个实体类型为[[prop_physics|物理实体]]的台灯模型上,这样光源就像台灯的一部分一样跟随着台灯模型运动。
== 下层实体特性 (Child Behavior) ==
* '''偏移量(Offset)''' 指的是实体与上层实体在绑定时的相对位置(以及角度)。偏移量会一直保持不变,下层实体的运动将会完全与上层实体的运动平行,并且在上层实体旋转时,绕着上层实体的原点“公转”。只有 ''SetParentAttachment'' 事件输入能够''修改''偏移量,它会将实体立即“传送”并维持在上层实体的绑定点上。


绑定关系是在子实体的[[HammerObjectPropertiesDialog|对象属性]]中设定的。父实体则无法控制谁绑定了它。这种形式导致了文档中不得不使用反身动词的形式进行说明,例如“必须被绑定到”“将子实体绑定到父实体”“实体必须有父实体”这类神奇的表述。
* '''碰撞箱(Collision)''' :下层实体自身的碰撞体在绑定后会被忽略,因此在上层实体运动时,可能会出现穿墙或其他穿模问题。受脚本控制的运动,例如动画、基于笔刷的实体,它们的碰撞箱仍然存在,因此你可以用各类笔刷实体来构建复杂的运动机械。
*注:“parented”是“parent”的过去分词形式,直译为“以xxx为双亲”。个人建议翻译成“绑定”,符合原意且易于说明和理解。


只有某些特定实体可以设置父实体属性。例如,[[prop_physics|物理实体]]不可以,因为它自身就是一个物理对象(但任何实体都能作为其它实体的父实体,如果被添加到了'parentname'属性栏中,尽管不都能正常工作)。这种情况下,可以使用 [[prop_dynamic]] 或 [[prop_dynamic_override]] 作为替代,或是使用 [[info_constraint_anchor]] 实体以连接成[[constraint|物理约束系统]]。
* 当上层实体收到 '''Killed''' 事件并被移除时,它当前的所有下层实体都将被从游戏中移除。


* '''Offset(偏移量)''' 指的是子实体与父实体的距离(包括任意角度的偏移量)。当应用了偏移量属性后,子实体将会平行于父实体运动,并且在父实体旋转时绕着父实体原点“公转”,只有 ''SetParentAttachment'' 事件输入能够''修改''偏移量;它会将子实体立即“传送”并维持在父实体的绑定点上。
* 如果下层实体没有定义与用户交互的事件,如(+USE)或是触碰,这些事件会被'''向上传递'''到上层实体。利用这一机制,我们可以将一个 {{L|prop_dynamic}} 绑定到一个 {{L|func_button}} 上;当用户对着 prop_dynamic 模型按下 +USE 键(使用键)时,实际上是在与按钮交互。


* '''碰撞箱''' :子实体的自身碰撞在绑定后会被忽略。它能够穿过墙或其它的固体对象。
==Parentname 属性==
在两个实体间创建绑定关系的方法是,将下层实体的 <code>parentname</code> 属性设置为上层实体的'''{{L|targetname|实体名称}}'''
* 维持偏移量。 {{Bug|{{L|Counter-Strike: Source|反恐精英:起源}} 中部分实体的 <code>parent</code> 属性存在异常。取而代之的是使用 {{L|logic_auto}} 实体,然后在地图开始时调用 <code>SetParent</code> 事件进行绑定。}}{{Bug| 在 {{L|Half-Life 2: Deathmatch|半条命2:死亡竞赛}}的Linux专用服务器中,实体可能会丢失绑定。因此,强烈建议使用 {{L|logic_auto}} 实体,并在输出中添加“<code>OnMapSpawn  child  SetParent  parent</code>”(其中:child 表示下层实体名称,parent 表示上层实体名称)}}
* 此外,如果要绑定到{{L|attachment|附着点(attachment point)}}上,可以通过 <code>parent,attachment</code> 的参数形式来进行设定。附着点的作用是,让其它实体可以绑定到某个模型的动画部分,例如{{l4d}}中的榴弹炮曲柄上。这种设置方法和
<code>SetParentAttachmentMaintainOffset</code> 类似。


* 当父实体收到 '''Killed''' 事件并被移除时,它当前的所有子实体都将被从游戏中移除。
[[File:L4D Handle prop Following attachment.gif|thumb|榴弹炮的手柄是一个单独的实体,它会跟随榴弹炮模型的 "Handle" {{L|$attachment|绑定点}}运动。]]


==Parentname属性==
== SetParent 输入事件 ==
为了在两个实体间创建父子关联,将子实体的 '''parentname属性''' 设置为父实体的'''[[targetname|实体名称]]'''。
你可以在实体上{{L|Inputs_and_Outputs|触发}}一个 <code>SetParent</code> 输入事件来更改绑定。
* 维持偏移量。 {{bug|[[Counter-Strike: Source|反恐精英:起源]] 中部分实体的父实体属性存在异常。取而代之,可以使用 [[logic_auto]] 实体,在地图开始时调用SetParent事件。}}{{bug|在Linux专用服务器上的 [[Half-Life 2: Deathmatch|半条命2:死亡竞赛]]中,子实体有时会丢失绑定。因此,强烈建议使用 [[logic_auto]] 实体,并在输出中添加“<code>OnMapSpawn  child  SetParent parent</code>”(其中:child 代指子实体名称,parent 代指父实体名称)}}
* 将上层实体的 ''targetname'' 作为 <code>SetParent</code> 的输入参数,来把实体绑定到该上层实体上。
* 此外,一个 [[attachment|附着点(attachment point)]]可以通过 '''parent,attachment''' 的参数形式来进行设定。它的作用就像 '''SetParentAttachmentMaintainOffset''' 一样。
* 如果参数一栏为空,则它的效果与 ''ClearParent'' 输入事件相同(见下方)。
* 偏移量会保持不变。


== SetParent输入事件 ==
== SetParentAttachment 输入事件 ==
你可以在子实体上[[Inputs_and_Outputs|触发]]一个 '''SetParent输入'''事件来更改绑定关联。
{{Note|在使用这个输入事件前,实体必须先完成绑定。在 <code>SetParent</code> 与 <code>SetParentAttachment</code> 两个输入事件之间必须至少有0.02秒的延时,以保证两个事件的执行顺序不会出错。}}
* 将 ''targetname'' 设置成新的父实体,作为 SetParent 的输入参数,来把子实体绑定到新的父实体上。
你还可以在下层实体上触发一个 <code>SetParentAttachment</code> 输入事件,用于将它绑定到上层实体的某个特定的{{L|attachment|附着点}}上。事件的参数为附着点的名称。
* 如果参数一栏为空,则它的效果与 ''ClearParent'' 输出事件相同(见下方)。
* 子实体会立即“传送”到附着点的位置。这是唯一一种''无法''保持偏移量不变的方法。
* 能够保持偏移量。


== SetParentAttachment输入事件 ==
== SetParentAttachmentMaintainOffset 输入事件 ==
{{note:zh-cn|在使用这个输入事件前,实体必须先完成绑定。在 ''SetParent'' ''SetParentAttachment'' 两个输入事件之间必须至少有0.01秒的延时。}}
{{Note|在使用这个输入事件前,实体必须先完成绑定。在 <code>SetParent</code> <code>SetParentAttachmentMaintainOffset</code> 两个输入事件之间设置至少0.02秒的延时,以保证两个事件按顺序执行,让实体附着到正确的位置上。如果延迟过短,实体的位置可能会不正确。}}
你还可以在子实体上[[Inputs_and_Outputs|触发]]一个 '''SetParentAttachment输入事件''',将它绑定到父实体的某个特定的[[attachment|附着点]]上。参数为附着点的名称。
你还可以在下层实体上{{L|Inputs_and_Outputs|触发}}一个 <code>SetParentAttachmentMaintainOffset</code> 输入事件,将它绑定到父实体的某个特定的{{L|attachment|附着点}}上。这部分的作用与 <code>SetParentAttachment</code> 输入事件完全一致,区别在于这个方法将会保持下层实体绑定到上层实体时的偏移量不变。
* 子实体会立即“传送”到附着点的位置。这是唯一一种无法保持偏移量的方法。
* 能够保持偏移量不变,但下层实体将会跟随附着点运动、旋转,而不是跟随上层实体的{{L|EntityOrigin|实体原点}}。


== SetParentAttachmentMaintainOffset输入事件 ==
== ClearParent 输入事件 ==
{{note:zh-cn|在使用这个输入事件前,实体必须先完成绑定。在 ''SetParent'' 与 ''SetParentAttachment'' 两个输入事件之间设置至少0.01秒的延时。}}
你还可以在下层实体上{{L|Inputs_and_Outputs|触发}}一个 <code>ClearParent</code> 输入事件来解除两个实体间的绑定关系。这个事件仅会将实体从它当前的上层实体上“解除绑定”、“分离”,这样该实体就能够独立于上层实体运动(或是静止)了。
你还可以在子实体上[[Inputs_and_Outputs|触发]]一个 '''SetParentAttachmentMaintainOffset输入事件''' 将它绑定到父实体的某个特定的[[attachment|附着点]]上。这部分的作用与 '''SetParentAttachment输入事件''' 完全一致,区别在于这个方法将会保持子实体绑定到父实体时的偏移量不变。
* 能够保持偏移量不变,但子实体将会跟随附着点运动、旋转而不是父实体的[[EntityOrigin|实体原点]]。
{{note:zh-cn|可以用逗号分隔父实体名称、附着点名称的形式将子实体直接绑定到父实体的附着点上,偏移量将会维持不变。<br />
例如 : Combine_Dead_Ragdoll,anim_attachment_RH }}


== ClearParent输入事件 ==
== KillHierarchy 输入事件 ==
你还可以在子实体上[[Inputs_and_Outputs|触发]]一个 '''ClearParent输入事件''' 来解除父子实体的绑定。This simply 'unparents' or 'detaches' the child-entity from its current parent, so the child is then free to move (or not) independently of its former parent.
{{Note|这是'''上层'''实体唯一与''运动层级''相关的输入事件。}}
如果在上层实体上{{L|Inputs_and_Outputs|触发}}一个 <code>KillHierarchy</code> 输入事件,会将该实体本身''以及''它下属的所有实体从世界移除。
* 如果在上层实体触发一个 <code>Kill</code> 事件,它所有的下层实体都会被游戏检测到并永久销毁,并在控制台中报出一条 warning(警告)。销毁几乎是在一瞬间完成的,但在完全清理干净之前,'''无法'''保证其中的一些逻辑不会继续执行、输出。


== KillHierarchy输入事件 ==
{{Bug|如果将 {{L|point_spotlight}} 实体绑定到其他实体上,并且仅使用输入输出事件删除了它绑定的上层实体时,该实体将生成在地图中心点(0,0,0)上,方向朝北。}}
{{note:zh-cn|这是'''父实体'''唯一与''运动层级''相关的输入事件。}}
如果在父实体[[Inputs_and_Outputs|触发]]一个 '''KillHierarchy输入事件''',会将父实体以及它所有的子实体从世界移除。
* 如果在父实体触发一个 '''Kill 输入事件''',也可以将父实体和它的子实体从世界移除。... ?


{{Bug|如果将 [[point_spotlight]] 实体作为其它实体的子实体,并且仅使用输入输出事件删除了父实体时,该实体将生成在地图中心点(0,0,0)上,朝向北面。}}
== 可选项 ==
在标准的实体层级系统之外还有一些“可选项”。它们或是有特殊的用途,或是专用于某些特定实体。


==FollowEntity()函数==
* {{L|Constraint|物理约束}}用于约束具有物理属性的实体,例如 prop_physics。可以实现摇晃、破碎之类各种炫酷的效果。
* {{L|logic_measure_movement}} 允许实体模仿其他实体的运动,同时也留有一定灵活调整的空间。可以用这个它来移动一些通常无法绑定的实体,例如逻辑实体、物理实体。
* {{L|prop_dynamic_ornament}} 可以使用骨骼系统(bonemerging),也就是将武器绑定到持有者手上的系统。它本质上还是在使用绑定系统。


程序开发者可以使用 <code>[[FollowEntity()]]</code> 以控制绑定关系。
程序开发者可以使用 <code>{{L|FollowEntity()}}</code> 来使用骨骼系统,而无需使用 prop_dynamitc_ornament。


[[Category:Level Design:zh-cn]]
{{ACategory|Level Design}}


==绑定的相关教程(俄文)==
==绑定的相关教程(俄文)==

Latest revision as of 04:14, 22 August 2024

English (en)Esperanto (eo)日本語 (ja)Русский (ru)中文 (zh)Translate (Translate)

本简体中文页面由 Gloria 汉化。

当一组实体“绑定(Parented)”到一起时,所有层级的实体就能严格一致地运动,表现得如同一个单独的物理对象。每个下层实体(child-entity)都会跟随上层实体(parent)的运动。

举个简单的例子,将一个 light_dynamic(en) 实体绑定到一个实体类型为物理实体(en)的台灯模型上,当台灯运动时,光源就会随台灯一起运动。

绑定关系始终都在下层实体的对象属性(en)中设定,上层实体无法控制绑定关系。(对英语用户来说)这种形式导致了文档中不得不使用反身动词(Parented)的形式进行说明,例如“必须被绑定到”“绑定下层实体到上层实体上”“实体可以有上层实体”这类神奇的表述。

  • 注:原文“parented”直译为“以xxx为双亲”。个人建议翻译成“绑定”,符合原意且易于说明和理解。

所有的实体都可以设置 parent 属性,尽管其中的一些在FGD中并不包含这个属性(en),而且通常它们即便设置了 parent 也不一定能正常生效。例如,将 prop_physics(en) 绑定到其他实体上时会表现得很奇怪,因为它们的运动是物理系统负责的;而对于一个 logic_relay(en) 实体来说,它们既不会自己运动,也不可见,因此绑定它也没什么意义。对于物理实体来说,建议用 prop_dynamic(en)prop_dynamic_override(en) 作为替代,或是使用物理约束系统(en)

Warning.png警告: 单组/单串嵌套的实体层级中最多允许 512 个实体
待完善: 如果超过上限会怎么样?

下层实体特性 (Child Behavior)

  • 偏移量(Offset) 指的是实体与上层实体在绑定时的相对位置(以及角度)。偏移量会一直保持不变,下层实体的运动将会完全与上层实体的运动平行,并且在上层实体旋转时,绕着上层实体的原点“公转”。只有 SetParentAttachment 事件输入能够修改偏移量,它会将实体立即“传送”并维持在上层实体的绑定点上。
  • 碰撞箱(Collision) :下层实体自身的碰撞体在绑定后会被忽略,因此在上层实体运动时,可能会出现穿墙或其他穿模问题。受脚本控制的运动,例如动画、基于笔刷的实体,它们的碰撞箱仍然存在,因此你可以用各类笔刷实体来构建复杂的运动机械。
  • 当上层实体收到 Killed 事件并被移除时,它当前的所有下层实体都将被从游戏中移除。
  • 如果下层实体没有定义与用户交互的事件,如(+USE)或是触碰,这些事件会被向上传递到上层实体。利用这一机制,我们可以将一个 prop_dynamic(en) 绑定到一个 func_button(en) 上;当用户对着 prop_dynamic 模型按下 +USE 键(使用键)时,实际上是在与按钮交互。

Parentname 属性

在两个实体间创建绑定关系的方法是,将下层实体的 parentname 属性设置为上层实体的实体名称(en)

  • 维持偏移量。
    Icon-Bug.png错误:反恐精英:起源(en) 中部分实体的 parent 属性存在异常。取而代之的是使用 logic_auto(en) 实体,然后在地图开始时调用 SetParent 事件进行绑定。  [todo tested in ?]
    Icon-Bug.png错误:半条命2:死亡竞赛(en)的Linux专用服务器中,实体可能会丢失绑定。因此,强烈建议使用 logic_auto(en) 实体,并在输出中添加“OnMapSpawn child SetParent parent”(其中:child 表示下层实体名称,parent 表示上层实体名称)  [todo tested in ?]
  • 此外,如果要绑定到附着点(attachment point)(en)上,可以通过 parent,attachment 的参数形式来进行设定。附着点的作用是,让其它实体可以绑定到某个模型的动画部分,例如求生之路中的榴弹炮曲柄上。这种设置方法和

SetParentAttachmentMaintainOffset 类似。

榴弹炮的手柄是一个单独的实体,它会跟随榴弹炮模型的 "Handle" 绑定点(en)运动。

SetParent 输入事件

你可以在实体上触发(en)一个 SetParent 输入事件来更改绑定。

  • 将上层实体的 targetname 作为 SetParent 的输入参数,来把实体绑定到该上层实体上。
  • 如果参数一栏为空,则它的效果与 ClearParent 输入事件相同(见下方)。
  • 偏移量会保持不变。

SetParentAttachment 输入事件

Note.png注意:在使用这个输入事件前,实体必须先完成绑定。在 SetParentSetParentAttachment 两个输入事件之间必须至少有0.02秒的延时,以保证两个事件的执行顺序不会出错。

你还可以在下层实体上触发一个 SetParentAttachment 输入事件,用于将它绑定到上层实体的某个特定的附着点(en)上。事件的参数为附着点的名称。

  • 子实体会立即“传送”到附着点的位置。这是唯一一种无法保持偏移量不变的方法。

SetParentAttachmentMaintainOffset 输入事件

Note.png注意:在使用这个输入事件前,实体必须先完成绑定。在 SetParentSetParentAttachmentMaintainOffset 两个输入事件之间设置至少0.02秒的延时,以保证两个事件按顺序执行,让实体附着到正确的位置上。如果延迟过短,实体的位置可能会不正确。

你还可以在下层实体上触发(en)一个 SetParentAttachmentMaintainOffset 输入事件,将它绑定到父实体的某个特定的附着点(en)上。这部分的作用与 SetParentAttachment 输入事件完全一致,区别在于这个方法将会保持下层实体绑定到上层实体时的偏移量不变。

  • 能够保持偏移量不变,但下层实体将会跟随附着点运动、旋转,而不是跟随上层实体的实体原点(en)

ClearParent 输入事件

你还可以在下层实体上触发(en)一个 ClearParent 输入事件来解除两个实体间的绑定关系。这个事件仅会将实体从它当前的上层实体上“解除绑定”、“分离”,这样该实体就能够独立于上层实体运动(或是静止)了。

KillHierarchy 输入事件

Note.png注意:这是上层实体唯一与运动层级相关的输入事件。

如果在上层实体上触发(en)一个 KillHierarchy 输入事件,会将该实体本身以及它下属的所有实体从世界移除。

  • 如果在上层实体触发一个 Kill 事件,它所有的下层实体都会被游戏检测到并永久销毁,并在控制台中报出一条 warning(警告)。销毁几乎是在一瞬间完成的,但在完全清理干净之前,无法保证其中的一些逻辑不会继续执行、输出。
Icon-Bug.png错误:如果将 point_spotlight(en) 实体绑定到其他实体上,并且仅使用输入输出事件删除了它绑定的上层实体时,该实体将生成在地图中心点(0,0,0)上,方向朝北。  [todo tested in ?]

可选项

在标准的实体层级系统之外还有一些“可选项”。它们或是有特殊的用途,或是专用于某些特定实体。

  • 物理约束(en)用于约束具有物理属性的实体,例如 prop_physics。可以实现摇晃、破碎之类各种炫酷的效果。
  • logic_measure_movement(en) 允许实体模仿其他实体的运动,同时也留有一定灵活调整的空间。可以用这个它来移动一些通常无法绑定的实体,例如逻辑实体、物理实体。
  • prop_dynamic_ornament(en) 可以使用骨骼系统(bonemerging),也就是将武器绑定到持有者手上的系统。它本质上还是在使用绑定系统。

程序开发者可以使用 FollowEntity()(en) 来使用骨骼系统,而无需使用 prop_dynamitc_ornament。

绑定的相关教程(俄文)

教程由 Project-S 制作。

All about Parent (Всё о Parent)