20190302のUnityに関する記事は4件です。

【Unity 2D】横スクロールにおける移動床ブロック

移動床ブロック 

3.gif
取り敢えずで作ってみた。この記事で書いた容量でタイルを設置してそれを動かしてみました。以下のスクリプトをタイルにアタッチすればOKです。

移動ブロックにアタッチするスクリプト
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveGround01 : MonoBehaviour
{
    //変数定義
    private Rigidbody2D rb;
    private Vector2 defaultpass;

    void Start()
    {
    rb = GetComponent<Rigidbody2D>();
        defaultpass = transform.position;
    }

    void Update()
    {
    //X座標のみ横移動
    rb.MovePosition(new Vector2(defaultpass.x + Mathf.PingPong(Time.time, 3), defaultpass.y));
    }
}

これでひとまずは動いた。

課題点

  • 移動床ブロックにプレイヤーが乗ったときに、連動して移動しない。衝突判定があった時に、移動床ブロックを親要素にしてプレイヤーを小要素にしてみたが駄目。どちらともリジッドボディだから駄目っぽい。
プレイヤーにアタッチするスクリプト(駄目なバージョン)
    void OnCollisionEnter2D(Collision2D col)
    {
        //衝突したオブジェクトにMoveBlockタグが設定してあるかどうか
        if (col.gameObject.tag == "MoveBlock")
        {
            this.gameObject.transform.parent = col.gameObject.transform; //プレイヤーを親要素に設定
        }
     }

    void OnCollisionExit2D(Collision2D col)
    {
        this.gameObject.transform.parent = null;
    }

これでプレイヤーが子要素にはなったが、上記の課題点どおり連動しては動いてはくれなかった。

移動床ブロックに乗ったらプレイヤーも連動して動くパターン(解決Ver)

4.gif
コメント欄でmamemoyassyさんに色々と教えていただき、無事に連動するものも作れました。SurfaceEffector2Dを利用することで、ベルトコンベアのように上に乗ったオブジェクトに力を加える形で解決しました。

プレイヤーにアタッチするスクリプト
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    //変数定義
    float Slide = 30f;  //横移動の力の強さ
    float flap = 800f;  //ジャンプ時の力の大きさ
    Rigidbody2D rb2d;
    bool jump = false;  //ジャンプが可能かの判定

    void Start()
    {
        //コンポーネント読み込み
        rb2d = GetComponent<Rigidbody2D>();
    }


    void Update()
    {

        //キーボード操作
        if (Input.GetKey(KeyCode.RightArrow))
        {
            //左入力時
            rb2d.AddForce(Vector2.right * Slide);
        }
        else if (Input.GetKey(KeyCode.LeftArrow))
        {
            //右入力時
            rb2d.AddForce(Vector2.left * Slide);
        }


        if (Input.GetKeyDown("space") && !jump)
        {
            //ジャンプ時
            rb2d.AddForce(Vector2.up * flap);
            jump = true;
        }
    }

    //設置判定があればジャンプ判定をfalseへ変更
    void OnCollisionEnter2D(Collision2D other)
    {
        jump = false;
      }
}

プレイヤーのオブジェクトにはRigidbody2Dと何でもいいからcollisionを付けておくこと。

移動ブロックにアタッチするスクリプト
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveGround01 : MonoBehaviour
{
    //変数定義
    Rigidbody2D rb;
    SurfaceEffector2D surfaceEffector;
    Vector2 DefaultPos;
    Vector2 PrevPos;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        DefaultPos = transform.position;
        surfaceEffector = GetComponent<SurfaceEffector2D>();
    }

    void FixedUpdate()
    {
        PrevPos = rb.position;

        // X座標のみ横移動 Mathf.PingPongの数値部分変更で移動距離が変わる
        Vector2 pos = new Vector2(DefaultPos.x + Mathf.PingPong(Time.time, 3), DefaultPos.y);
        rb.MovePosition(pos);

        // 速度を逆算する
        Vector2 velocity = (pos - PrevPos) / Time.deltaTime * 50;

        // 速度のX成分を SurfaceEffector2D に適用
        surfaceEffector.speed = velocity.x;
    }
}

移動床タイルにはRigidbody2DとSurfaceEffector2Dと何でもいいからcollisionを付けておくこと。Mathf.PingPong(Time.time, 3)の3の部分の数値を変えると移動距離も変わります。Y軸にも動かしたいならDefaultPos.yの箇所を変えるとGOODです。

終わりに

mamemoyassyさん色々と教えていただきありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】ド素人からShaderを使えるようにまでに重宝したリンク集まとめ

「Shaderって何それ?」ってレベルから、Shaderを雰囲気で理解できるレベルになりました(多分)

ここまで到達できたのは、”間違いなく”先人たちの最強すぎる情報のお陰様です。

そんな役立った有用すぎるShader学習リンクを紹介していきます!

対象レベル

  • Vertex/Fragment Shader(頂点/フラグメントシェーダー)を一から学ぶ予定の方
  • Shaderやろうとして、何度も挫折した方
  • Shaderを雰囲気で理解してみたい方

※注意
Geometry ShaderやCompute Shaderは含まれていません。理由は私がまだ使えないからです(^p^)

こちら扱えるようになったら、またQiitaにまとめたいと思います。

また数学(高校レベル・行列も出たりする)も関係してくるので、苦手な方は数式とかググりながらやることをオススメします!

7日間でマスターするUnityシェーダ入門

スクリーンショット 2019-03-02 16.41.59.png

控えめにいって神。Shaderを実際に書きながら学習できるので、超オススメです。モチベも維持できます!

Shaderの取っ掛かりには打って付けなので、Shader何からやったら良いの?という方は、ぜひお試しください!

Shaderの基本的な原理を学べるリンク集

Shaderについて原理を深めたくなるお年頃になるときが、いつか訪れるでしょう。

しかし、Shaderの原理に手を出そうとすると、難しさのあまり、気がおかしくなるかもしれません。私はおかしくなりました。

そんな自分でも、”これならわかる!(号泣)”と心から思えるリンクがありました。そちらを紹介します。

Unity Shader Programming Vol.01

スクリーンショット 2019-03-02 16.42.35.png

サンプルソースを添え、丁寧に一からShaderの原理を教えてくれます。

”わかりやすさ”はもちろん、サンプルソースも超簡単なモノを使用してくれているので、挫折しなくて済むのが最高です。

500円(2019/3/1現在)と有料ではございますが、安すぎて価格が崩壊しています。本当にわかりやすいので、購入することをオススメします!

Unity Shader 勉強会@mao_ さん

スクリーンショット 2019-03-02 16.42.20.png
2018年11月8日に「Unity Shader 勉強会」があったようです(羨ましい)

その時、まおさん@mao_ が公開してくださったスライドが超わかりやすかったです。

頂点シェーダを動かす方法について、原理に触れながら丁寧に解説しています。

頂点シェーダー動かした人は必見です!

Unity のシェーダの基礎を勉強してみたのでやる気出してまとめてみた

スクリーンショット 2019-03-02 16.58.45.png

みんなお世話になっているだろう凹みさんのブログ!

サーフェイスシェーダ(Surface Shader)を理解できて大満足した記事になります。

サンプルソースもあって、本当に有益すぎる記事でした。

Unity道場 2月~シェーダを書けるプログラマになろう~

スクリーンショット 2019-03-02 16.41.11.png

2019年2月に行われたUnity道場のアーカイブです。

タイトルの通り、シェーダを書けるプログラマになるための原理を解説してくださっています。

細かいところまで親切に教えてくれる神動画。本当にいつもありがとうございます(ジャンピング土下座)

Shaderサンプル集

ある程度、Shaderの原理がわかってくると、自分で実装したくなると思います。

とはいえ、まだShaderのインプットが少なく、色んなShaderをみてみたい!と思うときがくるかもしれません。

そんな時にオススメしたいリンクをご紹介します。

楽しい!Unityシェーダー お絵描き入門!

スクリーンショット 2019-03-02 17.14.26.png

setchiさんが公開してくださったスライドです。

2Dではありますが、フラグメントシェーダーの考え方やテクニックが載っており、めちゃくちゃ勉強させていただきました。

多数のサンプルもGitHubに上がっております!

Shaders Laboratory

スクリーンショット 2019-03-02 16.59.29.png

海外のサイトです。Shaderのサンプルが大量に載っています。

タダなのが信じられません。

ぜひチェックしてみてください!

Unity 2018 Shaders and Effects Cookbook

スクリーンショット 2019-03-02 16.58.34.png

こちらは海外製のShaderに関する本。Shaderのサンプルが70こ載ってます。

英語で書かれていますが、なんとなく理解できるレベルです笑

レベルも適切(難しすぎず、優しすぎず)なので、こちらもよかったら、参考にしてみてください!

紹介したリンク集まとめ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UnityCameraにAddComponentするだけで3DViwerを作る

Unityに使い慣れる為に、3DViwerを作った時に、一つのファイルにまとまって、CameraにAddComponentするだけで出来た為、そのメモ。
3Dゲームをやっていると、図鑑とかキャラの詳細で、キャラをぐりぐり360°見れるようにするのは、良くある話だと思います。
方法も既に、確立していて割と誰が作成してもほとんど同じ方法で実現されると思っていますが、どうしても簡単な数学が必要で、そこを理解していないとなかなか実現が難しいという話です。

方法

以下の式がカメラの移動を表現しており、半径(r)が拡大・縮小の役割を行い、sin/cosの計算が回転の役割を行い、aでカメラと視点を移動させる事で、平行移動を行います。

  • x = r * sin θ * cos φ + a
  • y = r * sin θ * sin φ + a
  • z = r * cos θ + a

拡大

マウスホイールの変化量を、rに増減させます。
スマホアプリだと、ピンチイン/アウトになる為、その変化量を増減させる事になります。
また、サンプルコードだと、最小値を入れていない為、視点に減り込みますので、対応する必要があるかと思います。

回転

極座標系の球面座標の考え方を用いる。式をそのまま使えます。
縦の移動量をθの角度の変化量に適用し、横の移動量をφの変化量に適用します。
スマホアプリだと、指一本のフリックやスワイプ操作で行うのが一般的でしょう。
9dTFqAzn.png

平行移動

特定の操作(サンプルコードの場合だと、右ボタン操作)で、縦横の変化量をaへ増減させます。コメントも入れていますが、transform.righttransform.upは単位ベクトルが入っている為、移動方向に使用しています。
スマホアプリだと、指二本のスワイプ操作が一般的なのでしょうか。

コード

実際に書いてみたコードです。検証用に書いた為、品質は保証ありません。
Inputで入力を取っている為、マウスだけで簡単に試す事ができます。

using UnityEngine;
using System.Collections;

namespace App
{
    public class PolarCoordinatesCameraController : MonoBehaviour
    {
        enum MouseDirection
        {
            None,
            Front,
            Back,
        }

         enum MouseClickType
        {
            None,
            Left,
            Right,
        }

        [SerializeField] float wheelLength = 2f;
        [SerializeField] float wheelSpeed = 0.1f;
        [SerializeField] float mouseLeftSpeed = 0.1f;
        [SerializeField] float mouseRightSpeed = 0.001f;

        Vector3 cameraLookAt = new Vector3(0f, 0f, 0f);
        Vector3 cameraPostion = new Vector3(0f, 0f, 0f);
        Vector2 mouseTouchStartPos;
        MouseClickType mouseClickType = MouseClickType.None;
        bool isMouseClick = false;
        // Fixed:初期Ⅰ。調整してこの角度
        float pie = -118f;
        float fhi = 310f;
        float radius = 3f;


        void Update ()
        {
            var wheel =  Input.GetAxis("Mouse ScrollWheel");

            if (wheel == 0f)
            {
                var moveX = 0f;
                var moveY = 0f;
                var moveZ = 0f;
                if (Input.GetMouseButtonDown(0))
                {
                    mouseTouchStartPos = Input.mousePosition;
                    mouseClickType = MouseClickType.Left;
                    isMouseClick = true;
                }
                else if (Input.GetMouseButtonDown(1))
                {
                    mouseTouchStartPos = Input.mousePosition;
                    mouseClickType = MouseClickType.Right;
                    isMouseClick = true;
                }
                else if (Input.GetMouseButton(0))
                {
                    moveX = (Input.mousePosition.x - mouseTouchStartPos.x) * mouseLeftSpeed;
                    moveY = (Input.mousePosition.y - mouseTouchStartPos.y) * mouseLeftSpeed;
                    mouseTouchStartPos = Input.mousePosition;
                }
                else if (Input.GetMouseButton(1))
                {
                    var moveVectorX = Input.mousePosition.x - mouseTouchStartPos.x;
                    var moveVectorY = Input.mousePosition.y - mouseTouchStartPos.y;
                    // memo : transform.right / transform.up は正規化済
                    var moveRight = transform.right * moveVectorX * mouseRightSpeed;
                    var moveUp = transform.up * moveVectorY * mouseRightSpeed;

                    moveX = moveRight.x + moveUp.x;
                    moveY = moveRight.y + moveUp.y;
                    moveZ = moveRight.z + moveUp.z;
                    mouseTouchStartPos = Input.mousePosition;
                }
                else if (Input.GetMouseButtonUp(0) || Input.GetMouseButtonUp(1))
                {
                    mouseTouchStartPos = Vector2.zero;
                }

                if (isMouseClick && mouseClickType == MouseClickType.Left)
                {
                    pie -= moveY;
                    fhi -= moveX;
                }
                else if (isMouseClick && mouseClickType == MouseClickType.Right)
                {
                    cameraLookAt.x -= moveX;
                    cameraLookAt.y -= moveY;
                    cameraLookAt.z -= moveZ;
                    cameraPostion.x -= moveX;
                    cameraPostion.y -= moveY;
                    cameraPostion.z -= moveZ;
                }
            }
            else
            {
                var direction = MouseDirection.None;
                if (Input.GetAxis("Mouse ScrollWheel") < 0)
                {
                    if (wheelLength < radius)
                    {
                        direction = MouseDirection.Front;
                    }
                }
                else
                {
                    direction = MouseDirection.Back;
                }

                switch(direction)
                {
                    case MouseDirection.Front:
                        radius -= wheelSpeed;
                        break;
                    case MouseDirection.Back:
                        radius += wheelSpeed;
                        break;
                }
            }

            var angelPie = pie * 0.01f;
            var angelFhi = fhi * 0.01f;

            var pos = new Vector3(
                radius * Mathf.Sin(angelPie) * Mathf.Sin(angelFhi) + cameraPostion.x,
                radius * Mathf.Cos(angelPie) + cameraPostion.y,
                radius * Mathf.Sin(angelPie) * Mathf.Cos(angelFhi) + cameraPostion.z
            );   

            transform.position = pos;
            transform.LookAt(cameraLookAt);
        }
    }
}

Inspectorの画像から、CameraにこのComponentの記事を追加しているだけという事が分かると思います。
Qita記事1.png.jpg

最後に

3DViewerも2DViewerも作ったのですが、基本用いる式は同じですが、インターフェース的に、全く同じやり方は出来ない為、少し実現方法を変える必要があります。例えば、回転をカメラに適用してしまうと背景もクルクル回る為、操作している人の気分を害してしまいそうだとか。
時間が取れたら、2DViewer記事も上げていきたいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者】Unityで2D横スクロールの地面地形作成(タイルパレット)

Unityを触り始めて3日目。
今日は横スクロール用の地形タイル作成を覚えました。

地面の地形作成

1.gif
練習用のUnity2Dゲームです。
マリオライクなゲームを作るにあたり、
上画像のような地面の地形データをタイルパレットで作成しました。

地面の作り方?

ネットで見たところ地面の作り方は
①スプライト作成
②スプライトにボックスコライダーを設定
③プレハブ化するなどして、手作業で敷き詰める?
って感じに見えたので、これは面倒だなーと思いました。

タイルマップとは

地面などの画像データを用意してパレットに置いといて、
後はパレットの画像を選択してからゲーム画面に簡単に放り込めるスタイル。
シムシティで建物を置くようにゲーム画面に画像を配置できます。
当たり判定なども簡単に設定できました。

実際に作ってみた

SnapCrab_NoName_2019-3-1_23-54-50_No-00.png
まずは上画像のようにタイルパレットを表示させる。

SnapCrab_NoName_2019-3-1_23-57-31_No-00.png
新しいパレットを作る

SnapCrab_NoName_2019-3-1_23-57-48_No-00.png
名前は分かりやすく付ける。何でも良い!
これでパレットが出来上がるので、好きな画像をドラッグアンドドロップするとタイルに登録できます。

SnapCrab_NoName_2019-3-2_0-2-20_No-00.png
試しに何個か登録しました。

SnapCrab_NoName_2019-3-2_0-3-36_No-00.png
お次はパレットの素材を実際に乗せるタイルマップを作成

SnapCrab_NoName_2019-3-2_0-5-21_No-00.png
画面にこんな感じに枠線が引かれました。
このブロックにタイルパレットの素材をワンクリックで乗せることが可能になりました。

2.gif
実際にパレットをタイルに乗せる様子。
これで地形データが簡単に載せられました。

注意事項

  • このままでは地形に当たり判定が無いので、2Dタイルマップコライダーを設定すること。 逆に当たり判定が必要ないものはそのままで良い。(背景の草とか雲とか)
  • タイルマップに画像を乗せるときに枠線一杯に表示させたいときは、元画像のインスペクターの「1ユニットのピクセル数」を元画像の横(もしくは縦)のピクセル数と同じにしよう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む