チャックブログ

UnityやC#などをメインに公開していきます。C++も勉強始めました!

【Unity】RenderTextuerからTextuer2DへしてからSpriteに変換

*前回記事にしたRenderTextuerからTextuer2Dの応用です。

tilyakuda.hateblo.jp

*前回公開したScript

     //このScriptはMainCameraにアタッチしてください

    public RenderTexture renderTexture;             //mainCameraにつけるRendertexture(アタッチしてね)
    public Texture2D kakunin;                       //ほんとに保存されているかの確認用
    Camera mainCamera;
    void Start ()
    {
        mainCamera = GetComponent<Camera>();
        kakunin = CreateTexture2D(renderTexture);
    }
    
    /// <summary>
    /// ここでTextur2Dに変換しているよ
    /// </summary>
    /// <param name="rt"></param>
    /// <returns></returns>
    Texture2D CreateTexture2D(RenderTexture rt)
    {
        //Texture2Dを作成
        Texture2D texture2D = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false, false);

        //subCameraにRenderTextureを入れる
        mainCamera.targetTexture = rt;

        //手動でカメラをレンダリングします
        mainCamera.Render();


        RenderTexture.active = rt;
        texture2D.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
        texture2D.Apply();

        //元に戻す別のカメラを用意してそれをRenderTexter用にすれば下のコードはいらないです。
        mainCamera.targetTexture = null;
        RenderTexture.active = null;

        return texture2D;
    }

これにこちらの関数を追加します。

  Sprite CreateSprite(Texture2D tex2D)
    {   
        Sprite sprite = Sprite.Create(tex2D,new Rect(0f,0f,tex2D.width,tex2D.height),new Vector2(0.5f,0.5f),100f);
        return sprite;
    }

*完成

    //このScriptはMainCameraにアタッチしてください

    public RenderTexture renderTexture;             //mainCameraにつけるRendertexture(アタッチしてね)
    public Texture2D kakunin;                       //ほんとに保存されているかの確認用
    public Sprite spriteTest;                       //Sprite確認用
    Camera mainCamera;

    

    void Start()
    {
        mainCamera = GetComponent<Camera>();
        kakunin = CreateTexture2D(renderTexture);
        spriteTest = CreateSprite(kakunin);
    }

    /// <summary>
    /// ここでTextur2Dに変換しているよ
    /// </summary>
    /// <param name="rt"></param>
    /// <returns></returns>
    Texture2D CreateTexture2D(RenderTexture rt)
    {
        //Texture2Dを作成
        Texture2D texture2D = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false, false);

        //subCameraにRenderTextureを入れる
        mainCamera.targetTexture = rt;

        //手動でカメラをレンダリングします
        mainCamera.Render();


        RenderTexture.active = rt;
        texture2D.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
        texture2D.Apply();

        //元に戻す別のカメラを用意してそれをRenderTexter用にすれば下のコードはいらないです。
        mainCamera.targetTexture = null;
        RenderTexture.active = null;

        return texture2D;
    }

    Sprite CreateSprite(Texture2D tex2D)
    {   
        Sprite sprite = Sprite.Create(tex2D,new Rect(0f,0f,tex2D.width,tex2D.height),new Vector2(0.5f,0.5f),100f);
        return sprite;
    }
}

【Unity】RendererTextureからTexture2Dの作り方

今回やること

Cameraで描画されているものをTexture2Dに変換させる。

用意するもの

  • RendererTexture (ProjectWindowで右クリック > Create > RendererTextureで作成可能)
  • Camera

Script

     //このScriptはMainCameraにアタッチしてください

    public RenderTexture renderTexture;             //mainCameraにつけるRendertexture(アタッチしてね)
    public Texture2D kakunin;                       //ほんとに保存されているかの確認用
    Camera mainCamera;
    void Start ()
    {
        mainCamera = GetComponent<Camera>();
        kakunin = CreateTexture2D(renderTexture);
    }
    
    /// <summary>
    /// ここでTextur2Dに変換しているよ
    /// </summary>
    /// <param name="rt"></param>
    /// <returns></returns>
    Texture2D CreateTexture2D(RenderTexture rt)
    {
        //Texture2Dを作成
        Texture2D texture2D = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false, false);

        //subCameraにRenderTextureを入れる
        mainCamera.targetTexture = rt;

        //手動でカメラをレンダリングします
        mainCamera.Render();


        RenderTexture.active = rt;
        texture2D.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
        texture2D.Apply();

        //元に戻す別のカメラを用意してそれをRenderTexter用にすれば下のコードはいらないです。
        mainCamera.targetTexture = null;
        RenderTexture.active = null;

        return texture2D;
    }

上のScriptをMainCameraにアタッチしてください。 作ったRendererTextureをアタッチし忘れに注意。 f:id:tilyakuda:20190419194255p:plain

注意!

この処理はそこそこ重いので毎フレームやることは推奨しません。 やるのであれば数フレームに一回や何かのボタンを押したら1度だけ動くようにするのがいいと思います。

おわり

何か質問などがある方はコメントください。

【Unity】何かを動かす時に必ずやるべきこと

今回やること

Unity上でオブジェクトを動かしたりする時にやっておくべきことをご紹介します。

例えば

1秒間にX座標60移動させるとします。

{
    transform.position=new Vector3(0,0,0);
    void Update()
    {
        transform.position += new Vector3(1,0,0);
    }
}

これを60fpsの状態で起動すると毎秒60移動していることになります、ですがこれが30fpsになると毎秒30しか進まなくてなってしまいます。 なら60fpsでいいじゃんって話なのですが必ず60fps出る保証もありません。ではどんなfpsでも毎秒進む距離が変化しない状態にするにはどうすればいいのかというと。

Time.deltaTimeを使う

このTime.deltaTimeってなにかというと「1 / 現在出ているfps」が戻り値として取得できます。 つまり60fps時なら「約0.0166」30fpsなら「約0.0333」を返してくれます。 それを元にコードを書くと。

{
    transform.position=new Vector3(0,0,0);
    void Update()
    {
        transform.position += new Vector3(60*Time.deltaTime,0,0);
    }
}

これでどんなfpsが出ていても1秒後には限りなく60に近い数値になります。 fpsの数値によって動く速さが変わるのはあまりよろしくないと思うのでこのようにどんなfpsになっても1秒間に動く距離が変わらないようにしてあげると良いと思います。

【Unity】簡単なセーブとロードの方法{ランキング編}

今回やること

前回やったUnityで簡単なセーブとロードの方法でやったPlayerPrefsを用いて簡易的なランキングを実装しようと思います。

仕様

  • 一度ゲームを閉じてもデータが保持される
  • 高い点数を取得したらランキングを更新する

これらを実装して組んでいこうと思います。

コード

using UnityEngine;
using UnityEngine.UI;

public class Ranking : MonoBehaviour {

    [SerializeField,Header("数値")]
    int point;

    string[] ranking = { "ランキング1位", "ランキング2位", "ランキング3位", "ランキング4位", "ランキング5位" };
    int[] rankingValue = new int[5];

    [SerializeField, Header("表示させるテキスト")]
    Text[] rankingText=new Text[5];

    // Use this for initialization
    void Start ()
    {
        GetRanking();

        SetRanking(point);

        for (int i = 0; i < rankingText.Length; i++)
        {
            rankingText[i].text = rankingValue[i].ToString();
        }
    }

    /// <summary>
    /// ランキング呼び出し
    /// </summary>
    void GetRanking()
    {
        //ランキング呼び出し
        for (int i = 0; i < ranking.Length; i++)
        {
            rankingValue[i]=PlayerPrefs.GetInt(ranking[i]);
        }
    }
    /// <summary>
    /// ランキング書き込み
    /// </summary>
    void SetRanking(int _value)
    {
        //書き込み用
        for (int i = 0; i < ranking.Length; i++)
        {
                //取得した値とRankingの値を比較して入れ替え
                if (_value>rankingValue[i])
                {
                    var change = rankingValue[i];
                    rankingValue[i] = _value;
                    _value = change;
                }
        }

        //入れ替えた値を保存
        for (int i = 0; i < ranking.Length; i++)
        {
            PlayerPrefs.SetInt(ranking[i],rankingValue[i]);
        }
    }
}

これで数値の高い順に並び変えられると思います。

Unityで簡単なセーブとロードの方法

セーブ方法

Unityでセーブorロードを実現するのであれば一番楽なものはPlayerPrefsが最も楽だと思います。 Unity PlayerPrefsのリファレンス

        PlayerPrefs.SetInt("HP" , 10);
        PlayerPrefs.SetFloat("MP" , 10.0f);
        PlayerPrefs.SetString("名前","Unityちゃん");

PlayerPrefsでセーブをするにはこのように記述します。

|Setする型|セーブデータの名前|値| |:---:|:---:|:---:| |Int|HP|10| |Float|MP|10.0f| |String|名前|Unityちゃん| int型のHPという名前の箱に10という値を保存 float型のMPという名前の箱に10.0fという値を保存 string型の名前という名前の箱にUnityちゃんという値を保存

注意

SetInt SetFloat SetStringは加える[+=]のではなく上書き[=]で保存されるので場合によっては

//HP保存されていた値に+10して保存
PlayerPrefs.SetInt("HP",PlayerPrefs.GetInt("HP")+10);

このように記述しなければいけなくなります。 (他にも色々と方法はありますが今はこれで…)

ロード方法

先ほど保存したHP MP 名前を呼び出したいと思います。

        PlayerPrefs.GetInt("HP");
        PlayerPrefs.GetFloat("MP");
        PlayerPrefs.GetString("名前");

これで先ほど保存したHP(10) MP(10.0f) 名前(Unityちゃん)を取得することができます。

Getする型 セーブデータの名前 保存されていた値
Int HP 10
Float MP 10.0f
String 名前 Unityちゃん

PlayerPrefsで呼び出せるもの

自己解釈した内容で書きます。 ちゃんとした内容が見たい人はこちらから(Unity PlayerPrefsのリファレンス)

PlayerPrefs. 内容
SetInt 設定した名前に対する値を保存します
SetFloat 設定した名前に対する値を保存します
SetString 設定した名前に対する値を保存します
GetInt 設定した名前が存在すれば値を取得します
GetFloat 設定した名前が存在すれば値を取得します
GetString 設定した名前が存在すれば値を取得します
DeleteKey 設定した名前が存在すればそのデータを削除します
DeleteAll すべてのセーブデータを削除
HasKey 設定した名前のデータがあるか確認します
Save 使ったことないのでわからないです…