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