さくらVPSでWordPressの更新をFTPから

1.経緯

テーマやらプラグインやらインストールしたり更新するたびに、
FTPの認証を求められてて、
そのたびにFTPのポートを開けたりしていたのが、とても面倒でした。

2.FTPポートをカスタムしてローカルのみ許可

パケットフィルタ機能があるからそこにポート追加すればいいんだろうなとは思いつつ、
とりあえず、設定ファイルにパスワードを設定!

下記のサイトを見ながらパスワードを設定してあげてください。

WordPressでアップデート時にFTP接続情報を聞かれないようにする方法
http://nb-style.info/?p=918

この時点でテーマのインストール&アンインストールが問題なく動いたので、
パケットフィルタリングの設定はいらんかったんや!と気づいた!!!
ポート開け閉めの苦労!!!ガッデム!!!!!!

Unityで3Dモデルをマウスクリックで動かす

1.経緯

3Dモデルが作れるっていうVRoidStudioを触ってキャラクターを作ったので、
Unityで動かせたらな!と思ったのがきっかけ。

完成というわけではないけど、
イメージはこんな感じ。

細かいところではイケてないところがあるので課題ですねぇ。。。

基本的には下記のサイトを参照してください!
ここでは、補足のみ記載します!

【ゼロから】VRoidで作ったキャラ(3Dモデル)をUnityで動かす(Unity編)
https://miyagame.net/vroid-unity-unity/

2.キャラのインポート

VRoidStudoioでエクスポートした形式は、拡張子がvrmっていうもので、
Unityに取り込むにはUniVRMというものが必要らしいです。

UniVRM
https://github.com/vrm-c/UniVRM/blob/master/README.ja.md

プロジェクトを開いておいて、ダブルクリックすれば適用された気がします。
それか、「アセット」→「パッケージをインポート」→「カスタムパッケージ」で。

いろいろ警告が出ててもエラーでなければ、
とりあえずOKかな。

あとは、vrmファイルをプロジェクトにドラッグ&ドロップしてあげればプレハブ化されます。
シーンウィンドウに放り上げてあげましょう(^^

3.キャラを動かすためのアセットをインポートしましょう

動かしたいのでコントローラーを入れていきたいですねってことで、
「ウィンドウ」→「アセットストア」!
※ウィンドウが小さかったら、ウィンドウの右上の縦3点から「最大化」しましょう。

検索ボックスに「standard assets」を入力して出てくる、
「Standard Assets (for Unity 2017.3)」を選んでください。

選択したら、「Import」を!

インポート完了したら、コンソールに警告が出ているけど、エラーも出ているはず。
こちらを解決していきましょう。

下記のサイトを参考にしてエラーを解消してください。

Unity 2019.3でのStandard Assetsのエラーへの対処方法
https://www.sbcr.jp/support/48965/

4.キャラが動けるように設定しましょう

3Dモデルを選択して、Animatorのコントローラーに「ThirdPersonAnimatorController」を設定。

3Dモデルに「コンポーネントを追加」から、左記の2つを入れていきましょう。

「Capsule Collider」はキャラクターの体系に合うように調整してください。
※あっていない場合、動かなかったりします。

5.クリック位置に移動するようにしましょう

床を静的にしてください。

「ウィンドウ」→「AI」→「ナビゲーション」を選択して、
ナビゲーションウィンドウを開いてください。

開いたら、床にベイクを設定しましょう。

左記のような水色のエリアが移動可能エリアになります。

次は、3DモデルにAgentを追加してあげます。
「コンポーネントを追加」→「ナビ メッシュ エージェント」

「速度」は3Dモデルを置き去りにしない速度を設定しましょう。

曲がり角で、ナビだけが先に行ってしまいます。

「Third Person User Control」は無効にしておきましょう。

次で作成するプログラムと命令が競合してしまうので。。。

ここまできたら、やっとプログラムを記述します。
ファイル名はMoveにでもしましょうか。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using UnityStandardAssets.Characters.ThirdPerson;
//using UnityStandardAssets.CrossPlatformInput;

[RequireComponent(typeof(ThirdPersonCharacter))]
public class Move : MonoBehaviour
{
    NavMeshAgent agent;
    RaycastHit hit;
    private ThirdPersonCharacter character;

    private bool m_Jump;
    private bool crouch;
    private string Direction;

    // Start is called before the first frame update
    void Start()
    {
        character = GetComponent<ThirdPersonCharacter>();
        agent = GetComponent<NavMeshAgent>();
        agent.updatePosition = false;
    }

    // Update is called once per frame
    void Update()
    {

        Flick();
        switch (Direction)
        {
            case "up":
                Debug.Log("Jump");
                if (!m_Jump)
                {
                    m_Jump = true;
                }
                break;

            case "down":
                //下フリックされた時の処理
                crouch = true;
                break;

            case "right":
                //右フリックされた時の処理
                break;

            case "left":
                //左フリックされた時の処理
                break;

            case "touch":
                Debug.Log("touch");
                //タッチされた時の処理
                SetDestinationToMousePosition();
                break;
        }

        if (crouch == true)
        {
            character.Move(Vector3.zero, crouch, false);
            agent.ResetPath();
            crouch = false;
        }
        else if (agent.hasPath == true)
        {
            character.Move(agent.nextPosition - transform.position, false, m_Jump);
            m_Jump = false;
        }
        else
        {
            character.Move(Vector3.zero, false, m_Jump);
            m_Jump = false;
        }

    }

    void SetDestinationToMousePosition()
    {
        if (agent.pathStatus == NavMeshPathStatus.PathInvalid)
        {
            Debug.Log("NoReady");
            return;
        }

        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out hit))
        {
            agent.SetDestination(hit.point);
        }
    }

    private Vector3 touchStartPos;
    private Vector3 touchEndPos;

    void Flick()
    {
        Direction = "";
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            touchStartPos = new Vector3(Input.mousePosition.x,
                                        Input.mousePosition.y,
                                        Input.mousePosition.z);
        }

        if (Input.GetKeyUp(KeyCode.Mouse0))
        {
            touchEndPos = new Vector3(Input.mousePosition.x,
                                      Input.mousePosition.y,
                                      Input.mousePosition.z);
            GetDirection();
        }
    }

    void GetDirection()
    {
        float directionX = touchEndPos.x - touchStartPos.x;
        float directionY = touchEndPos.y - touchStartPos.y;

        if (Mathf.Abs(directionY) < Mathf.Abs(directionX))
        {
            if (30 < directionX)
            {
                //右向きにフリック
                Direction = "right";
            }
            else if (-30 > directionX)
            {
                //左向きにフリック
                Direction = "left";
            }
        }
        else if (Mathf.Abs(directionX) < Mathf.Abs(directionY))
        {
            if (30 < directionY)
            {
                //上向きにフリック
                Direction = "up";
            }
            else if (-30 > directionY)
            {
                //下向きのフリック
                Direction = "down";
            }
        }
        else
        {
            //タッチを検出
            Direction = "touch";
        }
    }
}

フリック操作については、下記のサイトを参考にしました。

Unity-フリック操作について
https://qiita.com/pilkul/items/e8864882b3f7e59b05e3

障害物はキューブなどで作り、床と同様に「Navigation Static」にしてください。

「NavigationArea」を「NotWalkable」にすることで障害物になります。

こんな感じですね。
大きさとか色は適当に設定してます。

6.その他

動く障害物などあるようなのですが、そちらについてはまた気が向いたら試してみます。
とりあえず、参考リンクのみ。

【Unity】NavMeshを学ぶ 障害物編
https://www.urablog.xyz/entry/2017/10/14/190557

Unityでアプリ制作~タッチ操作を添えて~

1.経緯

なんとなーくUnity環境を構築したので、せっかくだからアプリを作ってみようと。

2.参考サイト

こちらのサイトさんを参考にさせていただきました。
私の環境では環境構築が完了していたので、#2からですね!

Unity入門
https://dotinstall.com/lessons/basic_unity_v2

3.問題に衝突

途中でちょっとしたタイプミスなどありつつ、
なかなか順調に進んでたんですけど、
最後に問題にぶつかりました!

「アプリに書き出してもタッチ操作に反応しない!」

まぁ薄々そんな気はしてました。
だって、スマホに矢印キーはないもの!!!

4.解決

いろいろなサイトを見て回りました!
結果的に作ったコードは以下の通りです!
(赤色の部分以外は、参考サイトを参照してください)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AppUtil : MonoBehaviour
{

    private static Vector3 TouchPosition = Vector3.zero;

    /// <summary>
    /// タッチ情報を取得(エディタと実機を考慮)
    /// </summary>
    /// <returns>タッチ情報。タッチされていない場合は null</returns>
    public static TouchInfo GetTouch()
    {
        if (Application.isEditor)
        {
            if (Input.GetMouseButtonDown(0)) { return TouchInfo.Began; }
            if (Input.GetMouseButton(0)) { return TouchInfo.Moved; }
            if (Input.GetMouseButtonUp(0)) { return TouchInfo.Ended; }
        }
        else
        {
            if (Input.touchCount > 0)
            {
                return (TouchInfo)((int)Input.GetTouch(0).phase);
            }
        }
        return TouchInfo.None;
    }

    /// <summary>
    /// タッチポジションを取得(エディタと実機を考慮)
    /// </summary>
    /// <returns>タッチポジション。タッチされていない場合は (0, 0, 0)</returns>
    public static Vector3 GetTouchPosition()
    {
        if (Application.isEditor)
        {
            TouchInfo touch = AppUtil.GetTouch();
            if (touch != TouchInfo.None)
            {
                return Input.mousePosition;
            }
        }
        else
        {
            if (Input.touchCount > 0)
            {
                Touch touch = Input.GetTouch(0);
                TouchPosition.x = touch.position.x;
                TouchPosition.y = touch.position.y;
                return TouchPosition;
            }
        }
        return Vector3.zero;
    }

    /// <summary>
    /// タッチワールドポジションを取得(エディタと実機を考慮)
    /// </summary>
    /// <param name='camera'>カメラ</param>
    /// <returns>タッチワールドポジション。タッチされていない場合は (0, 0, 0)</returns>
    public static Vector3 GetTouchWorldPosition(Camera camera)
    {
        Vector3 pos = GetTouchPosition();
        pos.z = Mathf.Abs(camera.transform.position.z);
        return camera.ScreenToWorldPoint(pos);
    }

}

/// <summary>
/// タッチ情報。UnityEngine.TouchPhase に None の情報を追加拡張。
/// </summary>
public enum TouchInfo
{
    /// <summary>
    /// タッチなし
    /// </summary>
    None = 99,

    // 以下は UnityEngine.TouchPhase の値に対応
    /// <summary>
    /// タッチ開始
    /// </summary>
    Began = 0,
    /// <summary>
    /// タッチ移動
    /// </summary>
    Moved = 1,
    /// <summary>
    /// タッチ静止
    /// </summary>
    Stationary = 2,
    /// <summary>
    /// タッチ終了
    /// </summary>
    Ended = 3,
    /// <summary>
    /// タッチキャンセル
    /// </summary>
    Canceled = 4,
}

以下、参考にしたサイトです。

UnityでiOS/Android/Editorの共通タッチ処理を実装する
https://qiita.com/tempura/items/4a5482ff6247ec8873df

さくらVPSのWordPress環境にSSL証明書を設定

1.経緯

先日作成した当サイトの管理者ページにログインしようとしたところ、
「保護されていない通信」と表示されたため、
「おいおい、ログイン情報が保護されていないのは不味いんじゃない?」と思って。

2.「Let’s Encrypt」のSSL証明書を発行

かといって、長続きするか分からないサイトのために有料の証明書を購入するのは、
ちょっと、いや、かなり躊躇われる。

なので、無料でどうにかならないかと調べてみると、、、
「Let’s Encrypt」なるものが使えるらしいじゃないですか!

しかもおあつらえ向きなことに、KUSANAGIならコマンドが用意されていて、
更新までやってくれて、ちょうど構築した環境もKU☆SA☆NA☆GI!!

これは使うしかないということでさっそく!

kusanagi ssl --email [EmailAddress] [Profile]

ところが、、、

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
~省略~
Detail: Invalid response from
http://xxxxxx.com/.well-known/acme-challenge/QEqWBDKJkUucWcuZGr942OUJxwxY5riqaU0iUFCEJns
~省略~
To fix these errors, please make sure that your domain name was
entered correctly and the DNS A/AAAA record(s) for that domain
contain(s) the right IP address.
Cannot get Let\'s Encrypt SSL Certificate files.
失敗しました。

なんじゃこりゃってことですよ。。。

3.解決

いろんなサイトを見まくって頑張りました。
どんなエラーかというと、
証明書発行時にDocumentRoot配下のディレクトリにファイルを配置して、
そのファイルが参照できるかな?って見てるらしいです。

で、私の場合は、証明書発行コマンドが判断したドメインがアクセス可能なドメインじゃなかった!!!
(「xxxxxx.com」じゃなくて「www.xxxxxx.com」だったのさ)

参照権限がどうのこうのとかあったので、かなり惑わされてしまいましたよ。。

まぁ、なんにせよ/etc/nginx/conf.dに移動して、
該当プロファイルのhttp.confにサーバーネームを追加。
※再起動をお忘れなく!(kusanagi nginx)

server_name www.xxxxxx.com;
↓
server_name xxxxxx.com www.xxxxxx.com;

あとは、証明書発行コマンドを再実行すれば...Congratulations!!!

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
~省略~
IMPORTANT NOTES:
Congratulations! Your certificate and chain have been saved at:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Your key file has been saved at:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Your cert will expire on yyyy-mm-dd. To obtain a new or tweaked
version of this certificate in the future, simply run certbot-auto
again. To non-interactively renew all of your certificates, run
"certbot-auto renew"
If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
証明書の自動更新を有効にします
nginx/httpd の設定を変更し、再起動しました。
完了しました。

4.最後の仕上げ

あとはhttpをhttpsにリダイレクトしてあげればOKなので、
/etc/nginx/conf.dに移動して、
該当プロファイルのhttp.confのコメントアウトを除去!
※再起動をお忘れなく!(kusanagi nginx)

# rewrite ^(.*)$ https://www.xxxxxx.com$uri permanent; # SSL ONLY
↓
rewrite ^(.*)$ https://www.xxxxxx.com$uri permanent; # SSL ONLY