Zombie Playground’s Character Pipeline: Designing a Modular Rig Solution

With a greater number of potential characters than Mothhead, our previous Unity project; I went into Zombie Playground’s pre-production with my mind already set on creating an automated rigging solution. I took some inspiration from a Modular Rigging course I followed on 3dBuzz and begun to break down my rigging process into object-oriented code in suite I named Automato.

class BaseSubstruct(object):
    '''
    Abstract class to derive new rig modules from
    '''
    NAME = 'abstractobject'
    NICE_NAME = ''
    CREATION_PARAM_JSON_ATTRNAME = 'creationParams'
    DESCRIPTION = 'generic abstract description'
    MIN_JOINTS = 1  # number of joints needed to create substruct
    REQUIRES_SKELETON_CHAIN = True  # if true, subsruct requires a skeletal chain for creation

    def __init__(self, basename, joints, parent, mainControl):
        '''
        Builds rig in maya and creates an asset node to contain relevant nodes
        '''
        self.container = None
        self.layer = None
        self.containedNodes = list()
        self._rigControls = dict()
        self.lockAttrs = list()
        self.basename = basename  # unique name to identify nodes created by this substruct
        self.parent = parent  # parent to attach top-most rig node
        self.joints = joints  # base skeleton joints to attach
        self.mainControl = mainControl

        self.mainColorAttr = None

        if self.parent is None:
            self.parent = self.joints[0].firstParent2()
            if self.parent:
                self.parent = pm.PyNode(self.parent)
            else:
                if mainControl:
                    self.parent = mainControl

        self.verifyParams()
        self.container = pm.container(name='_'.join([Prefix.CONTAINER, basename, self.NAME]))

        ## Parameter dictionary for storing settings for assets
        ## Children classes can further expand this dictionary with parameters of their own
        self.paramDict = {'classname': self.NAME,
                          'basename': self.basename,
                          'joints': [str(i) for i in self.joints],
                          'parent': str(self.parent),
                          'mainControl': str(self.mainControl),
                          'container': str(self.container)}

        pm.addAttr(self.container, dataType='string', ln=self.CREATION_PARAM_JSON_ATTRNAME)
        pm.addAttr(self.container, at=int, ln='color', min=0, max=31, defaultValue=0, keyable=False, hidden=False)

        self.mainColorAttr = self.container.attr('color')
        self.mainColorAttr.showInChannelBox(True)

        if self.layer is None:
            self.layer = Layers.getLayer(Layers.ANIMATION_CONTROLS)

        self.transform = self.install()
        utils.lockAndHide(self.lockAttrs, True)
        connectControlColors(self.rigControls, self.mainColorAttr)
        self.updateSelectionSets()

        self.layer.addMembers(self._rigControls.values())

        self.containedNodes.append(self.transform)
        self.containedNodes.extend(self._rigControls.values())
        self.container.addNode(self.containedNodes)
        self.containerPublish(self.container)

        self.saveCreationParams()
        pm.parent(self.transform, self.mainControl)

    @property
    def rigControls(self):
        return self._rigControls.values()

    def verifyParams(self):
        if self.REQUIRES_SKELETON_CHAIN and not checkJointsAreHierarchy(self.joints):
            raise SkeletonError('The specified joints must be from the same skeletal chain')

        if len(self.joints) < self.MIN_JOINTS:
            raise SkeletonError('Only works with {0} joints!!'.format(self.MIN_JOINTS))

    def install(self):
        '''
        Main juice function
        Basic rig framework is created
        Return the top-most group node for __init__ method to utilize
        '''
        raise NotImplementedError("Derive me please")

This is a small snippet of the base class I designed all the rig components (known as “Substructs” in my code) to derive from. The BaseSubstruct class contains a set of parameters stored as members that most, or all, of my rigging structures (leg, arm, etc.) share. Using a OOP approach to creating the rig makes for a very scaleable solution for our pipeline. As new creatures are designed and implemented; I can plan out the automation right away, simply making a new class with most of the ground work derived from the original base class. Continue reading

Mothhead

Mothhead – Behind The Scenes

Mothhead is an interactive art demo for Unity we did at Massive Black.  The characters are inspired from sculptures created by Pete König during his time at studio that I originally rigged as part of an art test. In the past during company downtime, we revisited Mothhead often to experiment with different directions to possibly take the IP; such as the renders seen in the Massive Black Vol 1 art book. Unity stood out as fresh opportunity; we had experience with it from previous projects with Emotiv and the editor is user-friendly enough for artists to prototype ideas.

Continue reading

A Look at the Beginnings of Zombie Playground’s Character Pipeline

Zombie Playground is an exciting project I’ve been working on in recent months. Even though this was the second project where we are using Unity3d (the first being Mothhead); this is a completely brand new IP for us, that isn’t tied down to maintaining legacy assets. As such, Zombie Playground offers us a lot of freedom in planning out an efficient pipeline so we can better concentrate on the vision of the game, and less on tedious tasks. I’m responsible for wrangling our said pipeline, documentation, character rigging, and developing tools to assist our small team. We’re still in the early stages of development, and there’s a lot of aspects of the project in WIP-phase, but I want to describe some tools I’ve developed for ZPG that have been coming along nicely.

Continue reading

sasStretchySpline

In part three of my scorpion rig series, I went into some detail of how I make a spline IK stretchy. The approach is something I’ve used for a while and I’ve made a Python script a while back to automate the process. Today, I wish to share that script with the world! How it works is that it takes the specified Spline IK,  builds the nodes, and connects the network together to make a stretchy system. You can download it here; give it a try, and feel free to post any feedback!

Download sasStretchySpline

Vertex Weighting Tool for Maya

screenshot

Download python script for Maya

The Weight Tool is a Python script designed to make your skinning life easier. It streamlines the process of manpulating skin weights on the vertex level with a neat UI. I came up with the idea of making this tool after skinning some rigs in 3dsMax. The result is a script that works very similar to 3dsMax’s built-in Weight Tool, but in Maya now!

Installation:

Like any python script, this will only work in Maya 8.5 or later regardless of OS (tested only on Windows). To use the script in Maya, simply copy all the scripts from the archive into your PYTHONPATH. Once copied, restart Maya and type “import WeightToolInterface” in the python command line. To start using the tool after importing, type “WeightToolInterface.draw()” in the same commandline/scriptEditor.

*Note that you can find your PYTHONPATH by opening your Maya.env file with a text editor (usu. located in …/My Documents/maya/versionNo/Maya.env). If PYTHONPATH is defined, simply copy the scripts and continue from there.If PYTHONPATH is NOT defined, type in the Maya.env, “PYTHONPATH=C:/your/script/path/here”, replacing C:/your/script/path/here with a real system path you wish to install Python scripts to. When editing Maya.env, be sure to restart Maya to apply any changes.

Feel free to post any feedback!

PSPad Highlighter for QC files

If you’re using PSPad for viewing .qc files (the text file needed for compiling assets for Source), try out my custom highlighter. To use it, take out the .txt extension and copy it into [Program Files]\PSPad editor\Syntax\. Once in place, it can be loaded through PSPad in Settings->Highlighter Settings and assigning it to an available slot. For those using a fancy text editor other than PSPad (shame on you!), and want to make your own QC highlighter, check out the example here (ConTEXT) http://bit.ly/dkbCtY.

Syntax screenshot