FC2ブログ
    05 «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.» 07

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

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

     

    【ハルシオンブログ】デリゲートに格納されたメソッドをスレッドセーフに呼ぶ方法? 

    こんにちは。坂内っす。

    UnityでC#書いてる時にデリゲート使ってますか?
    デリゲートクラスがNullになってしまいエラーが出たりってことありませんか?

    そんな時はスレッドセーフな書き方があるらしいです。

    スレッドセーフとはなんぞや?
    「スレッドセーフ(Thread-safe)は、マルチスレッドプログラミングにおける概念である。あるコードがスレッドセーフであるという場合、そのコードを複数のスレッドが同時並行的に実行しても問題が発生しないことを意味する。特に、ある共有データへの複数のスレッドによるアクセスがあるとき、一度に1つのスレッドのみがその共有データにアクセスするようにして安全性を確保しなければならない。」

    Wikiより


    だそうです。

    こんなコードを書いた時、TestBのほうがスレッドセーフらしいですよ。

    [Blog20220606.cs]

    using UnityEngine;

    public class Blog20220606 : MonoBehaviour
    {

    public delegate void Callback();

    void Start()
    {
    TestA(ShowHello);
    TestB(ShowHello);
    TestA(null);
    TestB(null);
    }

    void ShowHello() {
    Debug.Log("Hello!!");
    }

    static void TestA(Callback callback) {
    Debug.Log("TestA");
    if (callback != null) {
    callback();
    }
    }
    static void TestB(Callback callback) {
    Debug.Log("TestB");
    callback?.Invoke();
    }
    }



    もちろんTestAの方でもnullの判定はしているので動きます。エラーはでません。

    Delegateは非同期処理とかでよく使われたりするということで、TestAのcallback()の時点でcallbackがnullになった場合(ifの後で)NullPointerExceptionが出てしまう可能性があるらしいです。
    そこでTestBのように 「callback?.Invoke()」という形にするとスレッドセーフになるようです。

    メモ程度ですが、デリゲートのスレッドセーフな実行方法についてでした。

    では、あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】ゲームオブジェクトかつアクティブでコンポーネントが有効かの確認 

    こんにちは。
    大坂です。

    ゲームオブジェクトがアクティブかつコンポーネントが有効かの確認をしたいとき。
    まぁ簡単で「isActiveAndEnabled」を使うだけです。

    こんな3個のパターンで確認
    ①ゲームオブジェクトが非アクティブ


    ②Imageコンポーネントが無効


    ③ゲームオブジェクトがアクティブかつImageコンポーネントが有効


    確認コード

    public Image img_1;
    public Image img_2;
    public Image img_3;

    void Start()
    {
    Debug.Log($"img_1:{img_1.isActiveAndEnabled}");
    Debug.Log($"img_2:{img_2.isActiveAndEnabled}");
    Debug.Log($"img_3:{img_3.isActiveAndEnabled}");
    }


    結果


    「③ゲームオブジェクトがアクティブかつImageコンポーネントが有効」の場合だけ「True」が返ってきますね。
    あんまり使いどころがないかもしれませんが、両方を一気に確認したいときに使えます。

    ではまたノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】特定のRoot以下にある同じクラスをまとめてとる方法。 

    こんにちは。
    週末から暑くなってきましたね。
    そろそろ夏ですかね?まだ梅雨にもなってないですが・・・今年も暑そうだorz

    さてUnityのお話。
    同じような話は何回か書いた気もしなくはないが・・・

    Unityでこんな構成の時にまとめて文字を変えたい。
    もちろんTextじゃなくてもなんでもいいのですが、Root以下の同じクラスをまとめて取得する方法。




    Textsの子供にある、数あるuGUIのTextの文字を一気に変えたいって時、GetComponentsInChildrenを使うと楽ですよね。



    こんな感じに。

    [Blog20220530.cs]

    using UnityEngine;
    using UnityEngine.UI;

    public class Blog20220530 : MonoBehaviour
    {
    public GameObject uiBase;
    public Button btnExe;

    void Start()
    {
    btnExe.onClick.AddListener(ExecuteScript);
    }

    void ExecuteScript() {
    Text[] texts = uiBase.GetComponentsInChildren<Text>();
    foreach (Text txt in texts) {
    txt.text = "文字変更したよ";
    }
    }
    }



    GetComponentsInChildrenの戻り値は指定したクラスの配列になります。

    また、こんな感じで他のオブジェクトの子供や孫になっていてもちゃんと取ってくれます。



    上記でも問題なく文字が変更されます。

    まとめて同じ文字に変えるとかという動きはまずないと思いますが、Rootを指定してその子供のクラスを全部取るというのができるので、使い勝手はよさそうですよね!

    ということで、GetComponentsInChildren<クラス>の簡単な使い方の紹介でした。


    では、あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】アクティブシーンの再読み込み 

    こんにちは。
    大坂です。

    アクティブなシーンの再読み込みについて。
    シーン名を文字列で指定しても出来るんですが、「SceneManager.GetActiveScene()」を使うとよさそうですね。

    SceneManager.LoadScene(SceneManager.GetActiveScene().name);


    「SceneManager.GetActiveScene()」は「Scene」がとれるので、
    「.name」を付けて名前を取得すれば、これだけでアクティブなシーンの再読み込みができます。

    ステージ制のゲームのリトライなどで使いやすそうですかね。
    ではまたノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】uGUIのオブジェクトを複数同時に透明にしようとしたら、CanvasGroupを使うといいよ。 

    こんにちは、坂内っす。

    昨日一昨日はIndieLiveExpo2022がありましたね。

    https://indie.live-expo.games/

    2日目にポケガ3取り上げて頂きました。



    基本今までこういうのに応募してこなかったので、何書けばいいのかとか色々わかりましぇんでしたね。

    開発も中盤超えたので、このまま完成まで頑張っていこうと思いマッスル。


    UnityでuGUIの複数オブジェクトを同時に透明にする場合、どうやってますか?



    こんな感じでImageが複数あったり、Textがあったり。
    下にある「透明にする」ボタンを押すと、3個のImage、Textを透明にします。

    [Blog20220523.cs]

    using UnityEngine;
    using UnityEngine.UI;

    public class Blog20220523 : MonoBehaviour
    {

    [SerializeField] Image img1;
    [SerializeField] Image img2;
    [SerializeField] Image img3;
    [SerializeField] Text txt1;
    [SerializeField] Button btnTransparent;

    void Start()
    {
    btnTransparent.onClick.AddListener(TransparentUI);
    }

    void TransparentUI() {
    img1.color = new Color32(255, 255, 255, 0);
    img2.color = new Color32(255, 255, 255, 0);
    img3.color = new Color32(255, 255, 255, 0);
    txt1.color = new Color32(255, 255, 255, 0);
    }
    }





    こんな感じで、ボタンを押すとImage3個、Text1個を透明にできます。

    でも、透明にするオブジェクトが多いと、コードがどんどん増えていってしまいますよね。
    Imageが100個あると、 imgX.color = new Color32(255, 255, 255, 0); という行を100個書かないといけなくなってしまいます。

    そんな時にはCanvasGroupを使うといいですよね。

    空のオブジェクトを作成し、その子供として消したいオブジェクトを配置します。



    このCanvasGroupにはAlphaがあり、それをいじることで、子供全体のalphaが変更されます。



    そうすると、コードではこのCanvasGroupのAlphaだけいじればいいだけになります。

    [Blog20220523.cs]

    using UnityEngine;
    using UnityEngine.UI;

    public class Blog20220523 : MonoBehaviour
    {

    [SerializeField] CanvasGroup cg;
    [SerializeField] Button btnTransparent;

    void Start()
    {
    btnTransparent.onClick.AddListener(TransparentUI);
    }

    void TransparentUI() {
    cg.alpha = 0f;
    }
    }



    これだけで上記にあった処理と同じことができます。


    ということで、uGUIを使う方は、CanvasGroupを覚えておくと色々と便利です。

    CanvasGroupの話でした。
    では、あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0