FC2ブログ
    09 «1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.» 11

    ハルシオンシステムの気ままBlog

    株式会社ハルシオンシステムのメンバーが送る、UnityやらJavaやらの技術的話題から、自社開発のアプリの宣伝とかとかのブログです。ほんと気ままにいきたいと思います。更新日は毎週 月 木でっす!

     

    【ハルシオンブログ】Unity2021.2でちょっと便利な機能 

    こんにちは。
    大坂です。

    Unity2021.2でちょっと便利な機能を紹介。

    ①Scaleの比率固定
    ここをクリックすると比率が固定されます。


    こんな感じで1か所変えるだけで全部変わってくれます。




    Scale変えるときは大体比率は固定で変えるので少しだけ楽になりますね。

    ②UnityEditor上でTextureを非圧縮
    BuildSettingsでTexture Compressionを「Force Uncompressed」に変更するだけ。


    これをやると大量の画像をインポートしたときなんかに圧縮で凄い時間がかかっていたのがなくなります。
    ただEditor上で圧縮した画像が確認できなくなる注意点はありますかね。

    まだまだ便利になっているところはあると思いますが、今日はこの辺でノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】オブジェクトのONOFFとコンポーネントのONOFFは別ですよ。SetActiveとenabledを使い分けよう。 

    おはようございます。
    10月もそろそろ終わりですね。

    Unityの基本的な機能ですが、オブジェクトのONOFFにSetActiveとenableって使ってますか?
    同じような感じにみえて、違う処理なんですよね。

    要点をまとめると、SetActiveはオブジェクトをONOFF。
    enabledはコンポーネントをONOFF。

    この違いです。

    SetActiveをしてみます。

    [Blog20211025.cs]

    using UnityEngine;

    public class Blog20211025 : MonoBehaviour
    {
    [SerializeField] GameObject cube;

    private void Start() {
    cube.SetActive(false);
    }
    }



    これを実行すると、こうなる。


    オブジェクトがOFFになります。

    enabledの方はこういうことができません。

    [Blog20211025.cs]

    using UnityEngine;

    public class Blog20211025 : MonoBehaviour
    {
    [SerializeField] GameObject cube;

    private void Start() {
    cube.enabled = false;
    }
    }


    enabledのところがエラーになりますね。

    さきほど「enabledはコンポーネントのONOFF」といった通り、cubeオブジェクトについているコンポーネントを指定しないとenabledはいじれません。

    [Blog20211025.cs]

    using UnityEngine;

    public class Blog20211025 : MonoBehaviour
    {
    [SerializeField] GameObject cube;

    private void Start() {
    cube.GetComponent<MeshRenderer>().enabled = false;
    }
    }



    これはできますね。
    実行してみましょう。



    オブジェクトはONのままですが、MeshRendererがOFFになりました。
    (まぁMeshRendererをゲットしてenabledしたから当たり前だけど)

    という感じで、この2つのONOFF関数は別の動きをします。

    GameObject.Findを使ってオブジェクトを取得する場合、SetActiveで消したやつは取得できなくなるので注意してください。
    enabledでコンポーネントをOFFにしただけのものは、Findで取得できます。

    同じONOFFにする関数ですが、それぞれのシチュエーションにあった方を使ってください。

    では、あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】ちょっとした遅延処理を書くときにDOVirtualが便利かも? 

    こんにちは。
    大坂です。

    開発をしていてちょっとした遅延処理を書きたいときがあります。
    コルーチンにするにもなぁというときは「Invoke」を使ったりするのですが、メソッド名がString指定だったり引数渡せなかったりで使いにです。

    そんな時は「DOTween」に準備されてる「DOVirtual」を使うと便利かもしれません。

    こんな感じで使えます。

    readonly System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

    void Start() {
    sw.Start();
    Debug.Log("Start");
    // 1秒後にTestMethodを実行
    DOVirtual.DelayedCall(1f, () => TestMethod());
    }

    public void TestMethod() {
    Debug.Log("TestMethodt実行");
    sw.Stop();
    Debug.Log($"{sw.ElapsedMilliseconds}ms");
    }

    実行結果。


    ちゃんと1秒後に実行されてますね。
    お手軽に遅延実行ができるので選択肢の一つとして覚えておくといいかもしれません。

    ではまたノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】Destroyでオブジェクトが消えるタイミングとかとか 

    おこんにちは。坂内っす。
    10月も後半になってきたじゃありませんか!
    さすがに寒くなってきましたねぇ 朝方寒くて目ガ覚めてしまったですよ。
    みなさんも風邪にお気を付けください。

    さて、Unityでこんな構成の時。
    子供のオブジェクトを全部消したいってことありますよね。



    こんな感じに順番に0番目を消せば消せるんじゃないかと

    [Blog20211018.cs]

    using UnityEngine;

    public class Blog20211018 : MonoBehaviour
    {
    [SerializeField] GameObject objParent;

    void Start()
    {
    for (int i = 0; i < 5; i++) {
    Destroy(objParent.transform.GetChild(0).gameObject);
    }
    }
    }



    どうなるかというと、1個目のオブジェクトしか消えません。
    Destroyを使用して、オブジェクトが削除されるタイミングは、フレーム更新の完了後のようです。(公式マニュアルによる)

    ではこうすればどうなるか。


    using System.Collections;
    using UnityEngine;

    public class Blog20211018 : MonoBehaviour
    {
    [SerializeField] GameObject objParent;

    IEnumerator Start()
    {
    for (int i = 0; i < 5; i++) {
    Destroy(objParent.transform.GetChild(0).gameObject);
    yield return null;
    }
    }
    }



    一応消えます・・・・・

    すごいまばらにですが(笑)



    こういう時はこうやって消しましょう(過去ブログにも書いたと思いますが)

    [Blog20211018.cs]

    using UnityEngine;

    public class Blog20211018 : MonoBehaviour
    {
    [SerializeField] GameObject objParent;

    void Start()
    {
    foreach (Transform trn in objParent.transform) {
    Destroy(trn.gameObject);
    }
    }
    }





    ちゃんと起動直後に全部まとめて消えてますね。

    ということで、Destroyのタイミングについてでした。

    あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】独自の#ifディレクティブを使用したいとき 

    こんにちは。
    大坂です。

    開発中に独自の#ifディレクティブを使用したいときがたまにあります。
    特定のスクリプトにつけるだけなら、スクリプトの頭に「#define 〇〇」などを付ければできますね。

    スクリプトだけにつける書き方

    #define TEST

    using UnityEngine;

    public class Test_1 : MonoBehaviour
    {
    private void Start() {
    #if TEST
    Debug.Log("Test");
    #endif
    }
    }


    全体で使いたい場合は、「Scripting Define Symbols」機能を使うとできます。
    設定するのは[ProjectSettings]-[Player]-[OtherSettings]-[Scripting Define Symbols]
    に設定するだけ。



    とこの設定をするだけで使えますね。
    複数設定したい場合は「;(セミコロン)」で区切ると設定できます。
    独自の#ifディレクティブを使用したい場合はやってみるといいかもしれませんね。

    ではまたノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】Unityでオブジェクトプールって使ったりしてますか?私は使ってませんが、こういうこと? 

    今日は10月だというのに、気温が30度もあるとかって話ですね。
    週末には20度まで下がるとのことですが・・・・
    温度差で風邪ひかないようにしてくださいな。
    坂内っす。

    オブジェクトプール使ってますか?
    私は使ってません。

    これどういう時に使うといいんでしょうかね。
    数百個のオブジェクトをInstantiateするときとかなんでしょうか。
    シューティングゲームの弾みたいな?
    敵もいっぱい同じのが出るなら使えそうですよね。

    結局オブジェクトをInstantiateするときに、GCが走るので、「多大なオブジェクトをInstantiateやDestroyをすると重くなる」というものの対応でオブジェクトプールがあるんだとは思ってます。
    なかなかポケットガールみたいなシミュレーションゲームでは使う機会なさそうなんですよね・・・

    ちなみに簡単なオブジェクトプール

    [Blog20211011.cs]

    using UnityEngine;
    using UnityEngine.UI;

    public class Blog20211011 : MonoBehaviour
    {
    [SerializeField] GameObject objPref;
    [SerializeField] Button btnCreate;

    int count = 100;

    void Start()
    {
    btnCreate.onClick.AddListener(OnClickCreate);
    }

    void OnClickCreate() {
    for (int i = 0; i < count; i++) {
    Instantiate(objPref, new Vector3(Random.Range(-10f, 10), Random.Range(-10f, 10f), Random.Range(-10f, 10f)), Quaternion.identity);
    }
    }
    }



    例えば、ボタンを押したときにCubeを100個生成する処理がこのようにあった場合、100回GCが走ってしまいます。
    (このコードだけだとボタンを押すたびに100個を超えて増えてしまいますが)

    オブジェクトプールを使うとこんな感じになります(たぶん

    [Blog20211011.cs]

    using UnityEngine;
    using UnityEngine.UI;

    public class Blog20211011 : MonoBehaviour
    {
    [SerializeField] GameObject objPref;
    [SerializeField] Button btnCreate;

    GameObject[] cubes;

    int count = 100;

    private void Awake() {
    cubes = new GameObject[count];
    for (int i = 0; i < count; i++) {
    GameObject obj = Instantiate(objPref, new Vector3(Random.Range(-10f, 10), Random.Range(-10f, 10f), Random.Range(-10f, 10f)), Quaternion.identity);
    cubes[i] = obj;
    cubes[i].SetActive(false);
    }
    }

    void Start()
    {
    btnCreate.onClick.AddListener(OnClickCreate);
    }

    void OnClickCreate() {
    foreach (GameObject obj in cubes) {
    obj.SetActive(true);
    }
    }
    }



    はじめにオブジェクトを作成し、プールしておきます。
    実際に使う際には、プールされたオブジェクトを表示するといった形で使用します。

    また、消す際にもDestroyをしないで、SetActive(false)で消すことができます。
    これによって無駄にGCを発生させないようにするのがオブジェクトプールのようです。

    本日はオブジェクトプールについてでした。

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】スプラッシュスクリーンより前に何か処理したいとき 

    こんにちは。
    大坂です。

    スプラッシュスクリーンより前に何か処理したいときの方法です。
    「RuntimeInitializeOnLoadMethod」に「RuntimeInitializeLoadType.BeforeSplashScreen」を付けて使いましょう。

    一応書き方。

    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)]
    private static void Initialize() {
    // スプラッシュ前に実行したい処理
    }

    「RuntimeInitializeLoadType」は他にもあるみたいなので用途に応じて試してみるといいですね。
    https://docs.unity3d.com/ja/2021.1/ScriptReference/RuntimeInitializeLoadType.html

    使うときの注意点としては、
    複数指定すると実行順を制御できない
    必ず実行されるので、場合分けで使いたかったりする場合は使わない方がよい
    があるみたいですね。

    では、短いですが今週もこれにてノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】uGUIのSliderに、動かしている時は動かないが、離した時のみ動作する処理を追加する方法 

    こんにちは。
    まだ暑い日が続いてますね。
    秋なのに30度とかいっちゃってるらしいですよ。
    坂内っす。

    Unity uGUIのスライダーを使っているときに、「スライダーを動かして、決定したときに特定の処理を行う。」ということをしようとした場合、どうすればいいのかのメモ。

    スライダーについてるイベント「onValueChanged」だと、スライダーが動いたときに処理を行ってしまいます。

    こんな感じ。



    これだとスライダを動かしている間ずっと処理が動いてしまいます。

    動かし終わって離したときに1回処理が流れるようにしたいですね。

    まずは、こんなクラスを作ります。

    [SliderExt.cs]

    using UnityEngine;
    using UnityEngine.EventSystems;
    using UnityEngine.UI;

    public class SliderExt : MonoBehaviour, IPointerUpHandler
    {
    Slider sld;

    private void Awake() {
    sld = GetComponent<Slider>();
    }

    public void OnPointerUp(PointerEventData eventData) {
    Debug.Log(sld.value);
    }
    }


    これをSliderのオブジェクトにくっつけます。



    こうすることで、スライダーを動かしている時は処理が走らないが、離した時に処理が走るようになります。



    ということで、Sliderに離した時の処理を追加する方法でした。

    あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0