2018年7月14日土曜日

技術ブログを始める際に困ったこと。コードの見やすさについて。

以前の記事Atom使ってマークダウンで記事書けばすっごい楽!ということを書きましたが、色々試しているうちにどうやらマークダウンだけでは少々問題がありそうだったので、主な問題とその解決方法について書いていきます。

まぁタイトルから既に分かるとは思うので、先に結論だけ共有しておくと結局cssやhtmlを使うことになりました。

ので、今回は ブログ初心者である自分がどのような問題に直面し、どのように対応したかをまとめていきます。

マークダウンのみの課題

前提として、正直なところマークダウンが悪いというより、自分がウェブページの装飾について無知なのが原因な気がしなくもないです…。

なのでこれから話す内容は「マークダウンでもできるよ!」とか「設定が悪いだけだ!」とかかも知れませんが、ご了承ください。

ソースコード等の特殊な文章の見せ方

ブログのテンプレートデザインのみを使用した場合、パット見デザインもよく、正直文字サイズや色を変更するだけでも良いかなと思っていました。

ただし箇条書きだったり、特にソースコード等特殊な文章を記事内に記述する場合、正直あまり見栄えが良いとは言えない状態でした。(ここに関しては自分が選んだ ブログテンプレートや、Atomのマークダウン設定の問題かもしれませんが…。)

たとえばですが、私が使っていたブログテンプレート上を使用し、Atomでマークダウン記述してからhtmlとして出力した文字列をそのまま記事にした場合、以下のような見た目になります。

旧記事でのソースコード表示方法

これ実はソースコードを貼っているのですが、 普通の文章 に紛れ込んだみたいになってしまっています。正直見づらいしどこからどこまでがソースコードなのかも分からないです。

技術ブログを始めようと思った手前、流石にソースコードが見づらくては意味がない 。というのが今回htmlを書こう!と思ったきっかけです。

解決方法

今回私が導入したのは以下の3点です。

  1. Atomでhtmlを書きやすくするためのプラグイン導入
  2. google-code-prettifyの導入
  3. cssファイル等のアップロード用にGitHub.ioの登録

それでは、一点づつ何をしたかを追っていきます。

Atomでhtmlを書きやすくするためのプラグイン

Atomは色々プラグインを導入し、カスタマイズするタイプのエディターなのですが、今回は以下の3つのプラグインのみ導入してみました。というより、色々と選択肢が多すぎたため、まずは試しに3種類だけ導入してみたというのが正しいですが…。

  1. atom-html-preview
  2. tabs-to-spaces
  3. tag

atom-html-preview

Ctrl+Shift+Hでhtmlプレビューが見れるようになるすぐれもの。特にhtmlに不慣れな見としてはちゃんとタグが動いているか、どのようになるのかなどがリアルタイムで確認できるので重宝しています。

tabs-to-spaces

ソフトタブ信者として必須と思い、迷うことなく入れました。機能としては単純に強制的にソフトタブに変換してくれるもののようでした。また、ちょっと変わった要素として「保存時にタブ形式を一括変換する」設定もありました。

tag

何はともあれ入れるべきプラグインだと思います。機能はシンプルにAlt+Cmd+.で自動的にクローズタブを入れてくれます。自分みたいにタグに慣れていない人間や、 少しでも書く手間を減らしたい人間にとってまず間違いない便利プラグインだと思います。これから色々とプラグインを入れたり外したりしていくと思いますがこのプラグインだけは ずっと使い続けると思います。そう思わせてくれるほど便利なプラグインです。

google-code-prettifyの導入

正直なところ、まだ上手く使えていませんが、導入方法は至ってシンプルでした。

  1. google-code-prettifyをダウンロード。
  2. Bloggerテンプレートのhtmlを開き、Header内にrun_prettify.jsを参照する処理を記述。

上記2点を行うだけで、以下のようにソースコードがわかりやすく表示されるようになりました。

int a = 0;
a ++;
int b = 0;
b = a;
            

cssファイル等のアップロード用にGitHub.ioの登録

私は普段仕事でも個人でもGitHubを使用して コードの 管理をしているのですが、実はこのGitHub、GitHub.ioというページがあって、 簡単にウェブページやブログ的なことができる機能が あり、なにやらウェブページを簡単に実装できるとのことでした。なので今回はこちらを登録し、 各種cssファイル(google-code-prettifyや自作css等)をアップして使うことにしました。

試しに登録してみたところ、簡単に、かつ無料でアップローダー的な 使い方ができるリポジトリの作成ができたため、是非使ってみてください。実はこの 記事に貼ってある画像やcssも、登録したGitHub.ioから引っ張ってきています。

結論

色々と書きましたが、今回課題となっていたソースコードを見やすく表示したいという課題ですが、私はgoogle-code-prettifyと、GitHub.ioを使うことによって解消できました。

なので実はhtmlで記事を書く必要はなく、マークダウンでも行けたのでは?という状態になっています…。今からブログを書こうと思っている方は、マークダウンにするかhtmlをゴリゴリ書いていくか、自分に必要な機能とそれぞれの手法でできることをしっかりと調べて、選ぶことをおすすめします。
(私はせっかくなのでhtml、cssの勉強もかねてこのまま頑張って書いていこうと思います…。)

2018年7月5日木曜日

【緊急時】海外でパスポートの更新が必要な方へ。必要な書類と抜け穴についての共有。

はい。
題名通りですが、「国外にいる時にパスポートの更新/再発行が必要になってしまった!」という場合どうするのか、という内容です。

国外にいるときパスポートの更新が必要になったらどうなるか…

実は私海外に住んでいるのですが、ふと気がついたらパスポートの有効期限が6ヶ月切っていました
正直「終わった」と思いましたね。はい。

ご存知の方も多いでしょうが、一般的に国際便で移動する際は「パスポートの有効期限が6ヶ月以上残っている」ことが前提条件となることが多いです。
つまりこのままだと、可能性としては以下がありえそうかなと思います。

  1. パスポート発行のために日本に一時帰国しようとしても、そもそも出国できない。
  2. 日本へ帰国はできても、新しいパスポートの発行が完了するまで、現在住んでいる国に再度入国できない。

今の国で仕事をしている以上、正直「長期滞在になるかもしれないリスク」は厳しいものがあるので結構なピンチ…。


と、いうことで色々調べてみましたので共有します。

パスポート申請に必要なもの

まず外務省の公式ページから
国内及び国外でパスポートに関する申請手続きに通常必要な書類

ここを見る限り、私が該当するのは以下の部分ですね。

切替発給
残存有効期間が1年未満となった方
査証欄に余白がなくなった方(ページ数を増やす査証欄増補の申請も可能です。)

で、詳細を見てみると、国外でのパスポート切り替え申請に必要なものは以下の4点。

  1. 一般旅券発給申請書(10年用又は5年用) 1通
    • 平成28年1月4日以降,国外では併せて「ダウンロード申請書」が使用できます。
  2. 写真(縦45ミリメートル×横35ミリメートル) 1葉
  3. 有効旅券
    返納していただき、失効処理をいたします。残存有効期間は新しい旅券の有効期間には加算されません。
    (戸籍上の身分事項に変更がある場合)
  4. 戸籍謄本又は抄本(原本を必要とします) 1通


1. 一般旅券発給申請書(10年用又は5年用) 1通

1番の申請書がダウンロードで使えるというのは正直驚きましたが、便利でした。
実はこれ情報の登録は全部ブラウザ上で行って、印刷してサインだけ直筆で入力すればOKというすぐれもの。
私みたいに日本語書くのが苦手だったり、そもそも書くのが面倒という方にピッタリ。

ただ、ここのサイトを開いてもらえると分かるのですがこの申請書何故か日本では未対応です


日本人向けの日本国用のパスポート発行のためのシステムを、日本国外では使えるのに日本国内では使えないとは…。
つっこみどころ満載ですが、まぁそれはいいです。
そこの問題点や日本のシステムについての愚痴を書くとそれだけで記事が何件にもなりそうなので飛ばします。

2. 写真(縦45ミリメートル×横35ミリメートル) 1葉

これは特に問題ないと思います。
ただ国によってはまともな証明写真が取れない場所も有るかと思いますので、事前に調べておいたほうが良いかと思います。
とりあえず私は、今後証明写真を何枚か財布に忍ばせておこうと決心しました。

3. 有効旅券

これも特に問題ないと思います。
というより問題がある場合は「切替発給」ではなく「紛失届」が必要になりますので、詳しくは外務省の公式ページにて調べてください。

4. 戸籍謄本又は抄本(原本を必要とします) 1通

ラスボスです。
特にこの(原本を必要とします)がいやらしいですね。

とりあえず日本国内にいる人に代理で戸籍謄本を取得して貰う場合ですが、以下の条件があります。

6親等以内の血族、3親等以内の姻族、そして配偶者

※参照 : 委任状なしで取れる親族の戸籍謄本の範囲は?

下手するとこの段階で詰む人もいるかと思いますが、無事戸籍謄本を取れる前提で話しを進めます。

そして次のフェーズとして、日本で取得した戸籍謄本を国外にいる自分の元へ送ってもらう必要があります。
国によってまちまちと思いますが、私がいる国ではこれが容易ではなく、そもそも日数がかかったり、本当に届くか怪しかったりしますが、原本が必須といわれると送ってもらう以外選択肢はありません。
急いでパスポートを発行しなければ行けないという人が何日間も届くかわからない書類を待つのは精神的にも結構厳しいと思います…。

戸籍謄本の抜け道

で、最後に戸籍謄本の面倒な待ち時間をなんとかして排除できないか?という部分なんですが、実は2つ方法がありました。

こちらです。

  1. 戸籍謄本を用意しない。
  2. 戸籍謄本の原本を用意しない。

はい。そもそも戸籍謄本を使わずに、なんとかパスポートの申請を通してしまえば良いということです。
もちろんこれは賄賂や裏のどうこうではなく、正式にOKな手順を踏んだ上で、このようなやり方がある、という内容です。

1. 戸籍謄本を用意しない。

実は先程の外務省のページを見てもらえると分かると思うのですが、地味に分かりづらく以下の文章が書いてあります。

(戸籍上の身分事項に変更がある場合)
戸籍謄本又は抄本(原本を必要とします) 1通

よくよく調べて見たのですが、「紛失届」、及び新規旅券の申請や渡航書を申請する場合は必ず戸籍謄本が必要ですが、切替発給では必ずしも必要では無かったんですね…。
なので、特に戸籍に変更が無い方は戸籍謄本は必要ありません。

戸籍に変更があるかた、または何らかの事情でどうしても戸籍謄本が必要な方は以下を試してみてください。

2. 戸籍謄本の原本を用意しない。

これは原本じゃないモノでなんとかしてみよう!ということですが、実はこの戸籍謄本ってFAXでもOKだったりします。
特に公式に明記されているわけではないのですが、いくつかのパスポート紛失した方のブログを見ていると、「FAXでOKと言われた」というケースや「時間がなくなって、もうFAXで良いよと言われた」というケースがあるようでした。
一応「日本に帰国後に原本をしっかりと提出すること」が条件となっているようですが、FAXだけで住む場合は最悪旅行会社や勤め先にFAXを送ってもらうなどでも対応できそうです。

「今さらFAX機能付きの固定電話なんて持ってないよ」という方も多いと思いますので、必要な場合は大使館に相談してみると対応してくれるケースもあるそうです。
国によって違ったりするのでなんとも言えませんが、少なくとも相談する価値は有るかと思います。


まとめ

今回自分のケースとしては、戸籍に特に変更がないただの期限切れによる切替発給なため、戸籍謄本は不要らしいので後日証明写真だけ撮って申請に行ってきます。
(領事館に問い合わせの電話もしましたが、「戸籍に変更なければ大丈夫!」という力強い返事を頂いたので問題ないと思います)

こちら無事申請できて、無事新しいパスポートをゲットできたら一応結果だけまとめると思います。

t

2018年7月4日水曜日

[Unity C#] アクセス装飾子メモ。internalって何?

よく忘れるのでメモ

  1. public : あらゆるクラス、スクリプトから参照可能。
  2. protected : 親クラスからのみ参照可能。
  3. private : 自クラスからのみ参照可能。
  4. internal : 同スクリプト無いなら参照かのう。他クラスでもOK。



上記4番の internal をよく忘れてしまう…。
かつ「Unity C# アクセス装飾子」で検索しても「アクセス装飾子とはなにか?」的なサイトの検索結果が多くて探しづらい…。

ちなみにアクセス装飾子とは、メンバーや関数へのアクセス/参照するための権限を設定する的なことです(一応)。




また、小ネタとして UpdateAwake などの UnityEventprivatepublic 設定をしても正常に呼び出されます。
なので、他クラスから参照してほしくない場合は protected などにして、参照できないように自分は普段しています。

継承した子クラスで Update を設定した場合、親クラスの Update は自動的には呼び出されないので、 base.Update() などで親クラスの関数を忘れずに呼び出してください。

2018年7月3日火曜日

日常雑記。略して日記。

ベトナムで生活を始めてからしばらくして、今まで電動バイクを使って通勤や買い物等してるんですが、最近やけに電池の減りが早い気がするし音もなんかよろしくない音になっている気がする…。

まだ一年ほどしか乗ってないけど、中国産(恐らく)だしメンテナンスも一切行ってないからそろそろガタが来てるのかな…。

見た目も気に入ってるし、バイクがないとまともに生活できないからできれば廃棄/買い替えはしたくないけど…。
次の国へ転職するまで頑張ってほしいと思う今日この頃。


ちなみにこの国、バイクで20分ほどの距離をタクシーで乗ったとしても大体100Kvnd(500円)ほどでいけたりするので
最悪短期の期間ならバイクがなくても生活はできます。
**ただし**近距離だとタクシーの運ちゃんに断られたりするので、正直バイクがないと色々とめんどくさかったりします…。

2018年6月27日水曜日

[Unity C#] 汎用的かつシンプルなSingletonの実装方法(サンプルあり)

Unityで実装する際、結構な頻度でManagerクラスが必要だったりするので簡単なSingletonクラスを作成しました。
一言にSingletonクラスといっても、Attributeの設定やら初期設定やら色々有るとは思いますが、今回自分が作成したのは以下の3パターンのみです。

今回実装したSingletonクラス一覧

  1. 全てのクラスで継承可能なSingletonクラス。
    • インスタンス生成時は必ず引数なしのコンストラクタが呼び出されます。
    • 引数ありのコンストラクタが使いたい場合は別途Initialize関数でも作ってください。
  2. 全てのMonoBehaviourを継承したいクラスで継承可能なMonoSingletonクラス。
    • Scene上で同じクラスを保持しているオブジェクトがあるかを確認し、ない場合はインスタンス生成します。
    • インスタンス生成が必要な際は、まず空のGameObjectを作成し、AddComponentで自身を追加します。
    • つまりこちらも引数なしのコンストラクタが呼び出されます。
    • 引数ありのコンスタクタを使いたい場合は(ry
  3. Scene遷移時に削除されないようにしたMonoSingletonを継承したクラス、PersistentMonoSingleton.
    • MonoSingletonを継承し、Scene遷移時に削除されないようにしただけ。
    • Sceneに依存するのか、生存し続けるのかわからなくなりそうだったのでクラス分けしただけです。

サンプルコード

今回のサンプルはかなりシンプル。
ただUpdate関数内でひたすらInstance取得を行うだけ。
また、各Singletonクラスでは生成時にログ吐く用に設定してあります。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
/// <summary>
/// Singleton manager sample.
/// </summary>
public class SingletonManager : MonoBehaviour
{
    /// <summary>
    /// Update this instance.
    /// </summary>
    private void Update()
    {
        // Get instance of singleton every frame to check.
        SampleSingleton singleton = SampleSingleton.Instance;
        SampleMonoSingleton monoSingleton = SampleMonoSingleton.Instance;
        SamplePersistentMonoSingleton persistentMonoSingleton = SamplePersistentMonoSingleton.Instance;
 
        if(singleton == null)
        {
            Debug.LogError("SampleSingleton is null.");
        }
        if(monoSingleton == null)
        {
            Debug.LogError("SampleMonoSingleton is null.");
        }
        if(persistentMonoSingleton == null)
        {
            Debug.LogError("SamplePersistentMonoSingleton is null.");
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TC;
 
public class SampleSingleton : Singleton<SampleSingleton>
{
    public SampleSingleton()
    {
        Debug.Log("Constructor called for " + GetType().FullName);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TC;
 
public class SampleMonoSingleton : MonoSingleton<SampleMonoSingleton>
{
    public SampleMonoSingleton()
    {
        Debug.Log("Constructor called for " + GetType().FullName);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TC;
 
public class SamplePersistentMonoSingleton : PersistentMonoSingleton<SamplePersistentMonoSingleton>
{
    public SamplePersistentMonoSingleton()
    {
        Debug.Log("Constructor called for " + GetType().FullName);
    }
}

実装サンプル






実際のソースコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
namespace TC
{
    /// <summary>
    /// Singleton class for all non MonoBehaviour class.
    /// </summary>
    public abstract class Singleton<T> where T : new()
    {
        private static T instance;
        public static T Instance
        {
            get
            {
                if(instance == null)
                {
                    instance = new T();
                }
                return instance;
            }
        }
 
        /// <summary>
        /// Creates new instance if need.
        /// </summary>
        /// <returns><c>true</c>, if instance is successfully loaded or created, <c>false</c> otherwise.</returns>
        public static bool CreateIfNeed()
        {
            if(instance != null)
            {
                return false;
            }
            // Create instance by calling Getter.
            return Instance != null;
        }
    }
 
    /// <summary>
    /// Singleton class for all Monobehaviour class.
    /// </summary>
    public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
    {
        // Callback on when Instance is requested.
        protected static System.Action onRequestInstance = null;
        // Callback on when Instance is newly created.
        protected static System.Action onCreateInstance = null;
        // Callback on when Instance is found from scene and set to Instance.
        protected static System.Action onUpdateInstance = null;
 
        private static T instance;
        public static T Instance
        {
            get
            {
                if(instance == null)
                {
                    T[] validInstances = GameObject.FindObjectsOfType<T>();
                    if(validInstances == null || validInstances.Length <= 0)
                    {
                        // Create new instance.
                        GameObject gameObject = new GameObject();
                        // At this moment, instance settings will not be applied.
                        // Each settings such as name will be updated on Awake.
                        instance = gameObject.AddComponent<T>();
 
                        if(onCreateInstance != null)
                        {
                            onCreateInstance();
                        }
                    }
                    else
                    {
                        // Load instance from scene.
                        instance = validInstances[0];
                        if(validInstances.Length > 1)
                        {
                            Debug.Log("More than 1 instance is created. Destroying duplicate instances.");
                            for(int i = 1; i < validInstances.Length; i++)
                            {
                                Destroy(validInstances[i].gameObject);
                            }
                        }
 
                        if(onUpdateInstance != null)
                        {
                            onUpdateInstance();
                        }
                    }
                }
 
                if(onRequestInstance != null)
                {
                    onRequestInstance();
                }
                return instance;
            }
        }
 
        /// <summary>
        /// Creates new instance if need.
        /// </summary>
        /// <returns><c>true</c>, if instance is successfully loaded or created, <c>false</c> otherwise.</returns>
        public static bool CreateIfNeed()
        {
            if(instance != null)
            {
                return false;
            }
            // Create instance by calling Getter.
            return Instance != null;
        }
 
 
        /// <summary>
        /// Awake this instance.
        /// </summary>
        protected virtual void Awake()
        {
            InitializeInstance();
        }
 
        /// <summary>
        /// Initializes the instance.
        /// </summary>
        protected virtual void InitializeInstance()
        {
            gameObject.name = this.GetType().FullName;
        }
    }
 
    /// <summary>
    /// Persistent singleton.
    /// This class will not be destroyed on load.
    /// </summary>
    public abstract class PersistentMonoSingleton<T> : MonoSingleton<T> where T : MonoBehaviour
    {
        /// <summary>
        /// Awake this instance.
        /// </summary>
        protected override void Awake()
        {
            base.Awake();
            GameObject.DontDestroyOnLoad(Instance);
        }
    }
}

実際のソースコードはこちらにUPしてあります。
https://github.com/table-cloth/tc-common/blob/develop/Assets/Scripts/Singleton.cs

2018年6月26日火曜日

[Unity C#] オブジェクトのプールの実装方法(サンプルあり)

Unityで開発する際、よくオブジェクトをプールする必要があるのですが、毎回調べなおしたり作り直したりするのが億劫になったので、使い回す用のUtil作成してみました。

とりあえず、ソースはこちらにUPしてあります。

[Pool.cs]
https://github.com/table-cloth/tc-common/blob/develop/Assets/Scripts/Pool.cs
[PoolManager.cs]
https://github.com/table-cloth/tc-common/blob/develop/Assets/Scripts/PoolableObject.cs

オブジェクトのプールって何?

そもそもプールって何よ?という方向けの説明です。
知っている方は読み飛ばしてください。

プールとは何か。

プールとはオブジェクトのストックを保持する場所のことで、オブジェクトの生成、取得処理を効率化されるためによく使われている手法です。
プールを使用する場合、基本的にプールからオブジェクトを取得します。
そしてプールの中に使用可能なオブジェクトが存在する場合はそれを渡し、存在しない場合のみオブジェクトを新規生成しそれを渡します。
また、使用終了したオブジェクトをプールに返すことによって、可能な限りオブジェクトのインスタンス化する処理を省くというものです。

例えば、マシンガンで1万発弾を打つ場合、本来なら1万個のオブジェクト生成が必要ですが、0.01秒に弾を一発発射し、0.1秒で着弾(使用終了)する場合、オブジェクトの生成回数は10回のみで済みます。
そうすることで処理は高速化されますし、シーン上に無駄にオブジェクトを増やさなくて済むことになります。

オブジェクトをプールする方法について。

今回実装した内容は、以下のような内容になっております。

  1. PoolableObjectを設定したPrefabを作成する。
  2. Poolインスタンスを保持したクラスを用意する。
    • 今回はManagerクラスという名前ということにしておく。
  3. ManagerクラスとPoolableObjectを設定したPrefabを紐付ける。
    • SerializeFieldPrefabを設定するか、Resources.LoadPrefabを取得する想定です。
  4. Pool生成時にPoolableObjectを設定。
  5. Pool.GetOrCreate()という関数を呼び出せば自動的に設定したPoolableObjectが取得、または生成される。

ちょっと3番のPoolPrefabの紐づけが手動で煩わしいけれど、プールしたい物体なら毎回Prefabを設定するだろうということで今回の実装となっています。

サンプルコード

0.1秒ごとにオブジェクトをプールから取得し、1.0秒毎にオブジェクトをプールに返すサンプル。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
/// <summary>
/// Sample pool manager.
/// </summary>
public class SamplePoolManager : MonoBehaviour
{
    private const float SpawnDelay = 0.1f;
    private const float DestroyDelay = 1.0f;
 
    [SerializeField]
    private PoolableObject poolableObject;
    private Pool pool;
 
    public void Start()
    {
        pool = new Pool(poolableObject);
        StartCoroutine(RepeatSpawnPoolableObject(SpawnDelay));
    }
 
    /// <summary>
    /// Repeats the spawn poolable object.
    /// </summary>
    /// <returns>The spawn poolable object.</returns>
    /// <param name="_delay">Delay.</param>
    private IEnumerator RepeatSpawnPoolableObject(float _delay)
    {
        yield return new WaitForSeconds(_delay);
 
        PoolableObject obj = pool.GetOrCreate(this.transform);
 
        float randX = Random.Range(0.0f, 1.0f);
        float randY = Random.Range(0.0f, 1.0f);
        float randZ = Random.Range(0.0f, 1.0f);
        obj.GetComponent<Rigidbody>().velocity = new Vector3(randX, randY, randZ);
        obj.transform.localPosition = Vector3.zero;
 
        obj.Return2Pool(DestroyDelay);
 
        StartCoroutine(RepeatSpawnPoolableObject(_delay));
    }
}

実行サンプル


実際のコード

プールクラス。

オブジェクトのプールを行う場合、こちらのインスタンスが1つ必要。
インスタンスが複数存在してしまうと、プールの中身が分散されてしまうので要注意。

基本的にGetOrCreateReturn2Poolだけで使えます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
/// <summary>
/// Class for basic pooling.
/// Will need to be used with PoolableObject.
/// </summary>
public class Pool
{
 
    private const int PoolSizeNoLimit = -1;
 
    // Object to be pooled.
    private readonly PoolableObject poolableObject;
    private readonly Queue<PoolableObject> pool;
 
    /// <summary>
    /// Initializes a new instance of the <see cref="Pool"/> class.
    /// </summary>
    /// <param name="_poolableObject">Poolable object.</param>
    /// <param name="_maxPoolSize">Max pool size.</param>
    public Pool(PoolableObject _poolableObject, int _maxPoolSize = PoolSizeNoLimit)
    {
        poolableObject = _poolableObject;
        pool = _maxPoolSize == PoolSizeNoLimit
            ? new Queue<PoolableObject>()
            : new Queue<PoolableObject>(_maxPoolSize);
    }
 
    /// <summary>
    /// Gets the pool instance from queue or creates new pool instance.
    /// </summary>
    /// <returns>The or create.</returns>
    /// <param name="_parent">Parent.</param>
    /// <param name="_localPos">Local position.</param>
    public PoolableObject GetOrCreate(Transform _parent, Vector3 _localPos = default(Vector3))
    {
        PoolableObject poolObj = GetPoolableObject(_parent);
        if (poolObj == null) poolObj = CreatePoolableObject(_parent);
 
        // Initialize poolable object, no matter get or create.
        poolObj.gameObject.SetActive(true);
        poolObj.transform.localPosition = _localPos;
 
        return poolObj;
    }
 
    public List<PoolableObject> GetAllObjectsInPool()
    {
        return new List<PoolableObject>(pool);
    }
 
    /// <summary>
    /// Returns pool instance to the pool.
    /// </summary>
    /// <param name="_poolableObject">Poolable object.</param>
    public void Return2Pool(PoolableObject _poolableObject)
    {
        pool.Enqueue(_poolableObject);
        _poolableObject.gameObject.SetActive(false);
    }
 
    /// <summary>
    /// Gets the poolable object from queue.
    /// </summary>
    /// <returns>The poolable object.</returns>
    /// <param name="_parent">Parent.</param>
    private PoolableObject GetPoolableObject(Transform _parent)
    {
        if (!IsPoolObjectAvailable()) return null;
 
        PoolableObject poolObj = pool.Dequeue();
        poolObj.transform.SetParent(_parent);
        return poolObj;
    }
 
    /// <summary>
    /// Creates new poolable object.
    /// </summary>
    /// <returns>The poolable object.</returns>
    /// <param name="_parent">Parent.</param>
    private PoolableObject CreatePoolableObject(Transform _parent)
    {
        PoolableObject poolObj = PoolableObject.Instantiate(this, poolableObject);
        poolObj.transform.SetParent(_parent);
        return poolObj;
    }
 
    /// <summary>
    /// Determines whether reusable pool object is available in pool.
    /// </summary>
    /// <returns><c>true</c> if this instance is pool object available; otherwise, <c>false</c>.</returns>
    private bool IsPoolObjectAvailable()
    {
        return pool.Count > 0;
    }
}

プールしたいオブジェクト用クラス。

基本的にこちらの処理を呼び出す必要はなし。
必要に応じてReturn2Poolを呼び出してあげればOK。
Return2PoolPool、または PoolableObjectのどちらかで1回呼ぶだけでOK。)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
/// <summary>
/// Class for pooling objects.
/// </summary>
public class PoolableObject : MonoBehaviour
{
 
    // Pool where this object is spawned from.
    private Pool pool;
 
    /// <summary>
    /// Instantiate the specified _poolableObject in _pool.
    /// </summary>
    /// <param name="_pool">Pool.</param>
    /// <param name="_poolableObject">Poolable object.</param>
    public static PoolableObject Instantiate(Pool _pool, PoolableObject _poolableObject)
    {
        PoolableObject poolableObject = Instantiate(_poolableObject);
        poolableObject.pool = _pool;
        return poolableObject;
    }
 
    /// <summary>
    /// Returns this poolable object to pool.
    /// </summary>
    public void Return2Pool() {
        pool.Return2Pool(this);
    }
 
    /// <summary>
    /// Returns this poolable object to pool after delay sec.
    /// </summary>
    public void Return2Pool(float _delay)
    {
        StartCoroutine(CoReturn2Pool(_delay));
    }
 
    /// <summary>
    /// Returns this poolable object to pool after delay sec.
    /// </summary>
    private IEnumerator CoReturn2Pool(float _delay)
    {
        yield return new WaitForSeconds(_delay);
        Return2Pool();
    }
 
}
sa

2018年6月25日月曜日

【ブログ初心者用】htmlでの記事投稿お助けツールAtomについて


実は私、今Bloggerで記事を書いていますが、つい最近ブログを始めてみようと思った結果、はじめに選んだものはLivedoorBlogでした。

そしてブログを作って「さぁ書くぞー!」ってなってふと気がついたことが…。


「あれ、ブログってマークダウンじゃなくてHTMLで書くの…?」

冷静に考えればまぁそりゃそうだ、な感じなんですが、なぜか当然のようにマークダウンでブログをかける感覚でいました…。
(調べた所、別にマークダウン対応しているブログもいくつかあるようでしたが、作って早々に書きづらいから、でブログを変えるのもなー、と思い対策を調べてみました。)

で、そこでまさかのマークダウンで書いた文章をHTMLに変換できるエディターを発見したので早速インストール!

[Atom]
https://atom.io/

試してみた所、マークダウンを書きながら、リアルタイムでHTMLプレビュー変換できたり、簡単にHTMLとしてファイル保存/出力できたりとかなり便利な感じでした。
ので、とりあえず暫くの間このエディタを使って記事を書かせていただこうと思います。



ただ実はもう一点問題があり、
流石にマークダウンだけではブログの見た目の改修はできないので、流石にCSSは覚えないとなーという感じです。
そのうちちょこちょこ調整するとは思いますが、CSS勉強したら実際のCSSに関する記事とか上げるかもしれません。

実はまだBloggerでCSS適用できんの?とか
もっと楽な方法あるんじゃないの?とかはまだ調べていないのでわかりませんが…。
何か良い方法とか勉強進んだら記事にするかもしれません。

Atomの便利なショートカット(随時追加予定)

  1. Ctrl+Shift+M : マークダウン -> HTML変換


参考にさせていただいたサイト様

https://webtatan.com/blog/wordpress/wordpress-markdown

技術ブログを始める際に困ったこと。コードの見やすさについて。

以前の記事 で Atom使ってマークダウンで記事書けばすっごい楽! ということを書きましたが、色々試しているうちにどうやらマークダウンだけでは少々問題がありそうだったので、主な問題とその解決方法について書いていきます。 まぁタイ...