Continue(s)

Twitter:@dn0t_ GitHub:@ogrew

【Unity】公式チュートリアル"Create with Code"をすすめる。

ちょうど1年前にこの講座でUnityにちゃんと入門した。

Udemy - ユニティちゃんが教える!初心者向けUnity講座

そのときはまさかこんな形でUnityエンジニアにジョブチェンジするとは思っていなかった。

ただこの講座で学んだことはすっかりどこにもメモが残されておらず、結局学んだこともほとんど記憶から消えてしまった。

もったいない。

当時のツイートが出てきた。そうだ、たしかに年越しをこれしながら過ごした記憶がある。

それにしてもSNSに動画を上げている余裕があるならやったことのメモくらいブログなりに残しておいてほしいものだ。

単純なゲームだったがエッセンスがつまっていた(ように思う)のでとりあえずなにか始めたい人におすすめしたい。

さて、次の仕事まで暇な時間ができたので今回のUnity入門は公式のチュートリアルを始めることにした。

この中から探した。

どれがいいとかわからにので一番購読されていそうな「Create with Code」を始めた。 40時間近いコースとなっているが、コードがある程度書ける人ならその半分ちょいで一周できると思われる。 f:id:taiga006:20191215222703p:plain

…と言ってもまだ完走していないのだが…。

まあ、気長に続けていこう。


2020.01.09 終わらせた。 f:id:taiga006:20200110001819g:plain


やったらメモ残す。

①障害物のある道路を車を操作して進むだけのゲーム
- public変数はInspector上から操作できる
- Vector3.forward -> (0,0,1) みたいな便利なのか何なのかわからないメソッドがある
- ゲームなどのインプット機構はプロジェクトごとに変更できる
- Edit -> Project Settings Input他、プロジェクトに関する設定を変更できる
- Scene Viewの視点操作が癖がある、といってもBlenderやTDから入ったからそう感じるだけだと思う
-Input.GetAxis("Horizontal")などでそのプロジェクトで設定されたHorizontalのキーの値を-1~+1の間で取得できる

f:id:taiga006:20191208171201p:plain

②動物版インベーダー
- オブジェクトの消失はDestroy(gameObject)で簡単にできる
- Random.Range(int min, int max) はmin≦x<maxとなる
- PrefabsはHierarchy上のオブジェクトをProjectにD&Dで作成できる(インスタンスからクラスのデータを吐き出す、みたいなイメージかな?)
- カメラの投影方法はCamera->ProjectionからOrthographic(正投影) or Perspective(遠近投影)が選べる
- InvokeRepeatingは指定秒数後に発火させる(そして繰り返す)ことができる(=コルーチンに近い仕組み?)
- オブジェクトの設定を更新したときPrefabにあるものに関してはOverridesで適用するか破棄するか選ぶことができる(クラスの情報を更新する感じ)
- GetKey => 連続的なキー選択、GetKeyDown => 瞬間的なキー選択 を検知できる

f:id:taiga006:20191209230113p:plain

③横スクロールジャンプゲーム(サウンド&エフェクト付き)
- GetComponent<name> で名前空間or型がnameのコンポーネントを取得
- unity内の物理についてはUnityEngine.Physicsで操作可能
- RigidBody(=物理演算を受けるコンポーネント)のConstraintsで位置や向きを任意に固定できる
- Collider(=衝突判定に使うコンポーネント)この2つはBlenderでおなじみ
- objectにtag付けできる
- tagの比較はgameObject.CompareTagで可能
- scriptもコンポーネントなので他スクリプトから呼び出すことができる
- ただしその中でpublic変数のみが呼び出せることに注意
- Animatorを使うとノードベースの条件分岐でアニメーションを切り替えられる
- ノードの矢印を押すとその状態遷移の条件がわかるのでそれをスクリプト上で操作すれば良い(SetTrigger(), SetBool(), SetInt() etc...)
- エフェクトを管理する一つのクラスにParticleSystemがある(コンポーネントではないっぽい。)
- ゲームのBGMはカメラに当てる。(Audio Sourceコンポーネント)
- scriptから音楽をいじる場合はAudioClipで音源自体を管理、AudioSourceで再生を管理

f:id:taiga006:20191215215010p:plain

④
- child object 親の状態に左右される(今回ではカメラの回転)
- local座標でのtransformとglobal座標でのそれをうまく使い分ける
- Physical MaterialはGameObject同士の衝突時の跳ね返り等について管理するコンポーネント、コライダのMaterialとして設定する
- OnTriggerEnter -> 接触&通過を検知(ColliderのIsTriggerをONにしておけばOK)
- OnCollisionEnter -> 接触&衝突を検知(衝突物、対象物ともにColliderとRigidbodyを持つ.)
- 動くもの同士の衝突判定=> Collision系
- どちらかが動かない衝突判定=> Trigger系
- StartCoroutine(Method()) -> IEnumerator() { yeild return WaitForSeconds(N); ....}; でN秒後に次の処理を発火させることができる(コルーチン)
- FindObjectsOfType<XXX> でXXX型の(アクティブな)オブジェクトをすべて取得できる.指定しなければすべてのオブジェクトを取得する.

f:id:taiga006:20200108233344p:plain

⑤
- 関数の宣言時に何も書かなければすべてprivateになる
- Array(List)クラスとList<T>クラスは似たような使い方ができるが、前者の要素は型に縛られないのに対して後者は<T>の型しか取らない。よって前者は取り出すときにチェック、キャストをしなければならない。(Listのほうが使い勝手が良い。)
- GameManager Scriptとかはよく使うので勝手にアイコンがGearのものになる。他にもあるのかな。特に便利には感じない。
- SceneManagerのライブラリを使うことでシーンの再読み込みなどが可能。
- Empty Objectのchildに複数のObjectをグルーピングさせてSetActiveさせると楽。

f:id:taiga006:20200108232951p:plain

Declarative Pipelineでビルドパイプラインをコード管理する.

Jenkinsで複数のジョブ実行をパイプライン化させる際に、メンテナンス性を考えてPipeline as Codeさせることにしました。 (Pipeline as Codeって普通に書きましたが、ググるとJenkinsの話しか出てきません。)

JenkinsでPipeline as Codeさせるのには専用のDSLが存在し、それを使ってJenkinsfileを書くことができます。ただし気をつけなければいけないのはこれには2つの記法が存在していて、一つは初期のScripted Pipelineというもので、こちらは現在は使用が推奨されていません(とはいえケースバイケースのようですが)。

ただ、インターネットに転がっている適当なスクリプトを「自分のところでもだいたい用法同じだから!」ってコピペして使おうとすると結構な割合でこちらの古い構文のものにぶちあたるので注意が必要です。(私はそうなりました。)

ということで今回は新しいほう(といっても3年ほど前に出た)のDeclarative Pipelineで単純なサンプルを書きました。

pipeline {
    agent any // どのノードで実行するか決める
    environment { // 環境変数をセットする
        workspace = "/path/to/jenkins/workspace"
        export_dir = "/path/to/jenkins/export"
    }
    stages {
        stage('build') {
            steps {
                echo 'Start Build'
                build job: 'build'
                echo 'Finish Build'
            }
        }
        stage('backup') {
            steps {
                echo 'Start Backup'
                build job: 'backup'
                echo 'Finish Backup'
            }
        }
        stage('test') { // test1 とtest2 は並列で実行される
            parallel { // stageの下で宣言
                stage('test1') {
                    sh './do_test1.sh'
                    sleep 5
                }
                stage('test2') {
                    sh './do_test2.sh'
                    sleep 5
                }
            }
        }
        stage('deploy') {
            steps {
                 echo 'Start Deploy'
                build job: 'deploy'
                 echo 'Finish Deploy'
            }
        }
    }
    post {
        always {
            echo '<--------all process has done.-------->'
            deleteDir() // 事後はワークスペースをきれいにする
        }
        success {
            echo 'SUCCESS :)'
            slackSend   channel: '#notifiy',
                        color: 'good',
                        message: "ビルドが完了したよ :smiley:"
        }
        unstable {
            echo 'UNSTABLE :\'
            slackSend   channel: '#notifiy',
                        color: 'warning',
                        message: "ビルドが終わらなかったよ :thinking_face:"
        }
        failure {
            echo 'FAILED :('
            slackSend   channel: '#notifiy',
                        color: 'danger',
                        message: "ビルドが失敗したよ :zany_face:"
        }
    }
}

f:id:taiga006:20200108191048p:plain こんな感じでどのタスクにどれくらい時間がかかっているかなどを可視化できます。 f:id:taiga006:20200108191212p:plain Slackにもちゃんとメッセージが送られています。

※とはいえ、上のはあくまでサンプルです。ビルドどうこう言ってるのに'Finish Deploy'とか書いてます。変にコピペしないでね。

仮にJenkinsをわかっていなくてもおおよそこのスクリプトによってどのような手順で処理が進むのかわかると思います。 ちなみにslackSendコマンドはSlack NotificationというPluginを入れて設定すれば使用できます。bot_userを使うようにすればカスタマイズ性も高まります。(もちろん、他に設定でメールなども送れます。)

上でScripted PipelineのサンプルとDeclarative Pipelineのサンプルを勘違いするなよー、って書きましたが、見分け方は簡単でblockのトップがnode or pipeline かで見分けられます。(さらにpararell対応する前か後かみたいなのもあるようですが…)

参考

jenkins.io

www.blazemeter.com

cocodrips.hateblo.jp

b-side.work