FC2ブログ
    06 «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.» 08

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

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

     

    【ハルシオンブログ】リフレクションを使って別クラスのprivate変数にアクセスする。 

    こんにちは。
    大坂です。

    ちょっとしたテストをしたいときなんかにprivate変数の値を変更したいときがあったりします。
    ブレークポイント設定したり、TestRunner使ったりでもできるとは思いますが、
    今回はリフレクションを使用して変更してみました。

    変更したいprivate変数を持つクラス

    public class Test_1 : MonoBehaviour
    {
    private int test;
    }

    private変数を変更するクラス

    public class Test_2 : MonoBehaviour
    {
    // Start is called before the first frame update
    void Start()
    {
    Test_1 test_1 = FindObjectOfType<Test_1>();
    // タイプの取得
    Type t = test_1.GetType();
    // private変数へのアクセス用
    FieldInfo f = t.GetField(
    "test",
    BindingFlags.NonPublic |
    BindingFlags.Instance |
    BindingFlags.GetField |
    BindingFlags.FlattenHierarchy |
    BindingFlags.SetField
    );
    // private変数に値の設定
    f.SetValue(test_1, 10);

    Debug.Log(f.GetValue(test_1));
    }
    }

    結果



    ちゃんと値が設定されてますね。

    毎回止めてやるのと面倒な時があるので、こんな方法でもできますよという紹介でした。
    ではまたノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】Enumからランダムで1つを選択する方法。 

    オリンピックが始まりましたね。
    金メダルが現時点で5個ですか。
    金の数は世界2位ですね。
    日本頑張れ~!

    さてUnityのお話。

    凄い簡単な話なんですが、Enumをランダムで取得する方法。

    画面にボタンを1個おいて、次のコードを書いてみた

    [Blog0726.cs]

    using System;
    using UnityEngine;
    using UnityEngine.UI;

    public class Blog0726 : MonoBehaviour
    {
    [SerializeField] Button btnRandom;

    enum Direction {
    North,
    East,
    South,
    West,
    COUNT,
    }

    void Start()
    {
    // ボタンを押すたびにランダムに方向を取得
    btnRandom.onClick.AddListener(GetRandomDirection);
    }

    void GetRandomDirection() {
    Direction nextDir = (Direction)Enum.ToObject(typeof(Direction), UnityEngine.Random.Range(0, (int)Direction.COUNT));
    Debug.Log(nextDir);
    }
    }



    結果はこんな感じ。



    8回ボタンを押してみた。

    ランダムでEnumを取得するところはここ。

    Direction nextDir = (Direction)Enum.ToObject(typeof(Direction), UnityEngine.Random.Range(0, (int)Direction.COUNT));


    Directionが東西南北の4つなら、


    Direction nextDir = (Direction)Enum.ToObject(typeof(Direction), UnityEngine.Random.Range(0, 4);


    でもいいけど、Enumの中にCOUNTというのを用意して、Enumの数がいくつ増えてもいいようにしておいてます。

    これでいくらでもEnumからランダムに値をとることができますね!

    ということで今日はここまで。
    あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】Listでのソートの仕方。(あ、以前同じような内容かいたかも 

    こんにちは!坂内っす。
    夏真っ盛りですね!
    30度超えが続いてまいりました!熱中症などにお気を付けください!


    C#でのListソートのお話。

    一度同じような内容の記事かきましたね。

    まぁもう一度ってことで・・・・



    [Blog20210719.cs]

    using System;
    using System.Collections.Generic;
    using UnityEngine;

    public class Blog20210719 : MonoBehaviour
    {
    public enum GameType {
    Action,
    Puzzle,
    Rpg,
    Sports,
    Etc,
    }

    public class Famicon {
    public int no;
    public string gameName;
    public DateTime releaseDate;
    public GameType gameType;

    public Famicon(int no, string name, DateTime date, GameType type) {
    this.no = no;
    gameName = name;
    releaseDate = date;
    gameType = type;
    }

    public Famicon() { }
    }

    List cassettes = new List();

    private void Start() {
    SetGame();

    ViewList("そのまま", cassettes);

    // ソート

    }

    void ViewList(string viewStr, List list) {
    foreach (Famicon fami in list) {
    Debug.Log(fami.no + " 「" + fami.gameName + "」 発売日 : " + fami.releaseDate.ToLongDateString() + " ゲーム種 : " + fami.gameType);
    }
    }

    void SetGame() {
    Famicon game = new Famicon();
    game = new Famicon(0, "マリオブラザーズ", DateTime.Parse("1983/9/9"), GameType.Action);
    cassettes.Add(game);
    game = new Famicon(1, "テニス", DateTime.Parse("1984/1/14"), GameType.Sports);
    cassettes.Add(game);
    game = new Famicon(2, "ゴルフ", DateTime.Parse("1984/5/1"), GameType.Sports);
    cassettes.Add(game);
    game = new Famicon(3, "アイスクライマー", DateTime.Parse("1985/1/30"), GameType.Action);
    cassettes.Add(game);
    game = new Famicon(4, "ファイナルファンタジー", DateTime.Parse("1987/12/18"), GameType.Rpg);
    cassettes.Add(game);
    game = new Famicon(5, "コナミワイワイワールド", DateTime.Parse("1988/1/14"), GameType.Action);
    cassettes.Add(game);
    game = new Famicon(6, "ぎゅわんぶらあ自己中心派", DateTime.Parse("1987/11/11"), GameType.Etc);
    cassettes.Add(game);
    }
    }




    こんな感じでまだソートしてないのでそのままの順で表示されます。

    では、GameTypeでソートをしてみます。

    private void Start() {
    SetGame();

    ViewList("そのまま", cassettes);

    // ゲーム種でソート
    cassettes.Sort((a, b) => b.gameType - a.gameType);
    ViewList("ゲーム種でソート", cassettes);
    }



    List.Sort((a, b) => b.gameType - a.gameType)
    でソートができます。
    これの結果はこれ。



    ゲーム種でソートができました。
    Actionが最後にきましたね。
    ソートの引数を変えてやれば、逆順になります。

    List.Sort((a, b) => a.gameType - b.gameType);

    こうすれば、Actionが先にきますね。

    名前でソートする場合はこんな感じ。


    private void Start() {
    SetGame();

    ViewList("そのまま", cassettes);

    // ゲーム種でソート
    cassettes.Sort((a, b) => b.gameType - a.gameType);
    ViewList("ゲーム種でソート", cassettes);

    cassettes.Sort((a, b) => a.gameName.CompareTo(b.gameName));
    ViewList("名前でソート", cassettes);
    }



    stringには-(マイナス)が使えないため、CompareToを使います。



    ちゃんと名前でソートできましたね。

    こんな感じでListのソートができます。

    ってことで、今日はここまで!あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】複数行の文字列で行の先頭が改行の場合だけ消したかった 

    こんにちは。
    大坂です。

    こんなテキストの先頭が改行の行を消したいときがあったので、その方法です。


    正規表現を使ってやるだけですけどね。

    private void TestMethod(string test) {
    Regex.Replace(test, "^[\r\n]", string.Empty, RegexOptions.Multiline);
    }

    「RegexOptions.Multiline」を指定すると複数行モードで正規表現の処理をしてくれますね。
    複数行モードにすると
    『^ と $ の意味を変更して、文字列全体の先頭と末尾だけでなく、任意の行の先頭と末尾にもそれぞれが一致するようにします。』
    とのことなので、各行で処理してくれるようになりますね。

    一応、処理前と処理後の結果。




    簡単なことでしたが何かに使えればと。
    ではまたノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】Linqを使うとListと配列の相互変換ができちゃう! 

    今週もブログの時間がやってまいりました。坂内っす。
    梅雨あけたんじゃないかっていうくらい快晴ですね!(関東の一部)

    ポケガ3が難産すぎて大変ですね・・・・今年中にリリース!っていってたけど、最低でも来年3月ころになりそうです・・・・
    もうマジで死ぬ。
    金無くて死ぬ。
    来年リリースするまで持たない・・・・ってことで、3年くらい前に作ってたシミュレーションハクスラにも手を出し始めたけど、これまたクリエイティブが多くて進まなそう・・・・

    どっちにしてもやばいっすね。
    でもどちらも作り上げたいし・・・さてどうしたものか。

    Unityでゲーム作ってるとListを使ったり配列使ったりしますよね。
    Listと配列の相互変換がLinqがあると簡単にできるよって話。


    using System.Linq;
    using System.Collections.Generic;
    using UnityEngine;

    public class Blog0712 : MonoBehaviour
    {
    List<int> listData = new List<int> { 1, 3, 5, 7, 9 };
    int[] aryData = {2, 4, 6, 8, 10};

    private void Awake() {
    // Listを配列にする
    int[] outAryInt = listData.ToArray();

    // 配列をListにする
    List<int> outListInt = aryData.ToList();

    string strOutAryInt = "";
    Debug.Log("outAryInt");
    foreach (int data in outAryInt) {
    strOutAryInt += data + " ";
    }
    Debug.Log(strOutAryInt);

    string strOutListInt = "";
    Debug.Log("outListInt");
    foreach (int data in outListInt) {
    strOutListInt += data + " ";
    }
    Debug.Log(strOutListInt);
    }
    }




    こんな感じ。

    Listを配列に変換するには ToArray
    配列をListに変換するには ToList
    をつかいます。
    この二つを使うにはLinqが必要になるため、using System.Linq;は忘れずに。

    本日はListと配列の相互変換についてでした。

    あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】VSCodeのLocal Historyが便利 

    こんにちは。
    大坂です。

    Gitなどで操作を間違って破棄したくなかったコードを破棄してしまったときなんかに、
    VSCodeの拡張機能のLocalHistoryを入れておくとファイルの履歴が確認できるので便利です。

    インストール方法はVSCodeの拡張機能でLocal Historyを検索してインストールボタンを押すだけ。


    これでファイルを触って更新すると履歴が見れるようになります。


    当たり前ですが、履歴ファイルがどんどん増えていきます。


    LocalHistoryの設定で残しておく日数が設定できるので、設定しておくといいかもしれません。


    デフォルトは30日で、0を設定すると消さないみたいですね。


    簡単に使えるので導入しておくと便利かもしれませんね。
    では今週もこれにてノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】JsonUtilityとかでデータを保存する際に、ポリモーフィズム化されてるデータの値が保存されないときに、こうやったよ! 

    こんにちわ。
    坂内っす。

    熱海の大雨と土石流大変ですね・・・なくなった方もいるとか。
    現地の方はお気を付けくださいませ。

    Unityでデータを保存するときにJSONにして保存とかよくやりますよね。
    この時、子供クラスのデータが保存されないので気をつけましょう。

    例えばこんなコードの場合。

    [SaveDataBase.cs]

    [System.Serializable]
    public class SaveDataBase
    {
    public int num;
    }



    [SaveDataChild.cs]

    [System.Serializable]
    public class SaveDataChild : SaveDataBase
    {
    public string label;
    }


    [SaveData.cs]

    using System.Collections.Generic;
    [System.Serializable]
    public class SaveData
    {
    public List<SaveDataBase> data;
    }



    [Blog0705.cs]

    using UnityEngine;
    using System.IO;
    using System.Collections.Generic;
    using System.Runtime.Serialization.Formatters.Binary;

    public class Blog070502 : MonoBehaviour
    {
    string[] str = {
    "あああ",
    "いいい",
    "うう",
    "ええ",
    "おぉぉぉ"
    };
    string filePath;
    private static readonly string SavePath = "save.bytes";

    void Start()
    {
    SaveData saveData = new SaveData();
    saveData.data = new List<SaveDataBase>();
    for (int i = 0; i < 5; i++) {
    SaveDataChild data = new SaveDataChild();
    data.num = i;
    data.label = str[i];
    saveData.data.Add(data);
    }
    Save(saveData);
    }

    // 引数で渡ってきたオブジェクトをシリアライズして返す
    public static string Serialize<T>(T obj) {}

    // 引数のテキストを指定されたクラスにデシリアライズして返す
    public static T Deserialize<T>(string key) {}

    private static string GetJson() {
    string filePath = Application.persistentDataPath + "/" + SavePath; // Jsonを保存する場所のパスを取得

    if (File.Exists(filePath)) { // 指定したファイルがあるか調べるメソッド
    return File.ReadAllText(filePath); // ファイルがあれば取得してJsonに変換
    } else {
    return "";
    }
    }

    public void Save(SaveData data) {
    // 指定したパスに新しいファイルを作成し、内容をファイルに書き込み閉じる
    File.WriteAllText(Application.persistentDataPath + "/" + SavePath, JsonUtility.ToJson(data));
    string json = JsonUtility.ToJson(data);
    }

    void Load() {
    string jsonTxt = GetJson();
    SaveData data = new SaveData();
    data = JsonUtility.FromJson<SaveData>(jsonTxt);
    }
    }



    こんな感じで、SaveDataを保存。
    出来上がったファイルはこちら。



    「あああ」とか「いいい」などのSaveDataChildがもっているデータは保存されません。

    もちろんSaveDataChildのListをそのままSaveDataにいれれば保存されます。

    親:Chara
    子:CharaA:Chara
    子:CharaB:Chara

    こんな構成のデータって考えられると思うんですよね。
    このデータを保存するときって
    List<Chara> charas = new List<Chara>
    にCharaAやBのデータを保存するかと。

    この時に同じ現象が起きます。
    Charaが持っているデータは保存されるが、CharaAなどが継承後に追加したデータが保存されません。

    え?

    List<CharaA> charaA = new List<CharaA>();
    List<CharaA> charaB = new List<CharaB>();

    ってやればいいって?
    それもありですね。

    あ、話を戻します。

    ポリモーフィズム化したクラスは保存されないようですね。

    List<Chara> charas = new List<Chara>()
    にCharaAとかBのデータを入れた場合に、AやBの追加されたデータも保存する方法ありますか?

    とりあえずこんな感じで対応してみましたが・・・・

    SaveDataBase.csと保存処理のかいてあるSaveメソッドに手を入れてみた。

    [SaveData.cs]

    using System.Collections.Generic;
    [System.Serializable]
    public class SaveData
    {
    public List data;
    public string datastring;   ←New
    }


    [Blog0706.cs]

    public void Save(SaveData data) {
    saveData.datastring = Serialize<List<SaveDataBase>>(saveData.data);  ←New
    // 指定したパスに新しいファイルを作成し、内容をファイルに書き込み閉じる
    File.WriteAllText(Application.persistentDataPath + "/" + SavePath, JsonUtility.ToJson(data));
    string json = JsonUtility.ToJson(data);
    }



    赤文字のところを追加して、実際に保存をすると、こんなデータになります。



    あとはロードのところで以下の追加をすればSaveDataChildのデータも保存読み込みができます。

    [Blog0706.cs]

    void Load() {
    string jsonTxt = GetJson();
    SaveData data = new SaveData();
    data = JsonUtility.FromJson(jsonTxt);
    data.data = Deserialize>(data.data);  ←New
    }



    無理やり感すごいですが、別途シリアライズして文字列を突っ込んで保存って感じでできましたw

    正しいやり方わかる方教えてぷりーず!

    ということで、ポリモーフィズムのデータをJsonUtilityで保存する方法でした。

    では、あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】Listや配列の中身が一緒か確認するときはSequenceEqualを使うといいですね。 

    こんにちは。
    大坂です。

    Listや配列の中身が一緒か確認するときがたまにありますね。
    そんな時はLinqのSequenceEqualを使うと簡単ですね。

    コード

    List<int> list_1 = new List<int>() { 0, 1, 2, 3, 4, 5 };
    List<int> list_2 = new List<int>() { 0, 1, 2, 3, 4, 5 };
    List<int> list_3 = new List<int>() { 0, 1, 2, 3, 4, 10 };

    Debug.Log($"List_1とList_2:{list_1.SequenceEqual(list_2)}");
    Debug.Log($"List_1とList_3:{list_1.SequenceEqual(list_3)}");


    結果


    ちゃんと同じならTrueで違えばFalseですね。
    たまに使えるときがあるので覚えておくと便利かもしれません。

    ではまたノシ

    Category: Androidアプリ紹介

    tb 0 : cm 0