2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Unity(C#)】SteamVR Pluginを使わないVRでのフェードアウト、フェードイン

Last updated at Posted at 2019-02-15

  
  
  
この記事は

『プログラミング完全未経験からUnityでの開発現場に迎え入れてもらえた世界一の幸せ者』

の記事です。そのつもりでお読みください。
  

##SteamVR Pluginを使う
[SteamVR Pluginを使うフェード]←こちらです。

##SteamVR Pluginを使わない
前回の記事を活かして作りました。→3Dでのフェード

他にもやり方はありますが、今回はVRのカメラとは別にサブカメラを用意する方法を書きます。

サブカメラにキャンバス(UI)のみ映る設定をします。
Culling MaskUI以外のチェックをはずせばOKです。
Culling Maskは描画するオブジェクトをレイヤーごとに設定できる便利なプロパティーです。

つぎに、
・サブカメラの描画順を最後(一番目に近い位置)にする
・背景が二つのカメラで描画される(片方のカメラに映る背景が片方のカメラの映像を塗りつぶす)ことを防ぐ
上記2点を設定します。
カメラの最強の絵.png
このとても上手な絵を見れば一目瞭然だと思いますが、
メインカメラ、サブカメラで描画する順番があります。

私は最初聞いたとき描画とか言われてもイメージしづらいと感じました。
なので、絵のように物理的に距離があるものだと考えるようにしました。
目に近い位置のもの(描画順が遅いもの)が一番手前に描画される、といった理解の仕方です。

※以後、描画順の違いに物理的な距離の違いがあるような説明をしますが
 そんなものはありませんのでご注意ください。ただのイメージです

しかし、カメラの場合、目に近いほう(サブカメラ)にもメインカメラと同じ背景が映りこみます。
(Culling Maskで背景の描画は消せません)

それにより、サブカメラに映った背景が、メインカメラより目に近い位置で描画されるので
メインカメラの映像を上から塗りつぶしてしまいます。
(ここの説明はややこしいので声に出して5回くらい読んでください)

この塗りつぶしを防ぐために
Clear FlagsDepth onlyにします。
背景が上書きされることがなくなります。

ただし、Depthというパラメーターの確認をしてください。
数字の小さい順番で先に描画される(目から遠くなる)ので今回の場合は
メインカメラの方がサブカメラよりDepthが小さくないといけません。
(おそらく勝手にそうなってます)

###最終的な設定画面
CameraVRSetting.png
長々と説明しましたが、設定項目としてはこれだけです。

##コード

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

public class UtilityFadeCanvas : MonoBehavior
{
    Canvas faceCanvas;

    Image facePanel;

    Camera faceCamera;

    Coroutine coroutine;

    GameObject camera_G;

    [Tooltip("フェードする色")]
    public Color panelColor = new Color(0, 0, 0, 0);

    [Tooltip("フェードの時間")]
    public float fadeTime = 1;

    [Tooltip("0~1の値で透明度を設定")]
    public float alpha_Panel = 0.5f;

    const float FIXED_UPDATE_DELTATIME = 0.02f;

    float startTime;

    void Awake()
    {
        //シーンをロードするたびに新しいカメラを生成
        if (GameObject.Find("OnlyUIRenderingCamera"))
        {
            Destroy(GameObject.Find("OnlyUIRenderingCamera"));
        }
    }

    // Start is called before the first frame update
    void Start()
    {

        //カメラ自動生成
        camera_G = new GameObject("OnlyUIRenderingCamera");
        faceCamera = camera_G.AddComponent<Camera>();
        faceCamera.clearFlags = CameraClearFlags.Depth;
        faceCamera.cullingMask = (1 << LayerMask.NameToLayer("UI"));

        //キャンバス生成&設定
        GameObject canvas_G = new GameObject("FaceCanvas");
        faceCanvas = canvas_G.AddComponent<Canvas>();
        canvas_G.AddComponent<CanvasRenderer>();


        //キャンバスのポジションを調整
        Vector3 canvasPosition = canvas_G.transform.position;
        canvasPosition.x = 0;
        canvasPosition.y = 0;
        canvasPosition.z = 0.1f;
        canvas_G.transform.localPosition = canvasPosition;

        //レンダリングをfaceCameraに
        faceCanvas.renderMode = RenderMode.ScreenSpaceCamera;
        faceCanvas.worldCamera = faceCamera;

        //パネル生成&設定
        GameObject panel_G = new GameObject("FacePanel");
        facePanel = panel_G.AddComponent<Image>();

        Color tmpColor = facePanel.color;
        tmpColor.a = 0f;
        facePanel.color = tmpColor;

        //パネルをキャンバスの子に設定
        panel_G.transform.parent = canvas_G.transform;

        //パネルのポジションを正面に調整
        Vector3 panelPosition = panel_G.transform.localPosition;
        panelPosition.x = 0;
        panelPosition.y = 0;
        panelPosition.z = 0;
        panel_G.transform.localPosition = panelPosition;


        //キャンバスをカメラの子に設定
        canvas_G.transform.parent = faceCamera.transform;

        //Layerを変更
        canvas_G.layer = LayerMask.NameToLayer("UI");
        panel_G.layer = LayerMask.NameToLayer("UI");

    }

    void Update()
    {
        //Fixed Timestepを固定
        Time.fixedDeltaTime = FIXED_UPDATE_DELTATIME;

    }

    void FixedUpdate()
    {
        //キー押してない間はreturn
        if (Input.anyKey == false)
        {
            return;
        }

        if (coroutine == null)
        {
            //テスト用 フェードアウト
            if (Input.GetKeyDown(KeyCode.O) && panelColor.a == 0)
            {
                FadeOut();
            }

            if (Input.GetKeyDown(KeyCode.I) && panelColor.a == alpha_Panel)
            {
                FadeIn();
            }
        }
    }


    public  void FadeOut()
    {
        if (panelColor.a == 0)
        {
            //スタートの時間記録
            startTime = Time.time;
            print("フェードアウト開始");

            coroutine = StartCoroutine(FadeOutCoroutine());
        }
    }


    public  void FadeIn()
    {
        if (panelColor.a == alpha_Panel)
        {
            //スタートの時間記録
            startTime = Time.time;
            print("フェードイン停止");

            coroutine = StartCoroutine(FadeInCoroutine());
        }
    }

    IEnumerator FadeOutCoroutine()
    {
        int count = 0;

        yield return new WaitForFixedUpdate();
        while (facePanel.color.a < alpha_Panel - 0.00005f)
        {
            yield return new WaitForFixedUpdate();
            panelColor.a += alpha_Panel / (fadeTime * 50);
            facePanel.color = panelColor;

            count++;

            //フェード中の時間、Alphaを確認
            print(Time.time - startTime);
            print("アルファの値:" + panelColor.a + ":" + count + "回目");

        }
        print("フェードアウト停止");
        panelColor.a = alpha_Panel;

        StopCoroutine(coroutine);
        coroutine = null;
    }


    IEnumerator FadeInCoroutine()
    {
        int count = 0;

        yield return new WaitForFixedUpdate();
        while (panelColor.a > 0 + 0.00005f)
        {
            yield return new WaitForFixedUpdate();
            panelColor.a -= alpha_Panel / (fadeTime * 50);
            facePanel.color = panelColor;

            count++;

            //フェード中の時間、Alphaを確認
            print(Time.time - startTime);
            print("アルファの値:" + panelColor.a + ":" + count + "回目");

        }
        print("フェードイン停止");
        panelColor.a = 0;

        StopCoroutine(coroutine);
        coroutine = null;
    }
}

コードの解説も書きたいことが多くて長くなりそうなので
明日続き書きます。
続き→こちらです

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?