Hand Bone

  • HandBone is a fairly important script in OctoXR, it is attached to every GameObject that acts as a hand bone in a HandSkeleton

  • It is relatively useless on its own, it only plays an important role when added to a HandSkeleton

  • Unlike the HandSkeleton, this class is not abstract, it can be used as is without the need for implementing a concrete HandBone first - it all depends on the particular HandSkeleton that the HandBone should be added to

  • Some HandSkeletons can work with bones whose exact type is HandBone, most HandSkeletons in OctoXR support any kind of HandBone derived components too, there are many flavours of HandBones defined throughout OctoXR package and it is not difficult at all to define a new custom type of HandBone

  • In most cases there is no need to manually add this component to a GameObject as usually it will be added to one by a specific HandSkeleton when attaching the GameObject as a hand bone to it. However, if there is a need to attach multiple different types of HandBones to the same HandSkeleton then it will be necessary to manually add specific HandBone derived components to their corresponding GameObjects first and then add those GameObjects to the HandSkeleton

  • HandBones are controlled by the HandSkeletons they are added to, i.e. their poses and scales are updated by their HandSkeletons. For this reason it is important to be mindful about what GameObjects they are added to and what other components are added to those GameObjects. For example it wouldn't make much sense to attach Rigibody to the GameObject acting as a HandSkeleton's bone because that object's pose will then be controlled by physics and HandSkeleton the bone is attached to will constantly clash with the physics when it comes to updating the object's pose. Of course this depends on the specific type of HandSkeleton, some HandSkeletons drive their HandBones' poses using physics and physics related components like rigid bodies and joints. When it comes to HandBones defined in OctoXR, any additional components required to be added to the same GameObject the HandBone is added to are explicitly required by the HandBone, so there is never a need to manually add the HandBone's dependencies, it all gets taken care of automatically

  • This script executes in edit mode as well, so all of the methods and members described in the following text are being called/handled in edit-time too

Public properties

HandSkeleton HandSkeleton { get; }

  • HandSkeleton that the bone is attached to, null if it is not added to one

  • This property is visible in the HandBone's inspector, but as a read-only

HandBoneId BoneId { get; }

  • Identity of the HandBone in its current HandSkeleton. Value of this property does not matter at all if the HandBone is not in a HandSkeleton

  • Like HandSkeleton property, it is exposed in the HandBone's inspector as a read-only field

  • HandBone's identity is constant while it is in a particular HandSkeleton, but it can be changed if the HandBone is removed from one HandSkeleton and then added back to it or added to some other HandSkeleton under different identity, meaning this property does not play any role when HandBone is being added to a HandSkeleton

bool IsRootBone { get; }

  • Specifies whether the HandBone is a root bone, i.e. whether it is identified as the Wrist bone

Transform Transform { get; }

  • Reference to the Transform attached to the HandBone, i.e. Transform attached to the HandBone's GameObject

HandBone ParentBone { get; }

  • Reference to the HandBone's parent bone from the same HandSkeleton it is added to. This is null if the HandBone is not in a HandSkeleton

  • This does not necessarily correspond to the HandBone's natural parent bone since the HandSkeleton may not have one added to it, but because a HandSkeleton always has the WristRoot bone, every bone will have a parent bone in a HandSkeleton (with the obvious exception being the WristRoot bone) - if none other, it will be the WristRoot bone

  • This property is also exposed in the HandBone's inspector panel as a read-only field

bool IsParentBoneClosestAncestor { get; }

  • Indicates whether the HandBone's parent bone from the HandBone's HandSkeleton is its closest possible ancestor bone, i.e. whether it is HandBone's natural parent bone according to the HandSkeletonConfiguration or not

  • For the Wrist bone this is false, as is for any HandBone not added to a HandSkeleton

Pose BindPose { get; set; }

  • HandBone's pose relative to the bone's parent pose that serves as HandBone's initial or default pose

  • This pose is relative to the pose of the HandBone exposed via ParentBone property

  • For Wrist bone this is relative to the world origin, i.e. to the global zero point and identity rotation

  • This value is reset every time the bone is (re-)added to a HandSkeleton. This is actually reset whenever the HandBone's parent bone is changed in general

  • Although it can be manually changed, there is usually never a need to do so

bool CaptureBindPose { get; set; }

  • Specifies whether the HandBone's bind pose should be captured from HandBone's current Transform

  • Bind pose is going to be constantly updated with the HandBone's current Transform state as long as this is enabled, but note that this capturing process occurs from whithin the HandSkeleton's SetBoneBindPoses method, so it depends on the exact implementation of the HandSkeleton. Currently all of the HandSkeletons defined in OctoXR perform this functionality as expected

  • This process occurs only inside Unity editor during edit-time and setting the value of this property will have no effect outside of it

  • This property is, considering the exact effects it has described above, exposed in the HandBone's inspector, though it can be used from code as well

Public methods

void HandleAddedToHandSkeleton(HandSkeleton handSkeleton, HandBoneId boneId)

  • Initializes the HandBone's state as a consequence of HandBone being added to the HandSkeleton under the identity specified by the parameters of this method

  • Important thing to note is that this method is intended only for a HandSkeleton to call it while the HandBone is being added to one, calling it manually from any other context is going to result in an exception being thrown; therefore you should never call it since the HandSkeleton does that as intended, regardless of the exact type of a HandSkeleton - this isn't an implementation dependent behaviour

void HandleRemovedFromHandSkeleton()

  • This pretty much does the same as previously described method, only under the opposite circumstances and with opposite effects - uninitializes the HandBone after it is removed from the HandSkeleton it was last added to

  • Same rules apply for calling this method, it is done by the HandSkeleton and it should never be done from anywhere else

void NotifyAddedToHandSkeleton()

  • Performs some other minor internal initialization steps and sends out the internal callback on the HandBone that signals to the derived behaviours that the HandBone has been added to a HandSkeleton

  • Again, just like it is with HandleAddedToHandSkeleton method, this is already getting called by the HandSkeleton at appropriate times, calling it from any other context is either going to throw an exception or it will have no effect at all

void NotifyRemovedFromHandSkeleton(HandSkeleton handSkeleton)

  • Like the previous method, but with opposite effects and on opposite circumstances, with the same rules about calling this method applying here as well

Protected methods

virtual void OnAddedToHandSkeleton()

  • Callback method that gets called when the HandBone is added to a HandSkeleton

  • When this method is called, all of the HandBone's properties (HandSkeleton, BoneId, ParentBone etc.) are initialized and safe to use. The HandSkeleton the bone is added to also has its HandBone related state updated at this point as well

virtual void OnRemovedFromHandSkeleton(HandSkeleton handSkeleton)

  • Callback method that is called after the HandBone is removed from the HandSkeleton that is specified by the method parameter

  • When this method is called, the HandBone's properties and all of the HandBone related state in the HandSkeleton is unitialized/reset. Identity of the HandBone, however, remains unchanged since it no longer affects anything, but it may be useful to derived behaviours at this point to know about it. BindPose is unaffected too

virtual void Reset()

  • Unity built-in callback. This method performs an important task - when the bone gets reset in the editor, it reconstructs the HandBone's state and then it makes sure the HandBone reset takes place with all of the appropriate callbacks being sent and handled in both the HandBone and its HandSkeleton, but only if it was added to one. This keeps the state of the scene safe and valid just the same as the Reset method in the HandSkeleton script does

  • With all that stated it should go without saying that base.Reset should be called from overriding methods

virtual void OnValidate()

  • Unity built-in callback. Performs certain initialization steps for the HandBone and ensures its state is valid

  • Always call base.OnValidate from OnValidate override method

virtual void Awake()

  • Unity built-in callback. Performs certain initialization steps for the HandBone and ensures its state is valid

  • Always call base.Awake from Awake override method

Last updated