はらけんログ

unity触ったりバイクに乗ったり

【Unity】StartとかUpdateについて

unityに慣れてしまっていたので記憶から消えていた疑問なんですが

「UnityってなんでStart()とかUpdate()とかだけ勝手に実行されんの?」

「UnityのStratとかUpdateって、どのスクリプトのUpdate(Start)がどの順番で実行されてんの?」

うーん...わからん

Unityが作りやすいように魔法の呪文を用意してくれていて、実行順が重要な作り方でない限り、毎フレーム必要な処理はUpdateに、起動時に必要な処理はStartに書いておけばおk!

と、いう感じで使っている人多いですよね。でも、モヤモヤが無くならない人も多いハズ。

ってことで、調べたらモヤモヤの正体がわかるとてもわかり易い記事がありました。

blogs.unity3d.com

unity-michi.com

 

要は「MonoBehaviourが設定した魔法の呪文メソッドが、各魔法の呪文リストにランダムな順番でaddされて、決まった順番で魔法の呪文リストが実行される」からモヤモヤするみたいっすね。(日本語ムズイ

docs.unity3d.com

 

って、ことで上記記事からも分かる通り、むやみにスクリプトを増やしまくってUpadeなりを実行させるとかなり負荷がかかるみたい。

 

個人的には、毎フレーム実行したい関数はUpdateAction()みたいな名前にして、それらクラスを参照したSceneManagerクラスのUpdate()でUpdateAction()をすべて呼び出したら実行順も決めやすいし、わかりやすいし、良いような気がする。

 

public class SceneManager : MonoBehaviour {

 

     DataManager dataManager; 

     TimerManager timerManager;   

     DebugManager debugManager;

 

      void Awake()    { 

          dataManager.Awake_Action(); 

          timerManager.Awake_Action(); 

          debugManager.Awake_Action(); 

    } 

    void Start () {     

          dataManager.Start_Action();       

          timerManager.Start_Action();

          debugManager.Start_Action();

    }

    void Update () {

          dataManager.Update_Action();       

          timerManager.Update_Action();

          debugManager.Update_Action();

    }

}

 

 

 

 

【Unity】無名関数とかラムダ式とかいうやつ

C#でintとかstringみたいにSystem.Actionってのを引数にすれば関数を呼べるってことを最近知ったので使ってみてる。

例えば、下記の1と2は同じ処理だが1は引数の関数を実行するので、呼びたい関数を突っ込めばよい。

string log;

void Awake(){

    SendLog(SetLog); //1

    ActionLog();           //2

}

void SendLog(System.Action act){

    act();

    Debug.Log(log);

}

void SetLog(){

    log="Action!";

}

void ActionLog(){

    SetLog();

    Debug.Log(log);

}

 

ただ、困ったことにSetLogに引数がつけられない。

string log;

void Awake(){

    SendLog(SetLog("無理")); //エラー

}

void SendLog(System.Action act){

    act();

    Debug.Log(log);

}

void SetLog(string str){

    log=str;

}

 

で、無名関数とかラムダ式使うやつを使おうとおもった。

(引数)=>{処理}と書けば大丈夫らしい。

string log;

void Awake(){

    SendLog(()=>{log="ShimaRin"}); 

}

void SendLog(System.Action act){

    act();

    Debug.Log(log);

}

 

 書き方が独特なので覚えるのに時間かかったが、すごく便利なので多用していきたい。

が、これ処理のせいで動作が重くなったりしないかな。。。というとこだけ疑問。

 おかしなことしなければ大丈夫だとは思う。

 

 

【Unity】unityちゃんをつかってVtuberテスト!マジ卍!

過去記事にもあるけど、去年作りかけていたプロジェクトを掘り起こしたのでテストした。

 

haraken.hatenablog.com

 

去年の今頃はVtuberなんて言葉もなかったのに、気づけば600人以上のVtuberがいるとか。

あー俺が言いだしたことになんねーかn(例のコラ割愛

 忙しさにかまけてやりたいことやらなくなると時代において行かれるね。。。

 

ってことで下記に現状アップ

youtu.be

 

マジ卍!

次はモーフあたりをいじるかな

モデルもオリジナルにしたいからc4d頑張る

 

輝夜月としのめぐに会いに行くことを目標に暇を見つけてブラッシュアップするか!

 

【Unity】LightingやQualitySettingをいじっても影がちらつく

大きな街のモデルを配置してその中をプレイヤーが動く時、なぜだか影がちらつき出した。

解決方法を探していたらありました。

No hack, no work • サバティカるブログ 第13話「影がチラつく」

 

右の建物の影に注目

f:id:HarakeN:20180309171411g:plain

 

これが

こう

f:id:HarakeN:20180309171517g:plain

 

どうやらカメラの「Clipping Planes」のNearの数値を0.1以上にすれば直るっぽい。

近くを描画しない時は全体の処理が軽そうだからと言ってむやみにNearの値を小さくしないほうが良い。贅沢は敵。

 

奥の木がちらついてるのはTerrainの設定っぽい。直さないと。。。

【Unity】CSVの読み込みでハマるあれこれ

外部ファイルからアプリ内設定をしたり、データそのものを外部ファイルで扱いたいときって多々あるよね。

 

今回は外部ファイル(CSV)の読み込み方とか覚書しておく。

 

そもそもUnityで外部ファイルを扱う場合は「StreamingAssets」フォルダーを作成し、その中のファイルを独自に管理しなければならない。(とはいってもフォルダー名とか形式とかぐらいだが)

まぁこのあたりは他資料を参照してもらって、問題はExcelなどで管理したデータを使用する際に多用されるCSVファイルを読み込む方法について踏み込む。

 

・ざっくりと読み込み方

ExcelC#の大きな壁は文字コードだ。

Excelで書き出す際にShift-JISからUTF-8に変えないとC#では扱いづらい(個人的に)

Excelでは書き出すときに設定ができるので、そこはよしとして、次にC#UTF-8の文字列を読み込むには?って話をしよう。

 

これにはファイルを読み込むためのFileと文字コードを指定するEncodingクラスを使用する。FileはネームスペースにSystem.IOをEncodingはネームスペースにSystem.Textを追加しておく必要がある。

using  UnityEngine;

using System.Text;
using System.IO;

public class TestRead:Monobehaviour

{

    Encoding encoding;

    void  Start()

    {
  this.encoding = Encoding.GetEncoding("utf-8");

        string path =  Application.streamingAssetsPath + "test.csv";

        string csvText = File.ReadAllText(path, this.encoding);

        string dataStr = csvText .Split(","[0]);

    }

}

 

 

Start関数の1行目は文字コードの設定。

2行目は読み込むファイルのディレクトリを指定。

3行目ですべての文字列を読み込む。

4行目でCSVのカンマ区切りで文字をぶった切っている。

 

たったのこれだけ。

 

これで取得したデータを煮るなり焼くなりする。

 

 

 

 追記

セルの中に区切り文字(,)がある場合

ExcelからCSVに書き出す際に、セルの中身に「,」がある場合、「"any,text"」みたいな感じにダブルクォートでかこまれて書き出される。

このままでは、Splitで分割した際に「"any」と「text"」といった感じに分割されてしまう。  なので、一文字ずつ検索して見つけたら変換って感じにする。

(区切り文字を別にする、書き出し時にダブルクォートをつけなくする、とか言う注文ができない人用)

using  UnityEngine;

using System.Text;
using System.IO;

public class TestRead:Monobehaviour

{

    Encoding encoding;

    string dataString; 

    char targetChar = '"';
    char kanma = ',';

 

    void  Start()

    {
  this.encoding = Encoding.GetEncoding("utf-8");

        string path =  Application.streamingAssetsPath + "test.csv";

        string csvText = File.ReadAllText(path, this.encoding);

        

        StringBuilder sb = new StringBuilder(csvText .Length);
        int index = 0; //ダブルクォートをカウント
        bool addFlag; //ダブルクォートだったら加えない


        foreach (char c in csvText)
        {
            addFlag = true;
            char ch = c;
            if (c == targetChar) //ダブルクォートだったら
            {
                addFlag = false;
                index++;
            }
            if (c == kanma) //カンマだったら
            {
                 if (index % 2 != 0) //ダブルクオートの中にあるカンマ
                 {
                      ch = ',';  //別の文字に変換
                 }
            }

            if (addFlag)
            {
                sb.Append(ch);
            }
       }
       string replaceStr = sb.ToString();

 

       dataStrng = replaceStr .Split(","[0]);


       for(int i = 0; i < dataStr.Length; i++)
       {
            dataStr[i]= dataStr[i].Replace(',', ','); //別の文字に変換したカンマを元に
       } 

    }

}

 太文字の部分が重要。

ダブルクォートを文字列から外して、Splitで変換したくないカンマを「大文字のカンマ」に変えている。(大文字のカンマでなくてもなんでもいい)すべて変換し終わったらSplitで配列にして、このあとに配列に入っている文字列の大文字カンマを半角カンマに直している。

 

 

1行目と2行目の間にもカンマを入れたい

2行3行と行がかさむのは当たり前なんだけど、「行の最後のセル」と「次の行の最初のセル」の間には区切り文字が入らず改行コードが入る。

このままだとSplitした時に両方とも同じ文字列になってしまうので変換する。

using  UnityEngine;

using System.Text;
using System.IO;

public class TestRead:Monobehaviour

{

    Encoding encoding;

    void  Start()

    {
  this.encoding = Encoding.GetEncoding("utf-8");

        string path =  Application.streamingAssetsPath + "test.csv";

        string csvText = File.ReadAllText(path, this.encoding);

   csvText = csvText .Replace(System.Environment.NewLine, ",");

        string[] dataStr = csvText .Split(","[0]);

    }

}

 System.Environment.NewLineは改行コードの意。これを「,」に直している。

こうした後にSplitすれば行の変わり目も文字列をくぎることができる。