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

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

【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を学ぶ上でおすすめはこちらの書籍です。丁寧解説していてとても分かりやすかったです。

【コードが織りなす複雑系な世界】UnityのコーディングとWebのコーディングの違い

こんにちは、のすけです。

Unity(ユニティ)デビューして2ヶ月くらい。

作った物は2つくらいですが。


だんだんWebのコーディングとUnityコーディング(ゲームコーディング)の違いが分かってきたのでメモ

Unityとは?

誰でも作れるゲーム!とゲームの民主化をはかった最強のゲーム制作ツール。

それがUnity。(主観入ってます)

f:id:hollywis:20210122154352j:plain

youtu.be


HTML的なコードはない!

Unityは全て、GUI(グラフィカルユーザインタフェース)で作っていく。


ゆえに、使うのはキーボードというよりかは[マウス]や[トラックパッド]。

なので、全体の構成を記述するHTML的な物はなく


[Sceneビュー]と呼ばれる3D空間ないしは2D空間上に配置される。

f:id:hollywis:20210122141646p:plain


だから、このキャラクターも、Sceneビュー上にマウスで配置した。

ただ、x,y,zの絶対座標はあるので、キーボード入力で位置を微調整できる。



HTMLを積み上げ的に書くのではなく

position:absoluteを使いまくって実装していた人は

Unityでも近い感覚で作ることができる。(relative的な相対座標はおそらく無いっぽい)

そこに表示されているのは全部GameObject!!

[Sceneビュー]上に表示されている物は全て[GameObject]という型で定義されている。


Webでいうならば全てDivみたいな感じだ。(DOMと言ってもいいかもしれない)

だから、、、

キャラクターもGameObject

四角い箱もGameObject

地面もGameObject

光源(太陽的な)もGameObject


さらには、我々が見ている、この世界を覗き込む[カメラ]ですらGameObject



GameObjectには[座標と大きさ]などだけがある。


そこに様々な機能をAddComponet(コンポーネントを追加)していくことで、あらゆるものに変身できる

f:id:hollywis:20210122142951p:plain


この箱は、ただのGameObjectに

[箱型のメッシュ]と[箱型のメッシュレンダラー]、そして[箱型のマテリアル]の3つを付与することで表現できる。


コンポーネントを切り替えることで、箱にも球体にも、ボタンにも、光にもなれる。

メッシュという三角形の集合体

あらゆるGameObjectにはメッシュやマテリアルを設定できる。


メッシュとは言わば装飾だ。

メッシュがあるから、僕らはそこに物があると認識できる。


厳密にいうとメッシュとは三角形(ポリゴン)の集合体だ。

f:id:hollywis:20210122143805p:plain


例えば、この箱は六面体だが、1つの面に対して2つの三角形(ポリゴン)を使っている。

だから、三角形の数(ポリゴン数)は面の2倍なので12個だ。

マテリアルはCSSっぽい

Webの世界でボタンに色をつけたりするときCSSを使うと思う。

画像を貼り付けるときは、backgroud-colorなんかを使うよね。


じゃあUnityはどうするのか?


答え:マテリアルを使う


f:id:hollywis:20210122144155p:plain


マテリアルとは質感を表現するモノだ。

メッシュ(ポリゴンの集合体)に色を塗りたくるか、画像を貼り付けることができる。


こんな感じで、マテリアルをただの箱に貼り付けるだけで、様々なオブジェクトに擬態できる。

コーディングは生態系??

ほとんどマウスでできちゃうなら、Unityでコーディング不要では?

いやいや、もちろんある。


Unityのコーディングは基本的には GameObjectに対して行う


重要なのでもう一度言うけれど


Unityのコーディングは基本的には GameObjectに対して行う

のだ。



これはちょっとビックリした。


f:id:hollywis:20210122144941p:plain


こんな感じでコードすらGameObjectにAddComponet(コンポーネントを追加)していく。

この画像で言えば[BoxScript]がそれだ。


だから例えば、何かにぶつかった時に消えるとか。大きくなるとか。のコードはその箱のGameObjectに対して行う。


f:id:hollywis:20210122151018p:plain


何だかめんどくさそうに思えるけれど。

これはこれでコードがスパゲッティのようにグチャグチャしなくていいと思う。


JavaScriptで言うところのAddEventListenerで全て書いていく感じに近いと思う。

ボタンをクリックしたらevent発動!的なあれだ。



だから、全ての挙動を管理する巨大なコードがあるわけではなく。

複数のGameObjectに紐づくコードが織りなす複雑系な世界がUnityだ。


それは渡り鳥やの飛び方やイワシの群れに似ている。


渡り鳥の群れ全体を管理しているモノはいないが、個々の一羽一羽は独立した機能(法則・ルール・意思)を持っているだけ

でも全体としては意思があるような群れの生態系を描いて、効率的に島から島へと渡っていく。


だから、Unityのゲーム画面は常に生きている。

そこにはルールがあるだけで、精密な管理はない。二度と同じ画面には出会えないのだ。


UnityにおいてはGameObjectに如何に美しい(法則・ルール・意思)を持たせるかがコーダーの腕の見せ所だと思う。


Webはどちらかと言うと全体管理を徹底しているため、この点の思想が全然違うと思う。


ちなみにコードは全てC#という言語で書いていく。


所詮はデビュー2ヶ月の妄想かもしれないけれど、Web歴は相当長いのでこの点が感動ポイントだった。

UnityでもWebで出力できる

こんがらがって来るんだけど、実は

この複雑系な生態系であるUnityはWeb上でも表現できる。

こんな感じでブラウザ(Safari)で実行してみた。

f:id:hollywis:20210122151909j:plain


しかも、WebAssembly(ウェブアセンブリ)というブラウザからアセンブリ機械語)を実行できるようにする最新技術でコンパイルされるらしい!?から、実行速度も結構早い。


全部Javascriptで作るよりUnity使っちゃえ!とも言えるかな。

Webでできる、その他もろもろはできるのかな?

もちろんサーバーと通信できるし

  • 内部ブラウザでWeb画面を表示
  • 画像表示
  • 音声再生
  • 動画再生
  • データベース接続


なんかもできるのでWebでできることは大体全部できる。


ただ、C#で実装するので、C#のライブラリがないAPIなんかは利用しにくいけれど。

ゲームエンジンなのでPS4でも実行できるらしい

Unityで作ったモノはあらゆるプラットフォームで実行できる。


Webは紹介したけれど、Unityはゲームエンジンなので、iOSAndroidWindows, Mac, Linux,さらにはPS4やXboxOneなんかにも出力できるそうだ。

f:id:hollywis:20210122153541p:plain


そして、今後でるあらゆるデバイスもサポートするのではと思う。


正直、ビルドしたファイル群をどうやてPS4で実行するかは謎だけど、夢が広がるね。

終わりに: ゲームエンジンってつまり現実世界の物理シミュレーションってことは・・・

ゲームエンジンって、つまりは現実の世界の法則をシミュレーションしているってことなので、

つまりは、現実世界の諸法則を画面上で表現するための、地球における現在の最適解なんだよね。


という事は、記号表現においてはUnityの思想は全てを包含するわけで。。。


UnityやばしとWebエンジニアののすけは感じたのでした。


でもね。一番大事なのは、Unityでも表現し切れないあなたのその体!

それでは、また!