いんでぃーづ

個人でゲーム開発してる上で吸収したモノたち紹介。UnityからGIMPまでなんでも。デザインとかゲーム論まで語っちゃうよ的なアレ。

MENU

Unity : グローバルなイベント通知の仕組み(EventBus)を自前実装する [C#]

例えば、敵を倒したタイミングで、プレイヤー、UI、他の敵が何らかのアクションを起こしたい場合、どのような経路でイベントを通知するか悩みます。

敵を各オブジェクトが監視したりするのは、参照が絡み合って管理がめんどうくさいです。

f:id:sugar_affordance:20170526120444j:plain

そこで便利なのがEventBusです。

元はAndroidなどに存在するライブラリです。
発生したイベントをグローバルなバス(伝送経路的な意味)を伝って、それを受け取りたいオブジェクト全部に伝えるというもの。

f:id:sugar_affordance:20170526120554j:plain

今回はこれを実装してみます。

続きを読む

Unity : ゲーム性を持たせるAnimationCurveの小技3選

f:id:sugar_affordance:20170523193227p:plain

こういったウインドウを見たことがあると思いますが、これは AnimationCurve 型のメンバ変数を持つことで、インスペクタから設定することができます。

Unity - スクリプトリファレンス: AnimationCurve

public class AnimationCurveForRandom : MonoBehaviour {

    [SerializeField]
    AnimationCurve curve;

f:id:sugar_affordance:20170523193351p:plain

今回はこれを使った小技を紹介します。

アニメーションをなめらかに

“アニメーション"カーブなのでとりあえずアニメーションに使ってみましょう。

例えば

    void Update () {
        transform.position = new Vector3(500) * curve.Evaluate (Time.timeSinceLevelLoad);
    } 

とすることで、 座標(0, 0, 0)から(5, 0, 0)まで、カーブに沿った速度で移動していきます。

f:id:sugar_affordance:20170523194031g:plain

この方法の利点は、「ココからココまで速度変えながら移動。X秒間でぴったり到着」というような、時間ベースでの移動が可能なところです。

たとえばさっきの移動を8秒間でおこないたい場合、コードを以下のようになおします。

    void Update () {
        transform.position = new Vector3(500) * 
            (curve.Evaluate (Time.timeSinceLevelLoad / 8)); 
    } 

これで、シーンロードから8秒間ぴったりで座標(5, 0, 0)まで移動します。

重み付きランダム

例えばガチャで100枚のカードが排出されるとして、1番のカードは出やすく、100番に向かって出づらくするという表現が可能です。

やりかたは簡単で、Rand関数で出てきた値にAnimationCurve#Evaluate をかけて、範囲の値(ここでは 0 〜 99)に変換するだけ。

    float seed = curve.Evaluate(Random.value);
    int index = (int)(seed * 99);    // index : 0 〜 99 のどれ か 

カーブは下のようなかんじにしておきます。

f:id:sugar_affordance:20170524094326p:plain

Unity公式でも紹介されているやりかたです。

Unity - マニュアル: ランダムなゲームプレイ要素の追加

数値の補正(根性値)

0に向かっていくアニメーションカーブを使えば、体力が少なくなるにつれダメージを与えにくくなる敵(いわゆる根性値)などが表現できます。

public class AnimationCurveForDamage : MonoBehaviour {

    [SerializeField]
    AnimationCurve curve;

    const int MaxHP = 100;
    int HP = MaxHP;

    void Update () {
        if (Input.GetMouseButtonDown (0)) {
            Damage (10);
        }
    }

    void Damage(int damage) {

        // HPが少ないほどダメージも少ない
        HP -= (int)(curve.Evaluate ((float)HP / MaxHP) * damage);

    }
} 

アニメーションカーブの最小値は0.5くらいにします。
0にしてしまうと絶対に死なない敵になるので注意。

f:id:sugar_affordance:20170523194205p:plain

Unity : フォントデータから必要な文字だけインポートし、容量を軽くする

フォントファイル(ttf, otf)をそのままアプリにブチ混むと、そこそこの容量になる。
あらかじめ使用する文字がわかっているなら、その文字だけインポートすることで大幅な容量の節約になります。

続きを読む

Unity : アニメーションのポリモーフィズム - AnimatorOverrideController

たとえばオッサンキャラとJKキャラには同じ「歩く」というアニメーションが必要ですが、実際に適用するアニメーションクリップは異なるでしょう。

*下は同じアニメーションを適用したオッサンとJK(?)の例

f:id:sugar_affordance:20170502180616g:plain

そんなとき AnimatorController を共通化しつつ、クリップを分ける機能がAnimatorOverrideControlerです。

Unity - マニュアル: Animator Override Controller

元となる AnimatorController を作る

とりあえず下のような二つのステートを持つ AnimatorController を作っておきます。

f:id:sugar_affordance:20170502181308j:plain

JK用にAnimatorOverrideControlelr を作る

プロジェクトウインドウで右クリックし、Create > Animator Override Controller と選択します。

f:id:sugar_affordance:20170502181507j:plain

作成したらインスペクタで

f:id:sugar_affordance:20170502181901j:plain

Controller の欄に元となるAnimatorController を設定します。

すると、元のほうに設定済みのAnimationClipのリストが現れるので、上書きしたいものにアニメーションクリップを設定します。

f:id:sugar_affordance:20170502182027j:plain

ここではWalkのほうにJK用のアニメーションを設定しました。

Animatorに設定する

あとはキャラのAnimatorに、作成したAnimatorOverrideControllerを設定するだけです。

f:id:sugar_affordance:20170502182402j:plain

実行してみた結果

f:id:sugar_affordance:20170502182520g:plain

JK(若干 腐ってる人)の動きがかなり、なまめかしいものになっていることがわかるでしょう。

え?見えない? 目が腐ってるんじゃないですか?

キャラが多数出るゲームにはかなり有効です。

Amazon.co.jpアソシエイト