ぐーるらいふ

しがないリーマンの記録。遊びのunityのメモ帳にしたい。

【Unity】第三回unity1week「積む」に挑戦 後編 (開発編)

ghoul-life.hatenablog.com

ちゃんとゲームらしく

タイトル -> チュートリアル -> ゲーム -> 結果

と画面を作る。
必要な素材も大体ここで描く。
fireAlpacaで適当に描く。

他のゲームもいきなりゲーム画面のやつばかりやんけ!と
甘えから今まで一回もチュートリアルなんて作ってこなかったが、
今回はちゃんと作ろう。少しでもゲームをプレイして貰いたいし。
説明文に頑張って書く!という最終手段もあるけど。

開発

開発はスイスイ進んだ。流石に三回目ともなれば色々と積み重ねたものがある。
2DベースでuGUIでゲームを作るというあんまりやってはならない事かもしれないが、
それで行く事にした。

f:id:ghoul_life:20170627154507p:plain


各パーツと捉えてこれらは全て別々のCanvasにしている。
Canvasを複数作ってON/OFFをスッと切り替えて、画面遷移を制御するようにして、
順番やsortOrder , positionを細かく自由に変更可能にしていた。

縦書き

unityはデフォルトで縦書きに対応はしていない。
が、先人達がすでに挑戦してくれていたのを拝借。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Linq;

public class VerticalText : UIBehaviour, IMeshModifier
{
    private Text textComponent;
    private List<char> nonRotatableCharacters; // 回転させない文字リスト
    private List<char> adjustCharacters; // 位置を調整する文字リスト

    private void InitLimitCharacters()
    {
        if (nonRotatableCharacters == null)
        {
            nonRotatableCharacters = new List<char>();
            nonRotatableCharacters.Add('ー');
        }

        if (adjustCharacters == null)
        {
            adjustCharacters = new List<char>();
            adjustCharacters.Add('ァ');
        }
        
    }

    public new void OnValidate()
    {
        //base.OnValidate(); -> WebGLビルド時のみエラーになる。iOSやaOSは平気なのに…何故?
        textComponent = this.GetComponent<Text>();

        var graphics = base.GetComponent<Graphic>();
        if (graphics != null)
        {
            graphics.SetVerticesDirty(); // 更新有りと伝える
        }
    }

    public void ModifyMesh(Mesh m) { }
    public void ModifyMesh(VertexHelper verts)
    {
        var stream = ListPool<UIVertex>.Get();
        verts.GetUIVertexStream(stream);

        modify(ref stream);

        verts.Clear();
        verts.AddUIVertexTriangleStream(stream);

        ListPool<UIVertex>.Release(stream);
    }

    void modify(ref List<UIVertex> stream)
    {
        if (textComponent == null)
        {
            textComponent = this.GetComponent<Text>();
        }

        var characters = textComponent.text.ToCharArray();
        if (characters.Length == 0)
        {
            return;
        }

        InitLimitCharacters();

        float angle = 90.0f;
        // 頂点を云々する。1テキスト6頂点
        // 6文字ずつ進む
        for (int i = 0, streamCount = stream.Count; i < streamCount; i += 6)
        {
            int index = i / 6;
            if (IsNonrotatableCharactor(characters[index]))
            {
                continue;
            }

            // 文字の中央を取得(上なら[i+1])
            var center = Vector2.Lerp(stream[i].position, stream[i + 3].position, 0.5f);

            if (IsAdjustCharactor(characters[index]))
            {
                center = center + new Vector2(-2.0f , 2.0f);
            }

            // 頂点を回す
            for (int r = 0; r < 6; r++)
            {
                var element = stream[i + r];

                var pos = element.position - (Vector3)center; ;
                var newPos = new Vector2(
                    pos.x * Mathf.Cos(angle * Mathf.Deg2Rad) - pos.y * Mathf.Sin(angle * Mathf.Deg2Rad),
                    pos.x * Mathf.Sin(angle * Mathf.Deg2Rad) + pos.y * Mathf.Cos(angle * Mathf.Deg2Rad));
                element.position = (Vector3)(newPos + center);
                


                stream[i + r] = element;
            }
        }
    }

    bool IsNonrotatableCharactor(char character)
    {
        return nonRotatableCharacters.Any(x => x == character);
    }

    bool IsAdjustCharactor(char character)
    {
        return adjustCharacters.Any(x => x == character);
    }
}

OnValidate
https://docs.unity3d.com/ja/540/ScriptReference/MonoBehaviour.OnValidate.html

ModifyMesh
https://docs.unity3d.com/ja/current/ScriptReference/UI.IMeshModifier.ModifyMesh.html

簡単に言えばUIの更新イベントフックして、そこで回転させている。
縦書きにするとァやー(長音符)の位置が少しズレてしまい、違和感を感じるので、
それを調整するようにしました。
また、ListPoolはUnityのソースから拝借。

神様ありがとうございます!
http://madnesslabo.net/utage/?page_id=6042

注意点としては、
WebGLビルドした時に

error CS0117: `UnityEngine.EventSystems.UIBehaviour' does not contain a definition for `OnValidate'

とbase.OnValidate()が怒られる。
これなんでだろー?iOSやaOSビルドは問題が無かった。
とりあえずコメントアウトしていて、特に影響なかったのでそのまま…。

チュートリアル

一番苦労したのはマスタとかコメントに書いたけど、
実装側でちょっと困ったのはこれ。
長くなっちゃったので別記事で

ghoul-life.hatenablog.com

また1つ勉強になった。

リリース

後は体裁を整えたりデバッグしたりで日曜日夜に提出。

締め切りは守る。
これゼッタイ。
みんな決められた時間内で平等に頑張ってる。(と思っている)

感想

変なゲームを好きに作ろうとしたら
被ったー!盛大に被ったー!しかも結構多いw

もうすでに三回目になり、
付いていくのもギリギリですが、
毎回本当に勉強になるなぁ。
少しずつ出来ることが広がっていくのを感じる。

今まではなんかゴチャ混ぜ感があって、
適当に詰め込んだ感じがあったけど今回は割りとまとまった方だと思う。
ゲーム部分をもっと詰めたいな。なんか本とか読んでみよう。

そろそろTweet機能を付けてみてもええか…。