Home Website Youtube GitHub

How to setup a head aim ctrl?

I am trying to add a head aim ctrl. However I keep getting cycle errors since the head and neck have space switches.

If you were to use the biped template, what postBuild script would you run to set something like this up?

This is basically how I do it:

Add a control_01 control under the neck. This is the node that will aim towards the aimer. The head should not be parented under it, or it will cycle. (I use basic control_01 nodes for my neck and head, so the head/neck guide that is combined might be harder to setup.)

Add an aimer control for the head, forward near the eye aim. At the same translateY as the aim node.

And then add an upvector control too, above the head. Also not parented under the head. Parent it under the chest or neck. Basically set it all up so that node would aim like you want your head to aim.

And then I guess this is the trick to avoiding the cycle: In the guide, add that aim control_01 as an additional space switch for the head.

In a post script:

  • add the aim constraint.
  • add a condition node (or equivalent) so when it is switched to the aim space switch, the head aimer control visibility turns on.

I started experimenting with a similar chest aim too, for certain types of characters.


Downside. Since this is a choice between spaces, this won’t work if you want an aim for every one of your space switches. If you want aim plus rotation isolation. But maybe it would work if you add a space switch to the upvector object too…? And then link the two space switches.

2 Likes

Thank you Chris

these post scripts * add the aim constraint.
"

  • add a condition node (or equivalent) so when it is switched to the aim space switch, the head aimer control visibility turns on.
    "
    could y post how the python code should look like?

The solution I devised. I didn’t connect the on/off to visibility but did give the aimCtl an on/off switch.

    def rig_head_aim(self):
        bodyUi = pm.PyNode('bodyUI_C0_ctl')
        aimCtrl = pm.PyNode('headAim_C0_ctl')
        aimedCtrl = pm.PyNode('neck_C0_head_cns')
        aimedGrp = rigbits.addNPO(aimedCtrl)[0]
        aimedGrp = pm.rename(aimedGrp, 'headAim_npo')
        attribute.unlockAttribute(aimedGrp, ["tx", "ty", "tz", "rx", "ry", "rz"])
        # aim constrain the cns to the aimCtrl
        aimConst = pm.aimConstraint(aimCtrl,
                                aimedGrp,
                                worldUpType='vector',
                                worldUpVector=[0, 1, 0],
                                maintainOffset=True)
        # orient constrain the aim ctrl to the head
        applyop.oriCns(aimedCtrl, aimCtrl, maintainOffset=True)

        # add aim constraint on/off attr to itself
        aimOnOff_attr = attribute.addAttribute(aimCtrl, 'headAim', 'bool',
                                                 channelBox=True,
                                                 keyable=True,
                                                 value=True)
        weight_attr = aimConst.getWeightAliasList()[0]
        pm.connectAttr(aimOnOff_attr, weight_attr)
        # set attrs
        pm.addAttr(f'{aimCtrl}.control_control', edit=True, en='aim:')
        pm.setAttr(aimOnOff_attr, 0)
        attribute.lockAttribute(aimCtrl, attributes=["rx", "ry", "rz", "sx", "sy", "sz", "ro"])
1 Like

I don’t suggest using a “vector” for an upVector. If you rotate your character in world space, it might not follow.

Instead make an upVector object. And place it above your aimedGrp, in the direction of “upVector” in your aimConstraint.

And also define your aimVector and upVector. In a forward-facing biped, default X and Y should be fine by coincidence. But if you keep this snippet as a template, you’ll be able to quickly change it for other situations.

Example:

worldUpObj = pm.PyNode('Some node you make')
aimConst = pm.aimConstraint(
                aimCtrl,
                aimedGrp,
                name='{}_aimconstraint'.format(aimedGrp.name()),
                aimVector=(1,0,0),
                upVector=(0,1,0),
                worldUpType='object',
                worldUpObject=worldUpObj,
                mo=True,
                )

Thanks @chrislesage ! I’ll implement that.
Question: the upVector object, does it need to follow the body or be in the world?

@actoratwork , the bodyUI control is indeed an attribute host control that I added. I think I was going to put the on/off switch attr on it, but just put it on the aimCtrl in the end, and forgot to remove that first declaration in the method.

1 Like

In general, it has to follow the space you want your upVector to be.

Specifically here, you want it to follow the same space the head would follow. So I make it follow the closest control under the head or neck that won’t cycle. For example the chest, or top of the spine.

1 Like