约束 API
本页描述 VRChat 约束的应用程序编程接口(API)。它包含可以从 Udon 用于世界开发以及从 C# 用于 SDK 工具开发的面向公共的属性和方法。
前提条件
在使用此 API 之前,你应该已经了解 VRChat 约束的基本概念。
应避免使用此页面未记录的属性或方法,因为它们可能随时从公共接口中移除。
约束类型
API 为 VRChat 约束提供了以下面向用户的类型,全部位于命名空间 VRC.SDK3.Dynamics.Constraint.Components 中:
- VRCAimConstraint
- VRCLookAtConstraint
- VRCParentConstraint
- VRCPositionConstraint
- VRCRotationConstraint
- VRCScaleConstraint
在命名空间 VRC.Dynamics 中还有以下支持类:
- VRCConstraintSource - 单个约束源,包含
SourceTransform和Weight - VRCConstraintSourceKeyableList - 约束使用的源列表。
约束属性和方法
通用属性和方法
所有 VRChat 约束都公开了下面列出的属性。请注意,虽然这些与 Unity 约束 可用的属性基本相同,但两个接口并不完全相同,并且存在一些支持 VRChat 客户端运行的结构性差异。
ApplyConfigurationChanges()
此方法应用通过脚本对约束所做的任何更改。在通过脚本修改约束的属性后,必须调用此方法! 否则,你的更改可能不会应用到约束。
如果你需要同时更改多个属性,应尽量在完成所有更改后仅调用此方法一次,以最小化性能影响。
IsActive
bool:如果约束当前正在被评估,则为true,否则为false。
功能上与 Unity 的 constraintActive 属性相同。
GlobalWeight
float:此约束的全局权重,应用于其所有源之上(源也有自己的单独权重)。
功能上与 Unity 的 weight 属性相同。
Locked
bool:如果约束当前已锁定,则为true;如果未锁定,则为false。
功能上与 Unity 的 locked 属性相同。
在播放模式下,约束始终被视为已锁定。
Sources
VRCConstraintSourceKeyableList:属于此约束的源列表。
例如,以下代码示例通过遍历 每个源、更改其权重然后将其重新分配回列表,来随机化分配给特定约束的每个源的权重:
for (int i = 0; i < constraint.Sources.Count; i++)
{
VRCConstraintSource source = constraint.Sources[i];
source.Weight = UnityEngine.Random.value;
constraint.Sources[i] = source;
}
你可以通过获取源列表并在其上调用 Add() 以编程方式向约束添加源:
// 创建一个以权重 1.0 针对此变换的新约束源。
VRCConstraintSource source = new VRCConstraintSource(transform, 1.0f);
// 将此源添加到约束。
constraint.Sources.Add(source);
要移除源,你可以使用 Remove() 传入与添加时相同的源结构体,或通过索引查找特定现有源并使用 RemoveAt()。
// 移除特定源...
constraint.Sources.Remove(source);
// ...或者移除索引 i 处的源。
constraint.Sources.RemoveAt(i);
源列表有一个特殊限制:在化身上,只有前十六个元素可以被动画控制器定位。这是由于 Unity 引擎处理数组元素动画的方式以及需要与某些用户制作的动画工具保持兼容性。如果你计划为 Avatars SDK 编写向单个约束添加超过十六个源的工具,请记住此限制。
TargetTransform
Transform:受此约束组件结果影响的变换。
当设置为 null 时,约束将其结果应用于其附加到的变换。
SolveInLocalSpace
bool:如果此约束在本地空间中求解,则为true;如果在世界空间中求解,则为false。
Unity 约束始终在世界空间中求解。
FreezeToWorld
bool:如果此约束当前正试图保持在世界空间中的固定位置/旋转/缩放,则为true,否则为false。
约束在其从 false 切换到 true 时捕获当前姿势,并尝试保持该姿势直到下次切换回 false。
RebakeOffsetsWhenUnfrozen
bool:如果约束在解冻时应重新计算其相对于源的偏移,则为true;如果应保持其原始偏移,则为false。
这是 FreezeToWorld 的子属性,控制此约束在解冻时(即 FreezeToWorld 从 true 切换到 false 时)的行为。
ActivateConstraint()
在约束上调用此方法会激活并锁定它,同时保持其当前偏移。相当于在编辑器中按下约束检查器中的 Activate 按钮。
ZeroConstraint()
在约束上调用此方法会激活并锁定它,同时将其偏移重置为默认值。相当于在编辑器中按下约束检查器中的 Zero 按钮。
静止值和偏移值
每种类型的约束以各自的方式影响变换,因此每种类型都有其自己的静止值和偏移值,可以通过相应命名的属性进行访问。例如,位置约束具有 PositionAtRest 和 PositionOffset,各表示与源的距离,而旋转约束具有 RotationAtRest 和 RotationOffset,各表示一组欧拉角。
父约束是特殊的,因为每个源都有一个偏移值,而不是只有一个偏移影响整个约束。要更改应用于父约束的偏移,请通过 Sources 列表访问其源,然后修改其中的 ParentPositionOffset 和 ParentRotationOffset 属性。
瞄准约束对齐
这些是 VRChat 瞄准约束特有的属性,控制它们如何朝向目标对齐。
AimAxis
Vector3:应朝向源的轴 。
这有效地定义了哪个方向应被视为前方。
UpAxis
Vector3:此约束视为向上的轴。
约束尝试将此方向与下面描述的 WorldUp 指定的向上的方向对齐。
WorldUpTransform
Transform:用于确定约束向上向量的变换。
这仅与下面描述的某些 WorldUp 值一起使用。
WorldUpVector
Vector3:用于确定约束向上向量的方向。
这仅与下面描述的某些 WorldUp 值一起使用。
WorldUp
这是一个枚举类型,确定此瞄准约束的哪个方向被视为向上。选项如下:
WorldUpType.SceneUp:将向上视为场景的正 Y 轴(Vector3.up)。WorldUpType.ObjectUp:将向上视为从约束的目标变换指向WorldUpTransform属性中指定的变换的向量。WorldUpType.ObjectRotationUp:将向上视为WorldUpTransform中指定的变换的本地空间中的WorldUpVector轴。WorldUpType.Vector:将向上视为世界空间中的WorldUpVector。WorldUpType.None:不定义向上的方向。
WorldUp 的类型为 VRCConstraintBase.WorldUpType,这是命名空间 VRC.Dynamics 中的一个枚举。
注视约束对齐
与瞄准约束类似,注视约束具有一些控制它们如何朝向目标对齐的属性。注视约束实际上是简化的瞄准约束。
Roll
float:定义应围绕约束 Z 轴用于确定其向上方向的角度(以度为单位)。
此属性仅在 UseUpTransform 为 false 时有效。
WorldUpTransform
Transform:使约束向其滚转的变换。
此属性仅在 UseUpTransform 为 true 时有效。
UseUpTransform
bool:如果约束使用Roll的值来确定约束的倾斜方式,则为false;当其滚转以尝试将其正 Y 轴指向WorldUpTransform指定的 变换时,则为true。
约束转换钩子
此部分仅与想要更改 Unity 约束在化身上如何转换为 VRChat 约束的用户相关。
本节描述的功能不适用于 Udon 脚本。
当 SDK 自动将 Unity 约束转换为 VRChat 约束时,约束转换器运行。你可以编写自己的 C# 自定义编辑器工具,与 SDK 的约束转换器交互。
请查看工具的内联文档以获取完整文档,因为本节仅提供简要摘要。
转换方法
SDK 类 AvatarDynamicsSetup 包含 SDK 用于将 Unity 约束转换为等效 VRChat 约束的转换方法。以下约束转换方法对用户工具开放:
| 方法 | 描述 |
|---|---|
ConvertUnityConstraintsAcrossGameObjects(List<GameObject> targetGameObjects) | 将指定游戏对象列表上的 Unity 约束转换为 VRChat 约束。 |
ConvertUnityConstraintsAcrossAnimationClips(List<AnimationClip> targetAnimationClips) | 修改动画剪辑列表,使其中的任何 针对 Unity 约束的轨道更新为针对 VRChat 约束。 |
DoConvertUnityConstraints(IConstraint[] unityConstraints, VRCAvatarDescriptor avatarDescriptor, bool convertReferencedAnimationClips) | 将 Unity 约束数组转换为 VRChat 约束,可选地包括任何引用的动画剪辑。此操作立即执行,无确认对话框。 |
RebindConstraintAnimationClip(AnimationClip clip, IConstraint oldConstraint) | 尝试修改单个动画剪辑,将轨道从 Unity 约束重新定位到 VRChat 约束,可选地限制转换到给定的 Unity 约束。 |
TryGetSubstituteAnimationBinding(Type unityConstraintType, string unityConstraintPropertyName, out Type vrcConstraintType, out string vrcConstraintPropertyName, out bool isArrayProperty) | 尝试将 Unity 约束属性名称和类型转换为等效的 VRChat 约束属性名称和类型。 |
转换委托
为了补充上述方法,AvatarDynamicsSetup 类还提供了委托函数,允许你的工具控制转换器的行为。以下委托可用:
| 委托 | 描述 |
|---|---|
bool IsUnityConstraintAutoConverted(IConstraint constraint) | 给定一个 Unity 约束,如果此约束将在构建时由用户工具转换为 VRChat 约束,则返回 true。你可以使用此方法抑制 SDK 通常生成的验证警告,提示用户将其 Unity 约束转换为 VRChat 约束。 |
bool ConvertUnityConstraintsAcrossGameObjects(List<GameObject> gameObjects, bool isAutoFix) | 给定游戏对象列表,将它们上的所有约束和底层动画剪辑转换为 VRChat 约束。如果此操作由用户点击验 证列表中的自动修复触发,则 isAutoFix 参数为 true;如果由菜单条目或自定义用户脚本触发,则为 false。返回 true 以防止本机 SDK 转换器运行。 |
bool ConvertUnityConstraintsAcrossAnimationClips(List<AnimationClip> animationClips) | 给定动画剪辑列表,更新所有引用 Unity 约束的轨道改为引用 VRChat 约束。返回 true 以防止本机 SDK 转换器运行。 |