はりうすブログ (のすけのメモ)

湘南にある小さな会社 代表 ”のすけ”のブログです

【Unity道場5】衝突判定をせよ

問題1:衝突判定をせよ

キューブオブジェクトを上から落として、地面にぶつかった時にオブジェクトを削除してください。

回答例

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

public class CollisionTest : MonoBehaviour
{

    void OnCollisionEnter(Collision collision)
    {
            Destroy(gameObject);
            Debug.Log("当たったよ!");
    }
}

解説

OnCollisionEnterでイベントを検出して、オブジェクトを削除しています

実行結果

f:id:hollywis:20210215234005g:plain

問題2:衝突先のオブジェクトを削除せよ

問題1を改良します。

キューブオブジェクトを上から落として、地面にぶつかった時に地面オブジェクトの方を削除してください。

回答例

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

public class CollisionTest : MonoBehaviour
{
  void OnCollisionEnter(Collision collision)
  {
    Debug.Log("当たったよ!" + collision.gameObject.name);
    Destroy(collision.gameObject);

  }
}

解説

collision.gameObject

これで衝突先にgameObjectを取得できるので、それをDestroyします。

動作

地面に触れた瞬間に衝突して、地面が消えます

f:id:hollywis:20210216000553g:plain

【Unity道場4】マウスクリックを検出せよ

問題:マウスクリックを検出せよ

ゲームオブジェクトのマウスクリックを検出してログを出力してください。

回答例

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

public class PrefabDestroyer : MonoBehaviour, IPointerClickHandler
{
  // Start is called before the first frame update
  void Start()
  {

  }

  // Update is called once per frame
  void Update()
  {

  }

  public void OnPointerClick(PointerEventData pointerData)
  {
    Debug.Log(gameObject.name + " がクリックされました!");
  }

}

解説

マウスクリックを検出するためには、イベントシステムとカメラからのポインタークリックを検出します

f:id:hollywis:20210215231543p:plain

そのために、まずはインスペクタービューでカメラにPhysics Raycasterを設定します

そして、クリックを検出したいオブジェクトにスクリプトをセットします。

using UnityEngine.EventSystems;

イベントシステムのライブラリの利用宣言。

public class PrefabDestroyer : MonoBehaviour,  IPointerClickHandler

MonoBehaiviorの横に、IPointerClickHandlerを継承を記述します。


あとはOnPointerClick関数を定義して、クリックイベントを取得します。

public void OnPointerClick(PointerEventData pointerData)
  {
    Debug.Log(gameObject.name + " がクリックされました!");
  }

f:id:hollywis:20210215232154p:plain

【Unity道場3】ゲームオブジェクトを動的に生成せよ

こんにちは

Unityの書籍を何も考えずに言われるままにゲームを作っても

全く!!!覚えておらず


一向に手放しでゲームを作れるようになれる気がしないため始まった

Unity道場の3回目です。

問題1:ゲームオブジェクト動的に生成せよ

ゲームオブジェクト動的に生成するプログラムを書け。

動的生成するプレハブはInspectorビューから指定できるようにすること。

また出現位置をランダム化すること。

回答例

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

public class PrefabCreater : MonoBehaviour
{
  public GameObject prefab;

  void Start()
  {
    this.CreatePrefab();
  }

  void Update()
  {

  }

  void CreatePrefab()
  {
    float x = Random.Range(-5.0f, 5.0f);
    float y = Random.Range(0.0f, 5.0f);
    float z = Random.Range(-5.0f, 5.0f);

    GameObject new_prefab = Instantiate(
        prefab,
        new Vector3(x, y, z),
        Quaternion.identity
    );
  }
}

解説

最初のこの部分で、まずUnityのUIから動的に生成したいPrefabを指定してあげます。

public GameObject prefab;

こう記述することで、Inspectorビューから事前に生成するプレハブを指定できます。



そして、適当な名前の動的生成用の関数(CreatePrefab)を作ります.

void CreatePrefab()
  {
    float x = Random.Range(-5.0f, 5.0f);
    float y = Random.Range(0.0f, 5.0f);
    float z = Random.Range(-5.0f, 5.0f);

    GameObject new_prefab = Instantiate(
        prefab,
        new Vector3(x, y, z),
        Quaternion.identity
    );
  }

オブジェクトの動的な生成には、Instantiate関数を用います。

この関数は、プレハブからオブジェクトを生成する関数です。


Instantiate関数

  • 第1引数:動的生成するプレハブを指定
  • 第2引数:出現座標を指定(Vector3構造体)
  • 第3引数:回転方向を指定(Quatenion構造体)


問題では、ランダムな座標を指定する必要があるため、float型の数値,x,y,xをRandom.Range関数を用いて生成しています。

Random.Range関数の引数は範囲を示しており、xは-5~5, yは0~5, zは-5~5の間で乱数が取得できるようにしてみました。

Instantiate関数の第3引数で指定しているQuaternion.identityは回転しないという意味になります。

実行結果

こんな感じで、再生するたびにランダムに指定したプラハブがゲームオブジェクトとして出現します。

f:id:hollywis:20210215144338p:plain

f:id:hollywis:20210215144331p:plain
f:id:hollywis:20210215144326p:plain

問題2:動的生成したゲームオブジェクト削除せよ

問題1を拡張すること。

動的に生成したゲームオブジェクトが出現してから3秒後に削除するプログラムを書け。

回答例

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

public class PrefabCreater : MonoBehaviour
{
  public GameObject prefab;
  private GameObject new_prefab;

  // Start is called before the first frame update
  void Start()
  {
    this.CreatePrefab();
  }

  // Update is called once per frame
  void Update()
  {

  }

  void CreatePrefab()
  {
    float x = Random.Range(-5.0f, 5.0f);
    float y = Random.Range(0.0f, 5.0f);
    float z = Random.Range(-5.0f, 5.0f);

    new_prefab = Instantiate(
        prefab,
        new Vector3(x, y, z),
        Quaternion.identity
    );

    Invoke("DestroyPrefab", 3.0f);
  }

  void DestroyPrefab()
  {
    Destroy(new_prefab);
  }
}

解説

消すためにはグローバル変数に動的生成したオブジェクトを置いておく必要があるので、以下を追加

private GameObject new_prefab;

消すための関数を適当な名前(DestroyPrefab)で作ります

void DestroyPrefab()
  {
    Destroy(new_prefab);
  }
}

ゲームオブジェクト削除には、Destory関数を用います。

また、3秒後に消すために、メソッドを遅延実行させるInvoke関数を動的生成後に呼び出します。

Invoke("DestroyPrefab", 3.0f);

実行結果

3秒後に消えましたよと。

f:id:hollywis:20210215151306p:plain

Unity2020入門

Unity2020入門

【Unity道場2】ゲームオブジェクトを表示、非表示

ゲームオブジェクトを表示、非表示をやります

問題1:ゲームオブジェクトを非アクティブにせよ

ゲームオブジェクトを非アクティブにせよ

解答例

using UnityEngine;

public class Test : MonoBehaviour
{
  void Start()
  {
    this.gameObject.SetActive(false);
  }

  // Update is called once per frame
  void Update()
  {
  }
}
SetActive(false)

でアクティブ・非アクティブを切り替えられます。

ただ、一度非アクティブにしてしまうと検索に引っ掛からなくなったりといろいろ不便ですが。


Unity2020入門

Unity2020入門

【Unity道場1】座標を移動させる方法:問題文つき (Transformコンポーネント)

Unityの書籍を使っていくつかゲームを作った後に気付きました。


何も身についてねぇーーー!

本見ないと何にもできねxあーーー!


ということで、基本に立ち返って、ゲームを作る前にGameObjctの操作方法を

C#スクリプトレベルで覚え直すことにしました。


まず、1つ目!! Transformコンポーネント

問題1:ゲームオブジェクトのx座標を一定毎に増やせ

ゲームオブジェクトのx座標を一定毎に増やせ

解答例

using UnityEngine;

public class Test : MonoBehaviour
{
  Transform t;

  void Start()
  {
    t = this.gameObject.GetComponent<Transform>();
  }

  // Update is called once per frame
  void Update()
  {
    Vector3 pos = t.position;
    pos.x += 0.1f;
    t.position = pos;
  }
}

まず、取得したいゲームオブジェクトにこのTestスクリプトがAdd Componentされている前提です。

t = this.gameObject.GetComponent<Transform>();

この部分は、正確に書いたバージョンで、よく他の説明ページではより簡易的に

t = this.transform;

とか,さらにthisすら省略して

t = transform;

と書いている場合もありますが、こちらでもOK。だた、より内部構造を意識してプログラミングするなら前者の方がいいかと思います。


後、Update部の部分ですが

t.position.x += 0.1f

でもいいんじゃ。と思いがちですが、これだと動きません。

一度Vector3に入れて上げて、座標を修正し、元に戻すというような手順が必要

 Vector3 pos = t.position;
    pos.x += 0.1f;
    t.position = pos;

問題2:ゲームオブジェクトのx座標を軸に回転させよ

ゲームオブジェクトのx座標を軸に回転させよ

解答例

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

public class Test2 : MonoBehaviour
{
  Transform v;

  void Start()
  {
    v = this.gameObject.GetComponent<Transform>();
  }

  // Update is called once per frame
  void Update()
  {
    Quaternion rot = v.rotation;
    rot.x += 0.01f;
    v.rotation = rot;
  }
}


問題1との違いはVector3かQuaternionかの違いです。

あとはあんまり変わりません。


ちなみに、Quaternioは180が最大値なのでこのプログラムだと180まで行くと回転がとまります。

問題3:ゲームオブジェクトのx座標成分に大きさを変えよ!

ゲームオブジェクトのx座標成分に大きさを変えよ!

解答例

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

public class Test3 : MonoBehaviour
{
  Transform v;

  void Start()
  {
    v = this.gameObject.GetComponent<Transform>();
    Debug.Log(v);
  }

  // Update is called once per frame
  void Update()
  {
    Vector3 s = v.localScale;
    s.x += 0.01f;
    v.localScale = s;
  }
}


Unity2020入門

Unity2020入門

UnityのWebGLビルドしたファイルを読み込んでも進まない時

こちらに解決策がありました
note.com

Unity Editor 2020.1.4.f1の場合(圧縮)

Edit->Project Settings->Player ->(WebGL)Publishing Settings ->
Compression Format : gzip

Edit->Project Settings->Player ->(WebGL)Publishing Settings ->
Decompression fallback
にチェックを入れる


ありがとうございます!

Unityでのシーン間のデータの受け渡し方法6選

Unityで複数のシーン間でデータの受け渡しをする方法を調べました。

staticな変数に保持しておく

staticな変数に保存するのが、一番単純な方法です。シーンを跨いでも消えることはなく利用できます。

  public static int count = 0;

シングルトンを利用

staticな領域に値を保存する発展系として、シングルトンパターンを適用したクラスにデータを保存しておく方法もあります。

シングルトンとは、全体を通してインスタンスが一つになる性質がある物のことをさします。

シングルトンパターンの例

using System;

public sealed class ExClass
{
    private static ExClass c = new ExClass();

    private ExClass() // privateのコンストラクタ
    {
    }

    public static ExClass GetInstance()
    {
        return c;
    }
}

この場合は、MonoBehaiviorではなく、System.Objectを継承してクラスを実装

(非推奨)DontDestroyOnLoadを利用

MonoBehavioutのクラス内で利用できるDontDestroyOnLoad関数の引数にゲームオブジェクトのインスタンスを指定すると、そのゲームオボジェクトは明示的にDestroy関数を利用しない限りは削除されなくなる。

これにより、シーンの切替に関係なく、常に存在するゲームオブジェクトのコンポーネントにデータを保持しておくことができる。

ただしこの方法は2021年現在、既に非推奨らしいです。

こちらを参考:
Object-DontDestroyOnLoad - Unity スクリプトリファレンス

マルチシーンを利用

複数シーン編集によって、複数のシーンを同時にエディター上で開くことが可能になり、実行時でも簡単に複数シーンを管理できるようになりました。
これにより、破棄しないデータ保存用のシーンとコンポーネントを王位できるようになります。

DontDestroyOnLoadよりもより細かく独自の制御が可能ですが、管理や仕組みを構築するの難易度高め。

こちらを参考:
複数シーンの編集 - Unity マニュアル

ScriptableObjectを利用

DontDestroyOnLoad関数が非推奨なので公式では、こちらの方法を推しているようです。

構造としてはシングルトンパターンをよりスマートにしてUnityにフィットさせたような感じです。

チュートリアルは以下から

Achieve better Scene workflow with ScriptableObjectsScriptableObject を使ってシーンワークフローを改善しよう - Unity Technologies Blog


ストレージに値を保存

一旦、データをUnity外のファイルやデータベースなどに保存しておく方法です。ハイスコアやシステム設定など、端末に保存すべき簡単なデータであればこの方法が良いとのこと。


おすすめ書籍

Unityを学ぶ上でおすすめはこちらの書籍です。丁寧解説していてとても分かりやすかったです。