はらけんログ

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

【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すれば行の変わり目も文字列をくぎることができる。

 

(HoloLensでThetaの映像見たい続編).NetのwebrequestをUnityWebRequestで置換したいが

前の続き

noshipu.hateblo.jp

haraken.hatenablog.com

 

HoloLens用にビルドすると.Netのwebrequestの部分でエラー吐いてビルドできないやつをなんとか回避したいんだけど、UnityWebRequestで書き換えてやればいけるんじゃない?

と、思ってみたが、そもそも通信の実装はよくわからないので、お手上げ状態。

 

 

ちなみに、Player SettingでScriptBackendをIL2cppにしたら、そのままでもビルド自体はうまくいったが、Thetaとの通信はできなかった(ってかC++じゃ動かんよな)

 

 

んで、適当にブラウジングしてたら、こんなアプリがすでにあった模様。

www.microsoft.com

 

このアプリを使用したら普通にシータの画像をライブで見れた。

実装の仕方はわからないけど、そもそもUnityなんか使わないでVSで書けよって事。。。?

 

2Dアプリの方が、ライブカメラの使い方としてあってると思うけど、Thetaだったら3Dアプリでみたいよなぁ。。。

 

 

他に使えそうないいライブカメラがあればいいんだけど。

 

 

以上。

【Unity】Unity5.6のVideoPlayerとuGUI

はい。

Unity5.6もリリースされたことなので、久しぶりに記事書こうかな。

 

今回のアップデートで注目されてるのはVideoPlayer

今までUnityで動画を使おうとするとAssetのAV Proを購入せざるをえなかったが、今回導入されたVideoPlayerを使用すれば大概の事はAV Proを使用せずに済むようになった。

 

1.導入

使い方は超簡単。

まずはVideoPlayerを配置。Createからも作れるので楽。

f:id:HarakeN:20170405160323p:plain

 

 

次に再生したい動画をProjectに入れて、先ほど作ったVideoPlayerのVIdeoClipにつける。基本的にh.264の拡張子mp4なら動くみたい。

ちなみにmovでも再生できたので、たいていの動画は再生できそうです。(確認してないけどaviとか古いのは無理っぽい?)

f:id:HarakeN:20170405161527p:plain

 

 

 

次に動画を映したいCameraを配置。Play On Awakeにチェックを入れてあれば、この状態で実行したときに再生されます。

f:id:HarakeN:20170405162322p:plain

 

 

スクリプトから操作したい場合は、VideoPlayer.Play()とか読んであげれば任意に再生できます。Audioを再生する感覚で操作できるので楽ちん。

 

 

 

2.Canvas使ってるときの配置

コンテンツを作ってるとuGUIを使用してイメージを配置してたり、フェードインやフェードアウトしたりするシーンを作ることが多いと思います。

そんな時に動画を再生すると、uGUIのが動画の前に映った状態で再生されてしまいます。レイヤー構造的にはCanvasより後ろに動画が見える様になっているので、これをどうにかして手前に持ってこなきゃいけません。

 

んなら一番手前に配置すりゃエエだけの話で、これも簡単にできます。

ざっくりいうとレイヤーの一番上のImageを動画にしちゃう感じです。

 

 

まずは、先ほどのVideoPlayerのRender ModeをRender Textureにして、新しく作成したRender Textureをaddしましょう。

一つ気をつけたいのはRenderTextureのSizeを動画の縦横サイズにあわせること。(少し気持ち悪い気がするけど)

f:id:HarakeN:20170405164821p:plain

 

 

次にUIからImage(RawImageでもおk)を作成して、Textureに先ほど作成したRender Textureをaddしましょう。

f:id:HarakeN:20170405165254p:plain

 

これで解決です。

uGUIが描画されてても一番手前に動画が再生されるので、かぶったりしません。

 

 

 

 

今まではunityで動画って聞くだけで「あ~~~~^^」ってなってたし、ソースがmovとか聞いたら死んでたけど、5.6からは超簡単になって最高やね。

 

 

以上。

【Unity】ひらがなに濁点、半濁点をつけたりとったり、小書きにしたり

ひらがなに濁点、半濁点つけれないとダメでしょw

 

そう簡単に言わないでクレメンス。

 

ってことで、ひらがなに濁点とか半濁点をつけれるか判定して変換するようにスクリプトを実装するハメになったので記載。

 

 

どうやってやるンゴ・・・

わからなかったので調べて考えて実装。

 

ちなみに今回いっぱい使う単語の「小書き」ってのはひらがなカタカナの小さい文字(ぁ、っ、ぇ等)を指し、「並字」ってのはその対義語(普通のひらがなの事)を言うらしい。

 

 

・濁点(半濁点)をつけるスクリプト

using UnityEngine;
using System.Collections;
using System;
using System.Text;

 

public void Conversion(){

 

  string input = "は" ;

 

//UTF-8 NFDで他の文字と結合すると濁点になるもの
  char dakuten = '\x3099';

//UTF-8 NFDで他の文字と結合すると半濁点になるもの

  char dakuten = '\x309A';

 

//くっつけてNFCにNormalize

  string add = (input + dakuten).Normalize (NormalizationForm.FormC);

 

//NFCに文字がない場合、文字化けするので文字数が増える

//NFCに文字がある場合、文字数は増えないので

  if (lastMoji.Length == add.Length) {

      Debug.Log("add");  // "ば"になる

    } else {

      Debug.Log ("無理");
  }
}

 

 

濁点くっつけられる文字だけ調べて配列入れて、くぁwせdrftgyふじこlp・・・

とかしなきゃいけないンゴ?

 

と、いろいろ調べていたら、macwindowsUTF-8の違いに気づく。

URF-8にはNFCとNFDってのがあるみたいで、大雑把に言うと濁点入り1文字になるか文字と濁点の2文字で表示されるかの違いがあるらしい(詳しい仕組みはわからない)

たとえばこんな感じ

NFC ー がぎぐげご
・NFD ー か゛き

 

で、Normalizeってのをしてやると、それぞれに変化できるみたい。

この時にNFDで濁点がつけられない文字(たとえば「め」)をNormalizeすると文字化けが起こる。

すると文字数が増えるので、これを判定に使用すればおk。

 

邪道かもしれないけど、スクリプトもすっきりでいいかんじカモ。

 

 

 

・小書き⇔並字にするスクリプト

//小書き文字をあらかじめ用意

public string kogakiMoji;

 

//小書き文字にできる並字をあらかじめ用意

public string namiji;

 

public void Conversion(){

  string input = "あ";

 

//inputが小書き文字かどうか

  for (int i = 0; i < kogakiMoji.Length; i++) {
    if (kogakiMoji [i] == input ) //一致したら

    { 
      input = namiji [i];
      return;
    }
  }

 

//inputが小書き文字にできる並字かどうか

  for (int i = 0; i < namiji.Length; i++) {

    if (kogakiMoji [i] == input ) //一致したら

    { 
      input = namiji [i];
      return;
    }
  }
}

 

こっちは先ほどの、くぁwせdrftgyふじこlp、の部分で言いたかった実装。

あらかじめ、配列に小書き文字(「っ」とか「ぁ」など)と小書きにできる並字(「つ」とか「あ」など)を格納しといて、入力された文字をそれぞれの配列と比較して一致したら変換。みたいな。

配列用意するのがめんどいけど、こっちのほうが王道かな?

 

 

これでいいかんじに実装できるはず。

 

 

以上。