講演者紹介
― 4 ―
●入社:2012年 ●東京スタジオ勤務
テクニカルアーティスト 松尾 隆志
株式会社サイバーコネクトツー
プロフィール Unityを使用したタイトルとして「フルボッコヒーローズX」、
「.hack//NewWorld」などに携わる。
描画表現の開発やアーティスト向けツールの開発を行いつつ、
パイプライン構築、ゲームエンジンサポートなどの
技術的なサポートも担っている。
開発部
― 5 ―会社概要
商号
本社
東京スタジオ
モントリオールスタジオ
設立日
従業員数
資本金
事業内容
株式会社サイバーコネクトツー
福岡県福岡市博多区博多駅前1丁目
東京都品川区大井1丁目
カナダ・モントリオール
平成8年2月16日
福岡本社 :180名 (※うちアルバイト25名)
東京スタジオ:33名 (※うちアルバイト11名)
40,000,000円
家庭用・スマートフォン向けゲームソフト企画・開発
CC2開発のスマートフォンタイトルとUnity
― 6 ―
2011 2012 2013 2014 2015 2016
2011.11検証開始(Unity 3.5 beta)
2012.11ギルティドラゴン
2013.02シャドウエスケイパー
2013.10死神メサイア
2014.02フルボッコヒーローズX
2014.03リトルテイルストーリー
2014.11FINAL FANTASY VII G-BIKE
2016.01.hack//NewWorld
2017
※サービス終了タイトルを含む、年月はグランドオープン時
キャラクターカスタマイズとは
― 11 ―キャラクターカスタマイズ編
キャラクターカスタマイズの要素
• 分割したパーツを読み込んで合成する
• ひとつのモデルを複数の体格で利用する
• 複数のバストサイズに対応する
• 肌色, 髪色, 目色などを変更する
1 パーツの合成
― 14 ―キャラクターカスタマイズ編
任意のモデル&マテリアルを読み込んで合成
1. 髪
2. 顔
3. 上半身
4. 下半身
5. 頭装飾(任意)
6. 胴装飾(任意)
7. 武器 (任意)
パーツの種類
モデル
マテリアル A
マテリアル B
パーツ
A
パーツ
B
1 パーツの合成
― 15 ―キャラクターカスタマイズ編
SkinnedmeshRenderer
単一のスキンメッシュに結合
(髪、顔、上半身、下半身)
MeshRenderer
任意のボーン(Transform)に接続
(頭装飾、胴装飾、武器)
2 パーツの接続先指定
― 17 ―キャラクターカスタマイズ編
頭装飾・胴装飾のパーツは
あらかじめ設定したダミーの
ボーン(Transform)に接続する
3. 空中系(周囲を浮遊するもの)
4. 羽系 (背中に背負うもの)
5. 胸元系
6. 尻尾系
胴装飾
頭装飾
1. 帽子系
2. めがね系
3 パーツの可視性指定
― 19 ―キャラクターカスタマイズ編
装備に合わせて可視性を変更する
• 帽子を装備した際にツインテールが突き抜ける場合– ツインテール部分をあらかじめ分離しておき、非表示にする
• フルフェイスのようなもので髪が突き抜ける場合
– 髪全体を非表示にする
可視性の変更例
など
1 女性のみ S, M, L の3サイズ
― 27 ―キャラクターカスタマイズ編
素体のスケール用ボーンを使用する胸のサイズ毎に “Position”, “Rotate”, “Scale” を微調整
Sサイズ Mサイズ Lサイズ
1 肌、目、髪色の変更
― 33 ―キャラクターカスタマイズ編
R:カラー。 色を変更する箇所の指定
G:ライト。 ライトの影響を受けない箇所の指定
B:アルファ 透過させる箇所の指定
顔以外のマスクテクスチャ
フェイシャルアニメーションとは
― 40 ―フェイシャルアニメーション編
フェイシャルアニメーションの要素
• 様々な表情&アニメーションに対応する
• データ容量を極力減らす
• 短期間で制作できるようにする
1 ブレンドツリーでの表情作成
― 43 ―フェイシャルアニメーション編
各キャラ毎に表情、形状が異なるテクスチャでのアニメーションは難しい
目パチ、口パク、目線など動きが様々アニメーションとして実装するのも手間
1 ブレンドツリーでの表情作成
― 45 ―フェイシャルアニメーション編
レイヤーは動作するパーツ毎に分ける
目線
左目
口
右目
眉
感情
左右をまとめた眉の形状
まぶたの動き+目の形状
まぶたの動き+目の形状
頬を染めるなどの特殊表現
目そのものの動き
口の開閉+口の形状
1 ブレンドツリーでの表情作成
― 46 ―フェイシャルアニメーション編
基準となる表情とのブレンドを行う各ステートに表情を設定し、ブレンドツリーでブレンド
デフォルト表情例:目を開く
ブレンド表情例:目を閉じる
2 デフォルト表情設定
― 49 ―フェイシャルアニメーション編
基準となる表情のパラメータを設定各パーツ毎のパラメータを実行時に表情として反映
1.表情の状態
2.固定の状態 (通常/半固定/固定)
3.ブレンド率
デフォルトパラメータ概要
2 デフォルト表情設定
― 50 ―フェイシャルアニメーション編
• 表情の状態 :半目
• 固定の状態 :半固定
• ブレンド率 :0.9
• 表情の状態 :怒り
• 固定の状態 :半固定
• ブレンド率 :0.9
右目
口
キャラ毎にScriptableObjectで設定
• 通常– 0.0~1.0の間で自由に動く
• 半固定– その値を基準に動く
– 例:0.0~0.9 or 0.9~1.0
• 固定– その位置から動かない
– 目を閉じたまま など
3 キーフレーム設定
― 52 ―フェイシャルアニメーション編
表情を変えるタイミングとキーを設定指定した内容をスクリプトで制御する
右目/左目を0.1秒で閉じる1秒
右目/左目を0.1秒で開ける1.1秒
アニメーション開始0秒
アニメーション終了&ループ2秒
3 キーフレーム設定
― 53 ―フェイシャルアニメーション編
キーフレームはScriptableObjectで定義
1.再生までの待ち時間
2.対象のパーツ
3.ブレンドする表情の状態
4.再生時間
5.ブレンド率
キーフレームパラメータ概要
アニメーション1つで全キャラ対応デフォルト表情を元にアニメーションするので
どの表情のキャラクターにおいても対応可能
3 キーフレーム設定
― 55 ―フェイシャルアニメーション編
目を閉じたままのキャラ
半目気味のキャラ
猫目のキャラ
まばたきする
フェイシャル
アニメーション
目を閉じたまま
まばたきをする
アニメーション
キーフレームパラメータ デフォルトパラメータ 結果
タウンマップのクロスフェード
― 59 ―タウンマップ編
複数要素、リソースのフェード変化する要素が多い
1. ディレクショナルライト × 1
2. アンビエントライト × 1
3. パーティクルエフェクト × 複数(可変)
4. 背景のテクスチャ × 複数(固定)
5. 背景のライトマップ × 1
要素
各要素のクロスフェード
― 61 ―タウンマップ編
パーティクル
前:”emission.enabled” を false で
徐々に消えるようになる
後:Prewarm を false にすることで
徐々に表示するようになる
particleSystem.emission.enabled = false;
シェーダーでのクロスフェード
― 63 ―タウンマップ編
Shader.SetGlobal~を活用共通項目はまとめて処理する
• フェードの進捗(0.0~1.0)
SetGlobalFloat
• フェード前後のライトマップ
SetGlobalTexture
共通ではない項目は個別で差し替え
(空用のテクスチャなど一部の決まった要素のみ)
ライトマップ生成について
― 64 ―タウンマップ編
ライトマップを複数用意するUnity上でベイクしたライトマップを利用する
• ライトマップのUVは「シーン内」のメッシュに対応
• シーンに結びついたライトマップはクロスフェードできない
利用する際の問題点
ライトマップUVの一括設定
― 68 ―タウンマップ編
簡易ツールで一括設定設定しているシェーダーを調べて
ライトマップを使用するかどうか判別する
コンポーネントの追加Rendererの参照追加
UV値の反映
夜用
マップ
夕用
マップ
昼用
マップ
複数のライトマップへの対応
― 69 ―タウンマップ編
同じモデル(シーン)を用い
ベイク後にテクスチャをリネームする
昼用ライト
夕用ライト
夜用ライト
ライトマップを
ベイクする対象の
Prefab(モデル)
スクリーンキャプチャを撮りたい
― 74 ―開発効率化編
透過画像が出力できない装備のアイコンデータ作成などに時間がかかる
Unity上でモデルを配置
Unity上でキャプチャ
Photoshopで切り抜き
Photoshopでアイコン化
スクリーンキャプチャ
― 75 ―開発効率化編
Texture2D.ReadPixelsの利用スクリーン画面のピクセルデータを読み込むAPI
• 一般的な方法
• 透過画像を出力できない
Application.CaptureScreenshot
• OnPostRender内で行う方法
• 透過画像を出力できる
Texture2D.ReadPixels
― 76 ―開発効率化編
// エディタ上で動作するように.
[ExecuteInEditMode, RequireComponent(typeof(Camera))]
public class CaptureCamera : MonoBehaviour
{
private bool isCapture = false;
public string filePath;
public void Capture() { this.isCapture = true; }
void OnPostRender()
{
// 1フレームだけキャプチャする.
if (!this.isCapture) return;
var tex = new Texture2D(Screen.width, Screen.height, TextureFormat.ARGB32, false);
tex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
tex.Apply();
File.WriteAllBytes(this.filePath, tex.EncodeToPNG());
this.isCapture = false;
}
} スクリーンキャプチャ取得実装例
モデルインポート設定の問題
― 78 ―開発効率化編
インポート設定はコピーできない設定に時間がかかる+同じような設定が多い
• Model– Mesh Compression
• Rig– Avatar Source
• Animation– Avatar Mask
モデルインポート設定のコピー&ペースト
― 79 ―開発効率化編
多くの項目は
ModelImporter
ModelImporterClipAnimation
で取得・設定可能
無い項目については
SerializedObject.
CopyFromSerializedProperty
で設定可能
エディタで設定した値の問題点
― 81 ―開発効率化編
永続的に値を保持できないエディタで設定したフラグをゲームで使用したい
PlayerPrefs レジストリを書き換える
Static変数 実行時に初期化される
Scriptable
Objectファイルの更新が入る
エディタで設定した値を保持し続ける
― 82 ―開発効率化編
ScriptableSingletonを使うエディタ上でしか使わない(使えない)点を利用
1. 単一性が保たれる
2. 実行後も値が保持される
ScriptableSingletonの利点
― 83 ―開発効率化編
// Editorのみで使用可能にする.
#if UNITY_EDITOR
// ScriptbaleSingletonはUnityEditor名前空間内にある.
using UnityEditor;
// ScriptableSingletonを継承したクラスを用意する.
public class EditorPreference : ScriptableSingleton<EditorPreference>
{
// 設定するフラグの例.
public bool customMode = false;
}
#endif
ScriptableSingletonの定義
― 84 ―開発効率化編
// エディタ上での操作用クラス.
public static class EditorPreferenceTools
{
// エディタ上のメニューから操作してONにする.
[MenuItem(“Tools/CustomMode On”)]
public static void UseCustomModeOn()
{
// EditorPreferenceのインスタンスを取得して設定する.
var pref = ScriptableSingleton<EditorPreference>.instance;
pref.customMode = true;
}
// エディタ上のメニューから操作してOFFにする.
[MenuItem(“Tools/CustomMode Off”)]
public static void UseCustomModeOff()
{
var pref = ScriptableSingleton<EditorPreference>.instance;
pref.customMode = false;
}
} エディタ拡張での使用方法
― 85 ―開発効率化編
ゲーム内での使用方法
// ScriptableSingletonの使用例.
public class GameManager : MonoBehaviour
{
// ゲームの起動直後に行う処理として仮定.
void Start()
{
// Editorの機能なのでEditor上だけで動作させる.
#if UNITY_EDITOR
var pref = UnityEditor.ScriptableSingleton<EditorPreference>.instance;
if (pref.customMode == true)
{
/*! 設定した時に行う処理など
* 例:エディタでの実行時の特殊処理
* 特定の機能のON/OFF切り替え* AssetBundleではなくAssetDatabase経由の読み込みへの切り替え など
*/
}
#endif
}
}