おもちゃラボ

Unityで遊びを作っていきます

【Unity】ボタンを押したときに画面クリックは無視する

GetMouseButtonDownメソッドを使ってマウスの入力を取得していると、uGUIのボタンを押したときにも画面クリックを検出してしまいます。

f:id:nn_hokuson:20170712215201g:plain:w450

ボタンがタッチされたときは、画面のタッチは無視する

これでも良い場合もありますが、普通は画面のクリックとボタンのクリックは分離したいですよね〜。
そんなときはEventSystemのIsPointerOverGameObjectメソッドを使います。このメソッドは、ボタンがクリックされたときにだけ反応するので、簡単に画面クリックを無視することが出来ます。

スクリプトは次のようになります。

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

public class TouchController : MonoBehaviour 
{
    void Update () {
        if(EventSystem.current.IsPointerOverGameObject()){
            return;
        }

        if (Input.GetMouseButtonDown (0)){
            
        }
    }
}

GetMouseButtonDownで画面タッチされたことを検知する前に、ボタンのクリックをチェックして、ボタンがクリックされているときにはreturnしています。

Unityエディタで実行すると、ちゃんと動作していることが確認できます。

f:id:nn_hokuson:20170712215427g:plain:w450

この方法はテラシュールブログさんでも紹介されていたのですが、スマートフォンで実行するとなぜか画面のクリックまで検出・・・

tsubakit1.hateblo.jp

スマートフォン対応する

そこで、EventSystemを使ってボタンクリックを検出する部分を次のように修正しました。

#if UNITY_EDITOR
    if(EventSystem.current.IsPointerOverGameObject()){
        return;
    }
#else 
    if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)) {
        return;
    }
#endif

エディタで実行しているか、スマートフォンで実行しているかはマクロで分けています。スマートフォンの場合はIsPointerOverGameObjectメソッドの引数にフィンガーIDを渡している部分だけが異なります。

これを実行してみるとうまくいきましたー!

【Unity】Unityちゃんの注視方向をIKで変化させる

Unityではオブジェクト向きを変えるにはTransform.LookAtメソッドを使います。この場合、体ごとグルっと回ってしまって不自然なことがあります。

ここではIKを使ってUnityちゃんの注視点方向を変える方法を紹介します。

f:id:nn_hokuson:20170711205128j:plain

Unityちゃんを配置しする

Unityちゃんのモデルをシーンビューに配置しましょう。WAITアニメを表示するため、UnityChan/Animationフォルダにある「UnityChanLocomotions」をUnityちゃんにドラッグ&ドロップします。

f:id:nn_hokuson:20170711202548j:plain

これで、自動的にUnityちゃんにAnimatorコンポーネントがアタッチされます。実行するとWAITアニメーションが実行されます。

f:id:nn_hokuson:20170711202751j:plain:w450

UnityちゃんをIK対応にする

UnityちゃんをIKにしたがって動かすためには、Animator ControllerでUnityちゃんをIKで動くように設定する必要があります。

UnityChanLocomotionsを開いて、画面左のBaseLayerの横の歯車ボタンを押してください。出てくるメニューの一番下にある「IK Pass」にチェックを入れます

f:id:nn_hokuson:20170711203140j:plain

これで、MechanimでIKが使えるようになりました。

マウスの移動をUnityちゃんが追うようにする

最後に、Unityちゃんの視線がマウスを追うように、スクリプトを作成します。プロジェクトビューで右クリックし、Create→Script→C# Scriptを選択して「LookAtController.cs」という名前で保存しましょう。

保存できたら次のスクリプトを入力してください。

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

public class LookAtController : MonoBehaviour {

    Animator animator;
    Vector3 targetPos;

    void Start () {
        this.animator = GetComponent<Animator> ();    
        this.targetPos = Camera.main.transform.position;
    }
    
    void Update () {
        if (Input.GetMouseButton (0))
        {
            Vector3 touchPos = Camera.main.ScreenPointToRay (Input.mousePosition).origin;
            touchPos.z = -0.5f;
            targetPos = touchPos;
        }
    }

    private void OnAnimatorIK(int layerIndex)
    {
        this.animator.SetLookAtWeight(1.0f, 0.8f, 1.0f, 0.0f, 0f);
        this.animator.SetLookAtPosition(this.targetPos);
    }
}

ここではSetLookAtWeightメソッドと、SetLookAtPositionメソッドを使ってUnityちゃんの体をIKで動かしています。

SetLookAtWeightは体や頭、目の追従具合(重み)を調整するためのメソッドです。SetLookAtWeightの引数は次のようになります。

変数 意味
weight 全体の重み
bodyWeight 体を動かす重み
headWeight 頭を動かす重み
eyesWeight 目を動かす重み
clampWeight モーションの制限量

ここでは、第2引数でマウスの動きに対して体がどれだけ追従するかを指定しています。また、第3引数ではマウスの動きに頭がどれだけ追従するかを指定しています。

続けて、ユニティちゃんの注視方向をSetLookAtPositionで指定しています。ここではマウスでクリックしている座標を指定しています。

入力できたら、スクリプトをUnityちゃんにドラッグ&ドロップしてアタッチしましょう。

f:id:nn_hokuson:20170711203731j:plain

実行するとマウスのカーソルをUnityちゃんが追うように体と首を回転させます。

f:id:nn_hokuson:20170711205001g:plain

【Unityシェーダ入門】スパイクノイズを作る

スパイクノイズは、ブランドロゴのイントロとかでよく使われる感じのエフェクトです。といっても伝わりにくいので↓のような感じのものを作ります。

f:id:nn_hokuson:20170609224404g:plain

スパイクノイズという言葉はもともとは電子回路の言葉で、スイッチをオン・オフしたときに生じるパルスノイズです。チャタリングのようなものですね〜。余談でした(笑)

www.marutsu.co.jp

スパイクノイズのエフェクトを作る

画像を横方向に歪めるエフェクトは非常に簡単で、参照するテクスチャのX座標値をY軸の値をもとにずらすだけです。ずらす量は基本的にはsin関数で良いと思います。

f:id:nn_hokuson:20170609222354j:plain:w450

今回は場所によってもう少しランダムなノイズにしたかったので、sin(10*x)*(-(x-1)^2+1)という関数の0〜3の範囲を使います。
この関数はsin関数と二次曲線の値を掛けただけのものですが、これにより山形のノイズが生成できます。

f:id:nn_hokuson:20170609221144p:plain:w400

MacではGrapherというアプリ(デフォルトで入っている)を使うと、簡単にグラフが書けるので、「こういう波形が作りたい」というときに重宝しています。

パルスノイズのシェーダを作る

まずはシェーダファイルとマテリアルを作ります。プロジェクトビューで右クリックし、「Create/Shader/Unlit Shader」を選択してください。「PulseNoise.shader」という名前で保存します。このシェーダを設定した「PulseNoiseマテリアル」も作成します。

f:id:nn_hokuson:20170609222617p:plain:w150

PulseNoise.shaderに次のプログラムを入力してください。

Shader "UI/PulseNoise"
{
    Properties
    {
        _MainTex ("Sprite Texture", 2D) = "white" {}
        _Amount ("Distort", Float) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag  
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float  _Amount;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                float2 uv = i.uv;
                float x = 2*uv.y;
                uv.x += _Amount*sin(10*x)*(-(x-1)*(x-1)+1);
                fixed4 col = tex2D(_MainTex, uv);
                return col;
            }
            ENDCG
        }
    }
}

フラグメントシェーダで、テクスチャを横方向にずらす処理をしています。テクスチャのy座標の値をもとにx方向にずらす量を計算しています。計算式は上で書いたとおりです。

また、ノイズの強さ自体をインスペクタから操作するため、propertiesブロックに_Amount変数を用意しています。この値を上で計算した値に掛けることで、ノイズ全体の大きさを制御します。

シェーダが書けたら、ノイズをかけたいuGUIのImageのインスペクタのMaterial欄に作成したPulseNoiseマテリアルをドラッグ&ドロップしてください。

f:id:nn_hokuson:20170609222945p:plain:w400

PulseNoiseマテリアルのインスペクタからAmount値を操作するとノイズがかかることが確認できます。

f:id:nn_hokuson:20170609223344g:plain

パルスノイズを発生させるスクリプト

いちいち手作業でノイズを発生させるわけにもいかないので、スクリプトからノイズを発生させましょう。

ノイズを一瞬だけ発生させるため、C#スクリプトから_Amount変数の値を操作します。NoiseControllerを作って次のプログラムを入力してください。

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

public class NoiseController : MonoBehaviour {

    IEnumerator GeneratePulseNoise()
    {
        for (int i = 0; i <= 180; i += 30)
        {
            GetComponent<Image> ().material.SetFloat ("_Amount", 0.2f * Mathf.Sin (i * Mathf.Deg2Rad));
            yield return null;
        }
    }

    void Update () {
        if (Input.GetMouseButtonDown (0))
        {    
            StartCoroutine (GeneratePulseNoise ());
        }
    }
}

ここではノイズの大きさをsin波で変化させているだけです。もちろん、Animatorから_Amountの値を操作してもOKです。最終的な実行結果は次のようになります。

f:id:nn_hokuson:20170609224404g:plain