チュートリアル / カットシーンのデータ管理
第3回:TimeEditorを⼯夫して管理を効率化してみよう③

  • Maya
  • UI・ビューポート
  • ゲーム
  • コラム
  • スクリプト・API
  • チュートリアル
  • 学生・初心者
カットシーンのデータ管理 TimeEditorを工夫して管理を効率化してみよう3

みなさんこんにちは。
このコラムでは、ゲーム制作におけるカットシーンのデータ管理について、変化球的な効率化の事例を紹介しています。

ここまでで、第一回目は「TimeEditorのデータ構造に関して理解を深める」話題を。
第二回目は「TimeEditorをスクリプトで操作してみる」話題を展開しました。
そして、今回は「TimeEditorの変則的な使い方とカスタマイズ」について取り上げます。

この記事では最終的に…

TimeEditorのGUIを拡張して、Outlinerをくっつけたり、右クリックメニューからクリップを生成できるようにした例

こんな感じに、TimeEditorを拡張して左にOutlinerをつけたり、ポップアップメニューからクリップを作れるようにしたいと思います。

TimeEditorが重くなる問題への対処

まずはクリップの生成について。
対象のノードと紐づけてクリップを作成しますが、TimeEditorの「挙動の重さ」について対処を考える必要があります。

TimeEditorの挙動が重たくなる問題への対処

TimeEditorは大変便利なToolなのですが、登録するアトリビュートやノードの量によっては、挙動が重たくなってしまいます。
なので、リギングされたキャラクターのアニメーションをそのまま登録してしまうと、(登録の量にもよりますが)正直ちょっと重たすぎて、使いにくくなってしまいます。

そのため、登録するアトリビュートなどは選択的に絞って運用するのが寛容です。

いっそアトリビュートをTimeEditorに登録しない

しかし今回の用途はアニメーションの編集は目的ではなく、あくまで「出力対象をクリップで管理」することが目的です。
つまり、TimeEditor本来の便利な機能(アニメーションのブレンドやクリップによる編集機能など)は使用しないので、もういっそアトリビュートは登録しないで運用しようと思います!
相当割り切った、乱暴な対応かもしれませんが…要件定義を考えるなら、これでいいのです。

それに、別途TimeEditorでアニメーションを編集したい場合には、通常のTimeEditorの機能でクリップを作り、
compositionを分けて管理しながら運用すればよいので、今回は問題を切り分けて考えることにして、設計をシンプルにします。

ノードをたどる用にmessageアトリビュートを用意して接続

ただし、ノードとTimeEditorの接続がないと、クリップから対象ノードをたどることができません。
そこで代わりに、クリップと対象ノードにカスタムアトリビュートを追加して、お互いを接続させます。
これでクリップから対象のキャラクターを参照できるようになります。

なお、追加するアトリビュートはmessageアトリビュートにしました。
messageアトリビュートは便宜的なアトリビュートで、コネクションしてもノード間で処理が走らないため、処理負荷の軽減につながります。

参照:MFnMessageAttribute Class Reference
https://help.autodesk.com/view/MAYADEV/2025/ENU/?guid=MAYA_API_REF_cpp_ref_class_m_fn_message_attribute_html

Function set for message attributes. A message attribute is a dependency node attribute that does not transmit data. Message attributes only exist to formally declare relationships between nodes. By connecting two nodes via message attributes, a relationship between those nodes is expressed. Message attribute connections can be traversed in the same manner as any other connection in the dependency graph. Message attributes cannot be stored as they do not contain data.

メッセージ属性の機能セット。メッセージ属性は、データを送信しない依存ノード属性です。メッセージ属性は、ノード間の関係を正式に宣言するためだけに存在します。2つのノードをメッセージ属性を介して接続することで、それらのノード間の関係が表現されます。メッセージ属性の接続は、依存グラフ内の他の接続と同様にトラバースできます。メッセージ属性にはデータが含まれていないため、保存することはできません。

実際にやってみよう

対象ノードとクリップをmessageアトリビュートで接続するスクリプト

では、実際にやってみましょう。
まずは、対象ノードとクリップをmessageアトリビュートで接続するスクリプトを書いてみます。

def createClipConnection(node='', clip='', *args, **kwargs):
    if not cmds.attributeQuery(
        'COYOTE_ExportTargetNode',
        n=clip,
            ex=True):
        cmds.addAttr(clip, ln='COYOTE_ExportTargetNode', at='message')
    if not cmds.attributeQuery(
        'ExportSourceClip',
        n=node,
            ex=True):
        cmds.addAttr(node, ln='ExportSourceClip', at='message')

    cmds.connectAttr('{}.ExportSourceClip'.format(node),
                     '{}.COYOTE_ExportTargetNode'.format(clip), f=True)

ここでのポイント
・クリップに対して「COYOTE_ExportTargetNode」という名前のmessageアトリビュートを探して、なければクリップに追加しています。
・また、対象ノードに対しても「ExportSourceClip」という名前のmessageアトリビュートを探して、なければノードに追加しています。

カスタムクリップを作るスクリプト

続いて、クリップを作成するスクリプトです。
maya.cmds側の本処理部分については、前回の記事の通りですので、適宜使っていきます。

import re

# 名前を指定してトラックを探す関数
def findTrakID(name='', compositionNode=''):
    trackIDList = cmds.timeEditorTracks(
                                            compositionNode,
                                            q=True,
                                            atc=True
                                        )

    for id in trackIDList or []:
        trackName = cmds.timeEditorTracks(id, q=True, tn=True)
        result = re.match(name, trackName)

        if result:
            return id

    return None

# クリップを作る関数
def createClip(node='', *args, **kwargs):
    # -------------------------
    # <前処理>いろいろ準備…
    # 現在のコンポジションを取得
    compositionNode = cmds.timeEditorComposition(q=True, act=True)

    # 選択ノードの名前から「ラベル名」を取得しておく(後であちこちのノード名に使う)
    label = node.split('|')[-1].split(':')[0]

    # トラック名は選択ノード(ラベル名)にする
    user_trackName = label

    # 現在のタイムレンジを取得する
    timeRange_min = cmds.playbackOptions(q=True, min=True)
    timeRange_max = cmds.playbackOptions(q=True, max=True)
    timeRane_duration = timeRange_max - timeRange_min

    # トラックを作る
    targetTrackID = findTrakID(
                                  name=user_trackName,
                                  compositionNode=compositionNode
                              )
    # トラックがなかったら作る
    if not targetTrackID:
        # コンポジションにトラックを追加
        trackID = cmds.timeEditorTracks(compositionNode, e=True, at=-1)
        # トラックをリネーム
        cmds.setAttr(
                        '{}.track[{}].trackName'.format(
                                                        compositionNode,
                                                        trackID
                                                    ),
                        user_trackName,
                        type='string'
                    )
        # 後処理のため、trackIDの形にしておく
        targetTrackID = '{}:{}'.format(compositionNode, trackID)

    # -------------------------
    # <本処理>クリップをつくる!
    user_clipName = '{}_clip0'.format(label)
    clipID = cmds.timeEditorClip(
                            user_clipName,
                            track=targetTrackID,
                            s = timeRange_min,
                            d = timeRane_duration
                        )
    # 実際に命名されたクリップ名をidから取得して調べる
    clipName = cmds.timeEditorClip(
                            clipID,
                            q=True,
                            name=True
                        )
    # クリップのコネクション処理(さっき書いた関数に飛ばす)
    createClipConnection(node=node, clip=clipName)

こんな感じです。
スクリプトの動作としては…
・指定のノードに対してクリップが作られて、messageアトリビュートで接続がかかる。
・現在のタイムレンジにクリップの開始Fと長さを合わせて作成する。
・クリップが生成されるトラックには、選択ノードの名前が設定される。
…という働きになっています。

ここでのポイント
複数回実行された場合には、クリップも一つのノードに対して複数作られる。
その際、クリップは自動的にリネームされることを見越して、生成されたクリップのidから、実際に命名されたクリップ名を取得して、そのあとの接続処理に使っている

Mayaシーン内の単一キャラクターから出力されるアニメーションは、必ずしも単一とは限りません。
インゲームアニメーションでは、アクション(ジャンプや走りなど)の入り~Loop~終わり…などでアニメーションを分割出力するように、カットシーンでもカメラや都合によって、アニメーションを分けたいケースが十分想定されます。

上記ポイントは、このことにあらかじめ配慮した実装なわけです。

選択したノードに対して、カスタムクリップを生成するスクリプト

ここまで出来たら、あとはもう簡単です。
選択ノードに対して上記関数を実行する、実行関数を書いておしまいです。

def CreateClipFromSelection(*args, **kwargs):
    selection = cmds.ls(sl = True, type='transform')
    if not selection:
        cmds.warning('対象のノードを選択して実行してください。')
        return

    for node in selection:
        createClip(node)

あとは、上記関数をカスタムTimeEditorのGUI上から実行できるようにすれば、これにてクリップ生成機能は実装完了です。

TimeEditorのGUIを拡張しよう

さて、ここまでカスタムクリップの生成スクリプトをまとめました。
しかし、せっかく作ったスクリプトも、いちいちシェルフや別ウィンドウから実行するのでは手間です。
次はTimeEditorのGUIを拡張して、これらのスクリプトをTimeEditorから直に実行できるようにしましょう。

まずはユーザーのTool操作を想像して設計してみる。

Tool操作の動きを創造して設計してみます。
想定されるユーザー動作は…
1. 対象のノード(複数の可能性あり)を選択する
2. クリップの生成スクリプトを実行する
3. クリップが追加されたTimeEditorを目視して確認し、必要に応じてクリップの位置を調整する

といった流れです。
こう…なんていうか、ガバッと選択(?)して…チャチャッと機能が実行(?)できたら、気持ちよさそうです。(言語化とは
Outlinerが欲しいなぁ。。
ガバッと対象を選択するなら、やっぱりOutlinerです。

ガバッと対象を選択するなら、やっぱりOutlinerです。

TimeEditorの横にOutlinerがくっついていたら、視認性もよくなってノード選択のストレスがぐっと低くなりそうです。
…ここは好みによるところが大きいですが、僕はそう思うんです(笑)

OutlinerをTimeEditorの左に増設する

というわけで、TimeEditorの横にOutlinerをくっつくけてみます。
Outlinerは左側にあるのがMayaのGUI上見慣れているので、カスタムTimeEditorでも左側に増設します。

Outlinerを格納するレイアウトの名前を調べる
さて、OutlinerをTimeEditorに増設するはいいのですが、肝心の増設先の名前がわかりません。
まずは通常のTimeEditorが一体どんなレイアウトに格納されているのか調べてみます。

以下のスクリプトをScriptEditorから実行して、現在のMaya環境に存在するtimeEditorの名を調べます。

mel.eval('TimeEditorWindow;')
for editorName in sorted(cmds.lsUI(ed=True)):
    if not cmds.timeEditorPanel(editorName, q=True, ex=True):
        continue
    print(editorName)

このスクリプトでは…、
1. まずTimeEditorを起動し、
2. 現在Maya上に存在するエディタの名前をリストで取得、
3. timeEditorPanelコマンドで、TimeEditorかどうかチェックしてプリント
…という処理を行って、TimeEditorの名前を探します。
で、実行結果は以下の通り。

実行結果

「timeEditorPanel1TimeEd」という名前がわかりました。
今回はこの「timeEditorPanel1TimeEd」を対象にして、UIを拡張してみます。

レイアウトの構造を調べて、拡張挿入できそうな箇所を探す
TimeEditorのエディタ部分の名前はわかったので、今度はUIのフルパスを調べて、拡張GUIを挿入できそうな箇所を探してみましょう。 
以下のスクリプトで、 timeEditorPanel1TimeEdのフルパスを取得します。

TimeEdPath = cmds.timeEditorPanel('timeEditorPanel1TimeEd', q=True, p=True)
print(TimeEdPath)

実行結果は以下の通り。

実行結果

なるほど、タイムエディタのレイアウト階層は…

timeEditorPanel1
    └ formLayout
        └ paneLayout
            └ timeEditorPanel1TimeEd

…となっていることがわかりました。へぇ~。
パネル「timeEditorPanel1」以下のformLayoutにTimeEditorはまとまっているんですね。

【閑話休題】もうちょっとレイアウトを掘り下げてみる
ちなみに、TimeEditorが格納されているformLaybruout。 ほかの構成要素はどうなっているのか、少し掘り下げてみます。
以下のスクリプトを実行して子階層の構成要素をプリントしてみると…

childArray = cmds.formLayout('formLayout117',q=True, ca=True)
print(childArray)

実行結果は以下の通り。

実行結果

なるほど。
TimeEditorが格納されている「paneLayout4」のほかに、何やらframeLyaoutが同居していることがわかりました。

このframeLayoutがどこにあたるのか、ボーダーラインを表示させて見える化させてみます。

cmds.frameLayout('frameLayout42', e=True, bv=True)

実行結果は以下の通り。

実行結果

…なるほど、おまえかぁ。

浅い階層まででしたが、TimeEditorのレイアウト構成がちょっと紐解けました。
この後のOutliner以外にも、別のところにGUIを拡張したい場合には、このようにレイアウトを分析して挿入場所を探すのも一つの手です。

(注意)
formLayoutやframeLayoutの名前は動的に変わっています。必ずしも「formLayout117」や「frameLayout42」でない点に注意してください。
適宜「timeEditorPanel1TimeEd」から取得して調べることをお勧めします。

PaneLayoutでTimeEditorとOutlinerを分ける
ここで少し拡張後の使い勝手を考えてみます。
OutlinerとTimeEditorはそれぞれ、不要な時は狭く、積極的に使いたいときは広くして使えたら、利便性が上がってよさそうです。
そのため、ここではpaneLayoutで左右にレイアウトを分割してGUIを拡張してみます。

paneLayoutを作成し、TimeEditorが格納されているpanelの子階層に追加します。

paneName = cmds.paneLayout(p='timeEditorPanel1', cn='vertical2', ps=(1, 20, 100))

作成したpaneLayoutへ、OutlinerとTimeEditorが入っているformLayoutを移します。

outLinerPanel = cmds.outlinerPanel(p=paneName)
cmds.formLayout('formLayout117', e=True, p=paneName)

実行結果は以下の通り。

実行結果

TimeEditorにOutlinerが拡張されました!

なお、Outlinerは表示内容などを細かく指定することができます。
ここは公式ドキュメントにわかりやすいサンプルコードがあるので、そちらを見ながら適宜カスタマイズするのがよいでしょう。
https://help.autodesk.com/cloudhelp/2025/JPN/Maya-Tech-Docs/CommandsPython/outlinerPanel.html

ポップアップメニューがほしいなぁ。。

ノードを選択後、チャチャッとコマンドを実行するなら、やっぱり右クリックメニューからの実行です。
拡張したOutlinerでノードを選択し、右クリック→ポップアップメニューから、「クリップを生成」…と実行できたら、大変スムーズです。

Outlinerには既に右クリックのポップアップメニューがあるので、

Outlinerにすでにある右クリックのポップアップメニュー

ここにカスタマイズ項目を増やしてみたいと思います。

増設したOutlinerの右クリックメニューをカスタマイズする

ではまず、拡張先のポップアップメニューについて調べてみます。
scriptEditorの「Echo all commands」のオプションを入れて、Outlinerの適当なところで右クリックしてみます。

scriptEditorの「Echo all commands」のオプションを入れて、Outlinerの適当なところで右クリックしてみます。

プリントされたスクリプトがこちら。

プリントされたスクリプトがこちら。

ふーんナルホド。
なにやら右クリックしたときに「OutlinerEdMenuCommand」というmelプロシージャが実行されているようです。
これをwhatIsコマンドで調べて、ソースファイルを探し、さらに深掘ります。

whatIsコマンドで調べて、ソースファイルを探し、さらに深掘ります。
whatIs OutlinerEdMenuCommand

と入力して実行すると

実行結果

ソースファイルは
「C:/Program Files/Autodesk/Maya2025/scripts/others/OutlinerEdMenu.mel」
であることがわかりました。

実際には、Mayaがインストールされている場所によって上記のファイルパスは異なります。
同様にWhatIsコマンドで調べることでたどり着くことが可能です。

この中身を開いて、プロシージャ「OutlinerEdMenuCommand」を検索して調べます。
今回このプロシージャの解析内容は割愛しますが、melを読んで見ると、
・Outliner上でなんという名前のノード、上から何番目のノードでpopupMenuが開いたか調べる
・ノードの種類によって分岐させ、ビルドするポップアップメニューの内容を変える
…というようなことをやっています。
実際、setノードやsetメンバー、通常のtransformノードの上でpopupMenuを展開してみると…

transformノード上で展開した例

transformノード上で展開した例

setノード上で展開した例

setノード上で展開した例

setメンバー上で展開した例

setメンバー上で展開した例

たしかに内容がちょっと違います。
ここで分岐処理してたんですね、ナルホド面白い。

さて、プロシージャの解析を進めると、以下のプロシージャにたどりつきます。

global proc OutlinerEdMenu (string $outlineEd)
{
	// These variables are visible to clients, do not change their names
	global string $gOutlinerPopupMenu;
	string $menuName = $outlineEd + "Popup";

	// There are many outliner instances in Maya so only
	// set gOutlinerPopupMenu once (for the primary outliner)
	if ($gOutlinerPopupMenu == "") $gOutlinerPopupMenu = $menuName;

	popupMenu
		-ctrlModifier false
		-button 3
		-postMenuCommand ("OutlinerEdMenuCommand " + $outlineEd)
		-parent $outlineEd $menuName;
}

「string $menuName = $outlineEd + "Popup";」
ここの記述を見てわかるように、Outlinerのポップアップメニューは
「<Outlinerエディタの名前>Popup」
であることがわかりました。

ポップアップメニューの拡張方針として、カスタムメニューを拡張したことで元々のメニューや機能に支障があっては困ります。
なので、ここは手っ取り早く「もともとのメニューの一番下にカスタムメニューを追加する」方針でやってみます。

処理としては、
1. OutlinerEdMenuCommandをいつも通り実行させる
2. そのあとで、ビルド済みのポップアップメニューにカスタムメニューを追加する
という順序です。
これなら、もともとのメニューが生成された後で拡張するので、支障のリスクが少なく済みます。

では、実際にスクリプトを書いてみます。

カスタムポップアップメニューの作成
まずはカスタムポップアップメニューを追加してみます。

from maya import cmds, mel
def buildPopupMenu(outLiner, *args, **kwargs):
    # 引数としてOutlinerエディタの名前を渡して実行します。

    # ポップアップメニューの名前はルール通り、「<Outlinerエディタの名前>Popup」に設定
    outlinerPopupMenu = '{}Popup'.format(outLiner)
    # もしもポップアップメニューがなかったら、右クリックメニューを追加します。
    if not cmds.popupMenu(outlinerPopupMenu, q=True, ex=True):
        # 各種フラグだてを行って、右クリックメニューを追加
        outlinerPopupMenu = cmds.popupMenu(
                p=outLiner,
                ctl=False,
                b=3
            )

    # メニューを開いたら、「rebuildPopUpMenu」関数を実行してメニューをリビルド
    cmds.popupMenu(
        outlinerPopupMenu,
        e=True,
        pmc=lambda *args: rebuildPopUpMenu(outLiner, outlinerPopupMenu)
    )

メニュー内容の作成。

def rebuildPopUpMenu(outLiner, outlinerPopupMenu, *args, **kwargs):
    # OutlinerEdMenuCommandを実行して、通常メニューを作成
    mel.eval('OutlinerEdMenuCommand "{}";'.format(outLiner))

    # わかりやすいようにディバイダで区切る
    cmds.menuItem(
            d=True,
            p=outlinerPopupMenu
        )

    # カスタムメニューを追加
    subMenu = cmds.menuItem(
        l='COYOTE CutScene Menu',
        p=outlinerPopupMenu,
        sm=True,
        to=True,
        ver='2020'
    )

    # 子階層メニューに「クリップの作成メニュー」を追加
    cmds.menuItem(
            l='Add Clip from selection',
            c="<ここにクリップを生成する実行関数を書く>"
        )

アウトライナーにカスタムポップアップメニューを反映する
では、カスタムTimeEditorのOutlinerにポップアップメニューを追加します。
TimeEditorのformLayoutなどの名前は都度変わってしまうので、少しコードをリファクタリングして、動的に名前を取得するようにしてみます。

# TimeEditorの起動
mel.eval('TimeEditorWindow')

# TimeEditorのレイアウトのフルパスを調べて、構成要素を調べる
TimeEdPath = cmds.timeEditorPanel('timeEditorPanel1TimeEd', q=True, p=True)

# パネルの名前
timeEditorPanel = TimeEdPath.split('|')[1]

# formLayoutの名前
formLayoutName = '|'.join(TimeEdPath.split('|')[:-1])

# OutlinerとTimeEditorを分割するpaneLayoutを作成
paneName = cmds.paneLayout(p=timeEditorPanel, cn='vertical2', ps=(1, 20, 100))

# OutlinerとTimeEditorを合体!
outLinerPanel = cmds.outlinerPanel(p=paneName)
cmds.formLayout(formLayoutName, e=True, p=paneName)

# カスタムメニューの追加!
buildPopupMenu(outLinerPanel)

動作させてみた例がこちら。

動作させてみた例

うまくいきました!
カスタマイズしたOutlinerを左側に追加した状態でTimeEditorを起動できています。

カスタムメニューにクリップを作成する処理を入れてみると…

カスタムメニューにクリップを作成する処理を入れてみた結果

こんな感じです!
Outlinerで選択したノードを対象に、しっかりカスタムクリップの生成処理が実行されています。
これなら、対象物をoutLinerから選択して、さくさくクリップが作れて便利です。

今回ご紹介したGUIのカスタマイズについて、スクリプトと関数でご紹介しましたが、実際にはClassにまとめて作るのが良策です。
そのほうが、レイアウトやパネルの名前などの内部情報を管理しやすくなるのでお勧めです。

まとめ

今回は、TimeEditorの変則的な使い方として、「そもそもアトリビュートを接続せずに運用する方法」をご紹介しました。
この変則的な事例は、TimeEditorの便利なアニメーション編集機能を使わずに、クリップを管理するGUI部分のみを使用してみた、という事例です。
TimeEditorはアニメーション編集のToolとして沢山の便利な機能がありますが、GUIも直感的でわかりやすいデザインです。
いったんTimeEditorのアニメーション編集機能とは切り分けて考えることで、直観的なGUIを様々な事例に応用できるかもしれません。

また、TimeEditorのGUI部分の拡張についても触れました。
今回の記事をヒントに、GUIをより使いやすくカスタマイズいただけましたら、大変幸いです。

さて次回は、「TimeEditorを使った効率化」編のまとめです。
Clipに入力した値や情報など、TimeEditorから必要な情報を参照し、FBXやエクセルファイルなどを出力する…といった事例をご紹介いたします。

ではまた次回!

TA応援隊の⼩話

【第3回】

みなさん Bonjour!COYOTE TAチームの小澤です。
CEDECやTGSで大忙しだった夏が過ぎ、ようやく普段の落ち着きを取り戻しはじめた今日この頃です。

さて、今回はいよいよ弊チームが「どんなお仕事をしているのか?」をご紹介したいと思います。企業の方は「こんなことが依頼できるチームなのか」という目線で、学生さんや転職などを考えられている方は「このチームではこんな仕事ができるのか」などという目線でご覧いただけたらと思います。

まず大前提として、弊チーム…というか母体であるC&R Creative Studios(クリーク・アンド・リバー社内の制作スタジオ)自体が、基本は「受託制作」をメインとしています。
ですので、協力・外注会社としてパブリッシャー様・デベロッパー様の開発の一部をお手伝いさせていただくというのがメインです。

その中で我々の仕事としては、第2回でご紹介したような生い立ちであることから、
1. COYOTE 3DCG STUDIO内の各種3D制作におけるテクニカルサポート
2. パブリッシャー様・ディベロッパー様のプロジェクトへの直接的なテクニカルサポート
の2つに大きく分類され、その内訳は1:9で②が大多数を占めています。
そして近年はここに加えて、R&Dなどの内製プロジェクトも複数進行しているような状況です。

プロジェクト内容としては非常に多岐にわたり、図として可視化すると大体このような実績となります。

テクニカルアーティスト スキルレーダーチャート

こちらは弊チームで独自開発した「TAスキルレーダーチャート」を応用して、チームの案件実績比率をあらわしたものです。

特にセットアップ・リグや、パイプライン整備、ツール開発などは、ご相談いただくプロジェクト数・対応可能スタッフ数がともに多いため、実績としても最も多い部類となり、我々の得意としているところです。
(毎年採用している新卒社員も、リガー系TA志望の方が多いです!)
逆に、描画系分野などチャート内でへこんでいる箇所は、まだスタッフが潤沢にいないorプロジェクトのご相談が少ない領域ですので、これからもっと強化していきたいと考えております。…ので、ご応募・ご相談心よりお待ち申し上げております…!

まだチーム規模が急拡大してからはほんの数年、そして昨今のゲーム開発が軒並み長期化していることもあり、タイトルベースでご紹介できる実績はまだわずかですが、現在進行形であらゆるプロジェクトに携わらせていただいております。
もっともっとゲーム業界全体に技術貢献し、それに伴ってチームスタッフがキャリアアップできるようコツコツがんばっている毎日です。

「ここに入ったら、やりたい仕事ができる!」
「TA領域で困ったら、まずここに相談しよう!」

こんなふうに思っていただけるチームになれるよう、精進してまいります…!
それではまた次回お会いしましょう~!

製品購入に関するお問い合わせ
オートデスク メディア&エンターテインメント 製品のご購入に関してご連絡を希望される場合は、こちらからお問い合わせください。