2014年12月21日日曜日

Time.timeScale = 0 としたときの確認

Time.timeScale = 0 としたときの他変数の状態確認

Update関数内でDebug.Logを実行した結果
 
〇対象とした変数
  • realtimeSinceStartup
  • timeScale  (0を代入)
  • deltaTime
  • unscaledDeltaTime
  • frameCount
  • renderedFrameCount
  • time
  • unscaledTime

〇timeScale = 0 とした影響を受ける変数
  • deltaTime  (0になる)
  • time  (停止する)

ポーズ等でtimeScale = 0としたときでもframeCountは増加し続けてしまうので、
リプレイ機能の実装などで連続した1フレームの入力を記憶させる場合には、
フレームをカウントする変数を自前で用意する必要がありそうだ。

renderedFrameCountが何なのかわからない。
frameCount * 2 - 2 の値みたいだけれど特に利用することもないか。

それだけ。

2014年12月15日月曜日

uGUI ゲーム内キーコンフィグの実装

EventSystemが備わったunity4.6以降のお話。
実装したのが少し前でもう忘れてる。

スタンドアローン版では起動時に設定ダイアログを出すことでキーコンフィグが可能だが、
ダイアログを出したくないし、ゲーム内でいつでもキーコンフィグができるようにしたいし、uGUIだって使いたい!がために考えた方法。

必要な手順は下記の3つ
  1. Inputのラッパークラスを作成
  2. EventSystemのStandaloneInputModuleの置き換え(※)
  3. InputManagerにJoystickAxisを追加
で、良かったはず。
忘れないうちに文章化すべきだった…


手順1.ではInputのラッパークラスを作成し、キーマップを用意する。
手順から抜けているが、キーマップを変更するためのUI(キーコンフィグ)ももちろん必要。
これでほぼゲーム内キーコンフィグを実現できたようなものだけど、
これだけではuGUIのOnSubmitやNavigation等の用意された機能を利用することができない。

そこで手順2.のStandaloneInputModuleの置き換えを行う。
StandaloneInputModule内でInputが利用されている箇所を手順1.で作成したInputラッパークラスに書き換えたスクリプトを用意し、置き換える。(※)

手順3.はjoystickのアナログ入力に対応するためInputManagerにJoystickAxisの1st~20thを設定する。
こうすることでInputがアナログ入力を拾ってくれるのでラッパークラスでも拾うことができる。
アナログ入力を使用しないのであれば手順3.は行う必要がなく、
キーマップで入力の対応が出来ていればInputManagerの設定自体が不要になる。
(マウス関連は弄ってないのでわからない。不要にならないかも。)


大雑把なイメージ 間違ってたらごめんなさい



※注釈というか余談

StandaloneInputModuleのソースはこちらで公開されています。(少し古いみたいです)
提供元は下記リンクのやりとりを見たところ
UnityTechnologiesの方が非公式に公開してくれているアカウントのようです。
オープンソースとして公開される予定みたいなので、それを待ってもいいかもしれません。

2014年12月12日金曜日

uGUI フェードイン/アウト

こちらのサイト様を参考にuGUI版フェードイン/アウトを作成した。
また、シングルトンについてもこちらのものをそのまま使用させて頂いている。

〇コード
using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class FadeManager : SingletonMonoBehaviour<FadeManager>
{
    GameObject black;//暗転用のオブジェクト
    float time = 0.1f;//頻繁に使用するつもりのフェードイン/アウトの時間

    public void Awake()
    {
        if (this != Instance)
        {
            Destroy(this);
            return;
        }
        DontDestroyOnLoad(this.gameObject);
    }

    //秒数を指定したいときはこちらを呼び出す
    public void LoadLevel(string scene, float interval)
    {
        StartCoroutine(TransScene(scene, interval));
    }
    //timeの秒数を利用するとき
    public void LoadLevel(string scene)
    {
        StartCoroutine(TransScene(scene, time));
    }

    private IEnumerator TransScene(string scene, float interval)
    {
        float time = 0;
        RawImage raw = SetFadeObject();

        while (time <= interval)
        {
            raw.color = new Color(0, 0, 0, Mathf.Lerp(0f, 1f, time / interval));
            time += Time.deltaTime;
            yield return 0;
        }

        Application.LoadLevel(scene);

        //名前が変わる=シーンが変わるのを待つ
        while(Application.loadedLevelName != scene) yield return 0;

        time = 0;
        //LoadLevelでCanvasが一度破棄されているはずなのでもう一度呼び出す
        raw = SetFadeObject();

        while (time <= interval)
        {
            raw.color = new Color(0, 0, 0, Mathf.Lerp(1f, 0f, time / interval));
            time += Time.deltaTime;
            yield return 0;
        }

        Destroy(black);
    }

    //暗転用オブジェクトを生成し、透明度を変更するためRawImageを返す
    RawImage SetFadeObject()
    {
        black = new GameObject();
        black.name = "FadeObject";
        //Canvasの名前やヒエラルキーを変更している場合は要修正
        black.transform.SetParent(GameObject.Find("/Canvas").transform);
        RectTransform rect = black.AddComponent<RectTransform>();
        rect.anchorMax = new Vector2(1f, 1f);
        rect.anchorMin = new Vector2(0f, 0f);
        rect.anchoredPosition = new Vector2(0, 0);
        return black.AddComponent<RawImage>();
    }
}

〇余談
参考にさせて頂いたサイト様のスクリプトは、実行した際にエディタがほぼハングアップの状態になってしまった(×閉じるなどはできる)。
とりあえずthis.blackTexture.ReadPixels (new Rect (0, 0, 32, 32), 0, 0, false);のRectをRect(0,0,1,1)などに書き換えることで動作したのだが、
uGUI以前のGUIについては知識がほとんどないので、ここが本当に原因なのかもわかっていない。

現状ではフェード中にも操作できてしまうので、
フェードの始まりに入力受付OFF、フェードの終わりに入力受付ONというような実装が必要になるだろう。

2014年12月7日日曜日

SmoothMovesメモ CrossFade、スプライト反転、mLocalTransform

CrossFade前後でテクスチャーの変更があるような場合、モーフィングのような切り替わり方をしてくれるわけではない。
単純に前後のテクスチャーを描画するフレームの割合が変化していくだけなので、CrossFadeにあまり長い時間を設定すると点滅しているかのような不自然な見え方をする。
また、CrossFadeはレイヤーが同一のもの同士でないと正しく動作しない。


スプライトの反転方法を調べた。
smooth movesのサンプルではchefの顔の左右反転に
boneAnimation.mLocalTransform.localEulerAnglesのyに0か180を代入する方法をとっている。
他の方法には、scale.x = -1 や scale.x *=-1 などが考えられるがサンプルのy軸回転の方法がシンプルで幅広く対応できるだろう。


それでこのmLocalTransformってTransformと何が違うんだ、と思ったので
BoneAnimationがアタッチされているオブジェクトに下記コードのスクリプトをアタッチして確かめた。

〇コード
BoneAnimation bone = this.GetComponent<BoneAnimation>();
Debug.Log("this.transform         : " + this.transform.GetInstanceID());
Debug.Log("bone.transform         : "+bone.transform.GetInstanceID());
Debug.Log("bone.mLocalTransform : " + bone.mLocalTransform.GetInstanceID());

〇結果
結果はどれも同じインスタンスID

mLocalTransformとtransformの違いはわからなかった。
APIドキュメントにおいてもPublic Attributesの1つとして紹介されているだけ。
用意されてる以上何かしら意図があるものだとは思うのだけれど。


2014年12月4日木曜日

SmoothMovesメモ ミキシングとオートビルド

Unityのアセット「SmoothMoves」の使い方を覚えるにあたり、
こちらのサイト様を参考にさせて頂いた。
ミキシングではこちらのサイト様を参考にさせて頂いた。
感謝感謝です。日本語の導入があるだけでどれだけ助かるか。


上記サイトと同様にミキシングが上手く動作せずアニメが止まるという状況に陥った。
そのときに知り得た知識をメモる。

早速、原因は「ミキシングするアニメ同士のレイヤーが重複している」ことであった。
対策は、ミキシングするアニメのレイヤーをミキシングされるアニメよりも大きなレイヤーにすること。

例えば、走りながら剣を振るアニメを作りたい場合は、
走るアニメをLayer10とし、剣を振るアニメ(腕などのボーンのMixにチェック)をLayer15などとすればミキシングは動作する。
ちなみに、レイヤーの大小を逆転させ、走るアニメがLayer15、剣を振るアニメがLayer10とした場合は、走るアニメがプレイされてる間は剣を振るアニメのミキンシングはできず、走るアニメは止まらずプレイされ続ける。

なおレイヤーの変更を反映させたい場合はBoneAnimationのControl Panelを開きビルドし直す必要がある。

 
これがControl Panel



ここからControl Panelの話に変わる。
3つあるアイコンの上から
  1. ビルド
  2. オートビルド(ON/OFF)
  3. 更新ログのコンソールへの出力(ON/OFF)
である。
ただし、オートビルドはONにしてもControl Panelを開いておかないと動作しない。
なんとも邪魔ではあるのだが、レイヤーの変更の他にWrapModeの変更(インスペクターから出来るが)やおそらくその他変更諸々ビルドし直す必要があるので、オートビルドは活用したいところ。


英語で書いてあることそのままなのだけれど、
僕のように読んだつもりになって感覚で使用しちゃう人の助けになれば。