FC2ブログ
    11 «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.» 01

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

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

     

    【ハルシオンブログ】ScriptableObjectを使う時の注意点。そのまま使うとマスタの値が変わっちゃうよ? 

    今日は素敵な天気ですね!こんな日は散歩がしたくなります!
    まぁ しませんけど。坂内です。

    以前ScriptableObjectの作成方法や、使い方を紹介しました。
    【ハルシオンブログ】UnityでScriptableObjectを作成して、使う方法の紹介。なんか使いやすいように使ってください! 】

    マスタデータ的な感じで使うことが多いかと思いますが、使う上で気を付けないといけない点があるので、紹介。

    こんなデータを作成します。
    【Enemy.cs】
    public class Enemy : ScriptableObject
    {
    public List enemys = new List();

    [System.Serializable]
    public class EnemyData {
    public string name;
    public int maxHp;
    public int hp;
    public int atk;
    public Sprite image;
    }
    }




    これで、敵のデータ作成完了。

    次に画面にボタンを置き、クリックすることで、敵に攻撃をする感じのを作ります。



    【Script20190415.cs】
    using UnityEngine;
    using UnityEngine.UI;

    public class Script20190415 : MonoBehaviour
    {
    [SerializeField]
    Enemy enemyMst;
    Enemy.EnemyData currentEnemy;

    // UI
    public Text lblEnemyName;
    public Text lblEnemyHP;
    public Image imgEnemy;

    private void Start() {
    MakeNewEnemy();
    }

    public void OnClickAttack() {
    // 攻撃ダメージ(10~30)
    int atkDmg = Random.Range(10,31);
    currentEnemy.hp -= atkDmg;
    if (currentEnemy.hp <= 0) {
    MakeNewEnemy();
    return;
    }
    lblEnemyHP.text = currentEnemy.hp + "/" + currentEnemy.maxHp;
    }

    private void MakeNewEnemy()
    {
    // 敵のデータをランダムで1体作成
    currentEnemy = enemyMst.enemys[Random.Range(0, enemyMst.enemys.Count)];
    lblEnemyName.text = currentEnemy.name;
    lblEnemyHP.text = currentEnemy.hp + "/" + currentEnemy.maxHp;
    imgEnemy.sprite = currentEnemy.image;

    }
    }


    ボタンをクリックしたときにOnClickAttackを呼ぶようにします。

    そうすると・・・・




    えっ!

    なんかおかしい・・・・
    調べてみると、こうなっているのが分かります。



    えー!マスタの値がかわってるうううううう!!!

    これじゃマスタとしての意味なくなってしまいます。

    これ、値渡しじゃなくて参照渡しだから起きちゃうんですよね。

    なので、ScriptableObjectのオブジェクトを使う場合にはディープコピーにて使ってあげるといいと思います。

    なんかいい方法あるのかもしれませんが、今のところこんな感じでやってます。

    【Enemy.cs】
    using System.Collections.Generic;
    using UnityEngine;

    [CreateAssetMenu(fileName = "EnemyData", menuName = "ScriptableObjects/MakeEnemyData")]
    public class Enemy : ScriptableObject
    {
    public List<EnemyData> enemys = new List<EnemyData>();

    [System.Serializable]
    public class EnemyData {
    public string name;
    public int maxHp;
    public int hp;
    public int atk;
    public Sprite image;
    public void Copy(EnemyData enemyData)
    {
    this.name = enemyData.name;
    this.maxHp = enemyData.maxHp;
    this.hp = enemyData.hp;
    this.atk = enemyData.atk;
    this.image = enemyData.image;
    }
    }
    }


    コピーメソッドを付けてあげます。

    次にScript20190415.csのMakeNewEnemyメソッドを次のように変えます

    Private void MakeNewEnemy()
    {
    // 敵のデータをランダムで1体作成
    currentEnemy = new Enemy.EnemyData();
    currentEnemy.Copy(enemyMst.enemys[Random.Range(0, enemyMst.enemys.Count)]);

    lblEnemyName.text = currentEnemy.name;
    lblEnemyHP.text = currentEnemy.hp + "/" + currentEnemy.maxHp;
    imgEnemy.sprite = currentEnemy.image;
    }



    こんな感じでやれば、ちゃんと動くようになります。



    気を付けないと、マスタデータが書き換わってしまいます。

    という感じで、今日はScriptableObjectを使う上での注意点でした。

    あでゅ~ノシ

    Category: 開発日記(Unity)

    Tag: Unity  ゲーム  ゲーム開発  C#  ScriptableObject 
    tb 0 : cm 4   

    【ハルシオンブログ】Unityでのシーン間のデータの受け渡し…初心に戻ってみました。 

    花粉が飛び始めた感じですね。
    今年もまた多いとか・・・つらい時期が始まりました。坂内っす。

    ネタが思いつかないので、初心に戻って「シーンを跨いだデータの渡し方」をやってみましょう。

    まずはシーンを2つ用意します。

    シーン


    シーン


    やることは、「シーン1のインプットフィールドに文字を入力し、ボタンで次のシーン(シーン2)に行って、テキストにシーン1で入力した文字を出力する。」です。

    シーン間で引き継げるクラスとオブジェクトを用意する。
    まずは、以下のクラスを作成。

    引き継ぎ用クラス
    [DeliverClass.cs]
    using UnityEngine;

    public class DeliverClass : MonoBehaviour
    {
    public string deliverString;

    private void Start() {
    DontDestroyOnLoad(this);
    }
    }


    上記クラスをシーン1に置きます。

    ●シーン1



    受け渡す準備が完了しました。

    それでは、シーン1で「ボタンを押したら、インプットフィールドに入力した文字をDeliverクラスに引き渡す」をやってみましょう。

    [Scene1.cs]
    using UnityEngine;
    using UnityEngine.SceneManagement;
    using UnityEngine.UI;

    public class Scene1 : MonoBehaviour {
    public InputField inputField;

    public void OnClickButton() {
    // DeliverClassを取得
    DeliverClass deliver = FindObjectOfType<DeliverClass>();
    // InputFieldの文字列をDeliverに渡す
    deliver.deliverString = inputField.text;
    // シーンを20190304_02に移動
    SceneManager.LoadScene("20190304_02");
    }
    }


    ボタンを押した時にOnClickButtonが呼ばれるようにしておきましょう。

    これで、InputFieldに文字を入力したものが、DeliverClassのdeliverStringに入り、次のシーンに持ち越すことができます。

    それでは、シーン2の方のコードも書いてみましょう。

    [Scene2.cs]
    using UnityEngine;
    using UnityEngine.SceneManagement;
    using UnityEngine.UI;

    public class Scene2 : MonoBehaviour
    {
    public Text txtString;

    private void Start() {
    // DeliverClassを取得
    DeliverClass deliver = FindObjectOfType<DeliverClass>();

    // DeliverClassから文字列を取得し、セット
    txtString.text = deliver.deliverString;
    }

    public void OnClickBackButton() {
    SceneManager.LoadScene("20190304_01");
    }
    }


    シーン2の方では、Startの中でDeliverClassから値を持ってきて、Textにセットすることをしています。

    実際に実行すると、DeliverのオブジェクトがDontDestroyOnLoadのところにあるのが確認できると思います。



    これが「シーンが変わっても消えないオブジェクト」になります。

    これで、シーン1のInputFieldの値をシーン2に引き渡すことができます。

    ってことで、簡単かつ基本的なことでしたが、誰かの役に立てば幸い・・・・
    あでゅ~ノシ

    Category: 開発日記(Unity)

    Thread: プログラミング

    Janre: コンピュータ

    Tag: Unity  ゲーム開発  C#  シーン  Scene  シーン間   
    tb 0 : cm 0   

    【ハルシオンブログ】タイルマップを使ってみた。意外と簡単にできるんすね。 

    こんにちは!坂内っす。
    もう次の日曜日にはデジゲー2018っすね!
    ブースの皆さん頑張って準備してくださいな!

    さてさて、本日のUnityのお話はタイルマップについて。
    Unity2017.2くらい?から導入されたタイルマップなんですが、今まで触ってもなかったので、ここで触ってみようかなと。

    タイルマップとは?
    タイル(英: tile)は、建設資材の一つで、壁や床の保護、あるいは装飾用に多数張りつける板状のもの。

    地図、マップ

    ってことで、ゲームの画面をタイルで並べるように作る機能のようです。

    さてさて、アセットストアにもいろいろとタイルマップで使えるマップチップのアセットがあるようです。
    今回はこれを使ってみました。



    まずはタイルパレットを作成します。
    あ、ちなみに使用しているUnityは2018.2.1です。バージョンによって多少コマンドの位置が変わるかも?



    Tile Paletteを選択するとウインドウが出てきます。

    出てきたウインドウの「Create New Palette」を押して、Nameにパレット名を入力し、「Create」を選択。


    そうすると、今付けた名前のパレットプレハブができます。


    次に使用するテクスチャを選択し、設定します。

    今回はこれを使ってみましょう。


    Bricksってファイルです。

    Sprite Modeを「Multiple」に変更します。
    Pixel Per Unitの数値をタイルのサイズにします。
    チップが16x16だった場合は16を入力します。(今回は32x32だったので、32を入力)


    そして「Sprite Editor」ボタンを押す!

    SpriteEditorの画面で「Slice」ボタンを押し、出てきたウインドウでTypeを「Grid By Size」へ変更。
    PixelSizeを32,32に設定し「Slice」ボタンを押す。




    テクスチャが32x32で白い線で切られると思います。

    これでウインドウの右上にあるxを押してApply。

    これで、テクスチャの準備は完了です。

    次に、今のBrickファイルをTilePaletteウインドウにドラッグ&ドロップします。



    これで完成です。

    次にタイルマップを画面に置いてみましょう。

    「GameObject」⇒「2D Object」⇒「Tilemap」を選択します。


    そうすると、Hierarchyに「Grid」というオブジェクトが作成されます。
    このGridを選択すると、Sceneウインドウに白い線が出るようになります。


    この状態で、TilePaletteで好きなチップを選択、クリックやドラッグでタイルを配置できます。



    Shift+ドラッグ(クリック)で削除できます。

    また、"「"ボタン、"」"ボタンを押すことでタイルを回転できます。

    さて、このままだとこうなっちゃいます。



    そうです。コライダーが付いていないのですり抜けちゃう!

    コライダーの付け方は簡単です。

    Hierarchyにある「Tilemap」に「TilemapCollider2D」を付けます。



    これでキャラがちゃんとぶつかるようになります。

    こんな感じ。


    簡単にTilemapって使えるんですね!
    今度何かにつかってみよう!

    ということで、今日はこれであでゅ~ノシ

    Category: 開発日記(Unity)

    Thread: プログラミング

    Janre: コンピュータ

    Tag: Unity  ゲーム  2Dゲーム  Sprite  ゲーム開発  タイルマップ 
    tb 0 : cm 0   

    【ハルシオンブログ】DoTweenのSequenceにOnCompleteつけてやりたいんだけど、うまくいかなかったんよ。結果できました! 

    こんにちは!くっそ暑い日が続いてますね!
    部屋から出たら死にそうになります。坂内です。

    さて、本日はDoTweenの話。
    DoTweenSequenceって皆さんお使いになられてますか?

    簡単に連続してTweenができる優れもの。

    例えば、こんな感じにImageを並べて



    こんな感じにコードを書けば。

    DoTweenTest.cs】
    using UnityEngine;
    using UnityEngine.UI;
    using DG.Tweening;

    public class DoTweenTest : MonoBehaviour {

    public Image[] tiles;

    private void Start() {
    Sequence tileSeq = DOTween.Sequence();
    tileSeq.Append(tiles[0].DOFade(0f, 2f));
    tileSeq.Append(tiles[1].DOFade(0f, 2f));
    tileSeq.Append(tiles[2].DOFade(0f, 2f));
    tileSeq.Play();
    }
    }


    こうなります。



    DoTweenのTweenスタート時、Tween終了時に処理を加えることができます。

    DoTweenTest.cs】
    using UnityEngine;
    using UnityEngine.UI;
    using DG.Tweening;

    public class DoTweenTest : MonoBehaviour {

    public Image[] tiles;

    private void Start() {
    Sequence tileSeq = DOTween.Sequence()
    .OnStart(() => {
    StartProc();
    });
    tileSeq.Append(tiles[0].DOFade(0f, 2f));
    tileSeq.Append(tiles[1].DOFade(0f, 2f));
    tileSeq.Append(tiles[2].DOFade(0f, 2f));
    tileSeq.Play();
    }

    void StartProc() {
    Debug.Log("はじまり");
    }

    void EndProc() {
    Debug.Log("終わり");
    }
    }


    OnStartはちゃんと入るのですが、OnCompleteを書こうとすると、エラーになって書けない…
    書き方がいけないのかな?


    ここじゃない?
    ここ?


    ここも違う?どこ?

    ここも違う!!

    こうなったら先生がゴロゴロしているツイッターにきいてやれ!

    で、先生がいうには。


    なんだって!?ヽ(゚Д゚;)ノ!!

    【DoTweenTest.cs】
    using UnityEngine;
    using UnityEngine.UI;
    using DG.Tweening;

    public class DoTweenTest : MonoBehaviour {

    public Image[] tiles;

    private void Start() {
    Sequence tileSeq = DOTween.Sequence();
    tileSeq.OnStart(() => StartProc());
    tileSeq.Append(tiles[0].DOFade(0f, 2f));
    tileSeq.Append(tiles[1].DOFade(0f, 2f));
    tileSeq.Append(tiles[2].DOFade(0f, 2f));
    tileSeq.OnComplete(() => EndProc());
    tileSeq.Play();
    }

    void StartProc() {
    Debug.Log("はじまり");
    }

    void EndProc() {
    Debug.Log("終わり");
    }
    }


    こんな書き方できるらしいっす。

    さすが先生。

    これで、シーケンス使ったDoTweenで、最初や最後に別関数を呼べますね!

    それでは今日はこれくらいでお暇します。

    あでゅ~ノシ

    Category: 開発日記(Unity)

    Tag: Unity  DoTween  Sequence  uGUI  ゲーム開発 
    tb 0 : cm 0