3DCG覚書とかとか

参考書のすみっこ

~普段メモとかしても忘れちゃうのでブログにしました~

目指せUnityマスター[1週目]

Q.何この記事?
A.新卒Webエンジニアが、Unityマスターになるまでの過程を描いていく記事です。何週間続くか見ものですね。
今回の目玉は、privateでPrefabをロードしてInstantiateする事かな?

Unityは数年前に数カ月経験済みでC#は復習済みなので、全く知らないわけではないです。
C#復習場所↓

csharp.sevendays-study.com

今週やったこと

Create with Code

learn.unity.com

ここ↑にあるUnity公式チュートリアルを使って勉強してた。
これ見ないと、何書いてるかわからんと思う。から、ほぼ備忘録だねこれ。

全部英語で若干ひるんだけど、簡単なものしかないしむしろ用語の勉強になっていい感じ。あと、Unitごとに出てくるおっちゃん感じよくて好き。

Unit1 - Player Control

このUnitでは、車走らせたり障害物ぶっ飛ばしたりした。

ゴール

車オブジェクトにコンポネント(C#Script、RigitBody)くっつけて動かして、キー入力で走らせたり回転させたりできるようになること。

※Colliderはチュートリアルアセットに最初からついてた。

Lesson1.1 Start your 3D Engines

ここではプロジェクト作ってアセット読み込んで、あとUI覚えてTransformいじくるだけ。

Lesson1.2 Pedal to the Metal

ここでC#Scriptを追加し始める。UtniyでのC#の簡単な書き方と、車を前に進める方法を学習する。

void Update()
{
    transform.Translate(Vector3.forward * Time.deltaTime * speed);
}

なんでdeltaTimeが必要なのかというと、UnityのUpdate関数はフレームが固定されてなくて、1フレーム辺りの秒数が変わるから。deltaTimeが無いとFPS(Frame Per Second)によって速度が変わってしまう。気持ち悪すぎる。

あとついでに、Vector3.〇〇も調べておいた。

Vector3.forward   // new Vector3(0,0,1)のこと。z軸方向
Vector3.right     // new Vector3(1,0,0)のこと。x軸方向
Vector3.up        // new Vector3(0,1,0)のこと。y軸方向

これだけわかってれば基本困らなそう。

Lesson1.3 High Speed Chase

ここではソースコードを変数使って綺麗にしたり、カメラを車オブジェクトに追従させたりした。
本編ではpublic gameObjectでInspectorからオブジェクトを代入してたけど、↓みたいにprivateでも適用できた。

private GameObject gameObject;
void Start()
{
    gameObject = GameObject.Find("オブジェクト名")
}

気を付けないといけないのが、アクティブなオブジェクトのみ返すと記載されていたので、シーンに生成されてないPrefabのままのオブジェクトとかは読み込めない。だからPrefabは↓みたいに適用するっぽい。
※必ずResourcesフォルダを作る必要がある。Resourcesフォルダに入れ子でフォルダを作ったりしたら、"Box"のところを"フォルダ名/Box"というようにパス指定すればよい。

void Start () 
{
    // ResourcesフォルダからBoxプレハブを読み込み
    box = Resources.Load("Box") as GameObject;
}

Lesson1.4 Step into the Driver's Seat

ここではキー入力を使って車を前進/回転させる。あとEmptyオブジェクトの使い方として、複製した障害物をまとめるのに使ってた。

RotateもVector3で指定できるんだな~と思ってたけど、x,y,z軸で指定するんだから当たり前か、と納得した。
ちなみにRotateは度数法で指定するようで、ちょっと不思議な感じがしたが親しみやすくて良いと思った。

あと回転角を指定する方法にQuaternionがあるようで、これは4軸で回転を表す。具体的には、

Quaternion.AngleAxis(w,new Vector3(x,y,z));

というように指定して、x,y,zの合成ベクトルの方向を軸にして、wに時計回りに回転させるというもの。複雑な方向への回転はこっちのほうが指定しやすそうだけど、まだ使う場面には遭遇してないかな。他にもいろんなQuaternionがあったから、使う機会があればメモしとこう。

Challenge 1 Plane Programming

飛行機オブジェクトを使って、糸通しみたいなゲームを作るチャレンジ課題。 特に難しいところもなかったが、それゆえにプロペラの回転とか機体が動くときにモーションブラーとかかけて凝ってみたくなって、少し調べた。

そしてこの記事にたどり着いた↓

ekulabo.com

どうやらポストプロセシングなる技術を使うらしい。
カメラとポストプロセシングをかけたいシーンの一部分に専用のコンポネントを追加して、あとはパラメータをちょっといじるだけ。といっても光源を用意したり、大きめのオブジェクトを振り回したりしないとあまり映えないことが分かった。

Unit2 - Basic Gameplay

このUnitでは、簡単なシューティングゲームを作った。

ゴール

オブジェクト移動範囲の制限、PrefabのInstantiate(複製)、オブジェクトのCollider/Trigger(衝突判定)、ランダム関数を使いこなせるようになること。

Lesson2.1 Player Positioning

プレイヤーの移動を制限するだけ。この時Translateで戻したりするとガタガタして気持ち悪いので、↓のように書いた。

//-20≦x≦20の範囲制限
private xPositionRange = 20
if(Math.Abs(transform.position.x) > xPositionRange){
    transform.position = transform.position.x > 0 ? new Vector(xPositionRange,0,0) : new Vector(-xPositionRange,0,0);
}

三項演算子は何気自分で書いたのは初めてだったけど、絶対値使って範囲制限したときすっきりかけそうだったので、試してみたらうまくいった。あとnew使わなくてもVector.right * xPositionRangeでもできると思う。

まぁでもこれif文2重になってるからあんまりよくないかも。

Lesson2.2 Food Flight

ここでは弾丸(Food)をPrefab化して、キー入力でInstantiate(複製)して後は前に進むScript通りに動く。弾が画面外に出たら消すのを忘れないこと。それ以外は特にないかな?

Lesson2.3 Random Animal Stampede

ここでは↓のように、一定時間でメソッドを繰り返すメソッドを学んだ。なんかメソッド名を文字列で渡すの気持ち悪いな...。あ、Invokeは"呼び出す"という意味。

private float startDelay = 5.0f;
private float interval = 3.0f
InvokeRepeating("メソッド名",startDelay/*(s)*/,interval/*(s)*/);

あとは敵オブジェクトの生成位置や種類を乱数で決めた。

この時気になったのは乱数の範囲についてで、↓のようになる。

Random.Range(-10.0f,10.0f)    //これは-10≦x≦10
Random.Range(0,10)            //これは0≦x<10(0≦x≦9)

どうやら、intを引数にする時は最大値は含めないらしい。これは配列を使うことを想定しているのかな。
あくまで個人の意見だけど、これは配列が0から始まる事をきちんと学ぶであろう初心者には、かえってわかりづらい仕様じゃないかなと思う。実際自分も一度間違えた。

Lesson2.4 Collision Decisions

ここでは関数を分けてScriptを整理したり、ゲームオーバー時の処理を書いたりして仕上げをした。

ColliderとTriggerについて、オブジェクトが衝突するときのふるまいを今一度復習すると、

  1. 互いのオブジェクトにCollider/Triggerが追加されていて、どちらかにRigidBadyが追加されていることで衝突判定が行われる。
  2. 両方のオブジェクトがColliderの場合、衝突時に干渉しあう。
  3. 片方のオブジェクトがTriggerの場合、衝突時にすり抜ける。

参考にした記事↓

kimama-up.net

汎用性が高いからか若干複雑に感じていたけど、参考記事でストンと理解することができた。先人は偉大だな。

Challenge2 Play Fetch

このチャレンジでは、上からランダムな位置/サイズで落ちてくるボールオブジェクトを、キー入力で犬を走らせてキャッチするゲームを作る。

ちょっと大事だなと思ったことは、まず最初の時点で回転しているオブジェクトの、Vector.forwardの向きだったかな。

例えば、
gameObject.transform.rotationが(0,90,0)の場合

gameObject.transform.translate(Vector.forward)
は相対座標上の向きはz軸方向だけど、絶対座標上の向きはx軸方向になる。
※Unityは左手座標系

他には、↓みたいにやるとランダムにオブジェクトの複製ができたり、

private float delay = 5.0f;
void Start()
{
    Invoke("メソッド名",delay/*(s)*/);
}
void メソッド名()
{
    //この辺に適当な処理を記述

    Invoke("自メソッド名",Random.Range(1.0f,5.0f);
}

↓みたいにやると入力遅延を実装できたりした。

private float startTime;
private float delay;
void Start()
{
    startTime = TIme.time //float型で、単位は秒(s)。今の時間を持つ。
}
void Update()
{
    if(Input.GetKeyDown(KeyCode.〇〇)){
        if((Time.time - startTime) > delay){
            Instantiate(gameObject,position,rotation);
        }
    }
}

振り返り

最初の週はこんなもんかな~って感じだった。

前Unity使ってたときは、C#どころかオブジェクト指向という概念すらうろ覚えでUnity使ってたから、関数とかその都度調べてたり、なんでそう動くのかよくわからなかったりしてた。
でも今になって1から勉強してみると、今まで見えてなかった深いところまで見えてきて、これはこれで新しい発見があって楽しい。

あと仕事ではJavaPHP使ってるから、それぞれのコーディング規約ちゃんと覚えとかないとゴチャゴチャになりそう(-_-;)

てか1週間分の振り返りって結構重たいな...2時間ぐらいかかっちまった。
だからちょっとブログの頻度を上げるか、密度を下げるかしようと思う。

皆さん今週もお疲れ様です( ´_ゝ`)