タグ別アーカイブ: Unity

[Unity]UnityとC#を学ぶ問題:007

第一問

前回作成したコードのUpdate関数も見やすくまとめましょう。

ヒント

if ( xxx ) return;
で以降を読まなくて済むやりかたが良いです。by readable code

答え(のひとつ)

if()returnを多用するようにし、ブロックを使わないことで見やすくしています。

第二問

SnakeHeadのスクリプトを編集して次の仕様を追加してください。

仕様

  • Head,Body,Tailを関係なく、cube -> sphere -> cube -> sphere … と交互にでてくるように変更してください。
  • その際、色は赤、青、緑、赤、青…と3色が順に出るようにしてください。

ColorSnakeBoxAndSphere from s2kw on Vimeo.

続きを読む

[Unity]UnityとC#を学ぶ問題:004

4日続きました。

第一問

ゲーム空間中に配置した球体を無限にバウンドさせ続けるようにコンポーネントを配置してください。

仕様

  • ゲーム空間にはPlaneがあります。
  • Planeは地面として使用するため動いていはいけません。
  • 同様に、ゲーム空間にはSphereがあります。
  • 再生ボタンを押下するとPlaneは移動せず、Sphereが落下し、地面に触れるとバウンドして元の高さかそれ以上の高さまで跳ね上がります。
  • これらはコードによる生成、Unityのシーン上で作成、どちらのやりかたでもかまいません。

ヒント

  • 落下にはRigidbodyを使用します。
  • 跳ねさせるにはPhysicMaterialを使用します。

続きを読む

[Unity]UnityとC#を学ぶ問題:002

二日目の問題を出題しました。
Unity本をやったことがある人が居たので後半は難易度が高いです。

第一問

マウスで画面をクリックすると、マウスでクリックした座標をConsoleに出力するようにしてください。

ヒント

  • Inputクラスを使ってマウスのクリックを取得します。
  • Debug.Log()でコンソールへの出力ができます。

第二問

マウスでクリックしたら、クリックした位置からワールド座標系における、カメラから10m離れたところにキューブを出現させてください。

仕様

当たり判定を取って、キューブの位置を決定します。

ヒント

  • Camera.main でカメラを取得できます。
  • ScreenPointToRayで画面座標からワールド座標へ座標変換されたRayを飛ばすことが出来ます。Rayとは光線みたいなものです。
  • 当たり判定は Collider 継承コンポーネントで取ることが出来ます。
  • PlaneやCubeなどのPrimitiveでCollider付きのGameObjectを予めゲーム空間に配置して、Rayの当たり判定を取れるようにしておきましょう。

続きを読む

[Unity]UnityとC#を学ぶ問題:001

取引先の若い人たち向けにUnityとC#でドリルをすることにしました。
c#を書けないスタッフ向け、という位置づけからスタートしています。
件のスタッフがUnityを使えるようになることを目標に、私自身の説明能力を高めるために、可能な限り細かく解説していこうと思います。

というわけで今日のお題と、追加仕様や仕様変更という形で応用を問題を用意しています。

第一問

UnityのHierarchy上で以下の状態を作ってください。

- Directional Light
- Main Camera
    - ここに駆動コンポーネントをアタッチします。名前は何でもOK。

- AAA0
    - BBB
        - CCC1
        - CCC2
        - ...
        - CCC10
- AAA1
    - BBB
        - CCC1
        - CCC2
        - ...
        - CCC10
...
- AAA10
    - BBB
        - CCC1
        - CCC2
        - ...
        - CCC10

仕様

  • AAAn と名前をつけたGameObjectにBBBが子として、CCCが孫として階層構造を持ちます。
  • AAAn CCCn は 1~10 の数字を割り当てます。
  • 1つのコンポーネントで上記を行います。
  • Unityの再生ボタンを押下して初めて結果がわかるようにします。

必要な知識

  • オブジェクトを new することを理解する必要があります。
  • for文、while文のいずれかを理解する必要があります。
  • GameObject の APIからnameプロパティの使い方を理解する必要があります。
  • Transform の API を理解し、親子構造を理解する必要があります。
  • ブロックとスコープの概念を理解する必要があります。

ヒント

解説

答えのソースコードはいずれアップしますが、大凡以下の解説を読めば動く形にはなるはずです。

続きを読む

[Unity3D][ImageEffect]Kino bloom filterを見る

高橋啓二朗(@_kzr)氏のKino Bloomフィルターの中身をみてみる。

Bloom

Bloom.csとshaderを行ったり来たりしながら見ていく。

void OnRenderImage(RenderTexture source, RenderTexture destination)

MonoBehaviour.OnRenderImage(RenderTexture,RenderTexture)

メインとなる関数。
第一引数がこれまでの結果。第二引数にこの関数で変更した内容を適用してあげなければならない。

適用はGraphics.Blitで行う。

    Graphics.Blit( source , dest );

続きを読む

[Unity3D]UPDATE()は遅いらしいし

  • UPDATE()を10000回呼ぶ
    Unityのオフィシャルブログの記事を見ていくつか気づいたこと、今後すべきことをメモしておく。

気づいたこと

  • Script Call Optimization を Fast but no Exceptions に変更 という作業で高速化できる
  • Updateは遅い

Script Call Optimization を Fast but no Exceptions に変更

Updateをまま使う場合、 Script call optimazation の項目を設定してあげる必要がある。

メニュー: Edit->Project Settings->Player

ここから設定が可能。

Updateは遅い

Updateやその他のマジックメソッドは、まずUnity側に登録されてその後GameObjectの存在チェックやNullチェック等を経て初めて呼び出される。
そのため、たとえ中身がカラだとしても void Update(){} と記述するだけで呼び出し対象にはなるし、上記のチェック等を経ているために処理の対象になり、少ないとはいえレイテンシーが発生する。

記事中では、この辺が必要無い場合、自前でManagerを作ってManagerのUpdate時に子に対して自前のUpdateを流す仕組みの方が高速であるとしている。
さらにListではなくArrayを使用したほうが効率的だとも述べられている。

自律制御のテストをしやすく子として呼ばれた時もよ動作させやすいやりかた

Manager側は一方的に呼び出すで良いとして、子側はMonobehaviour継承クラスだとしても void Update() 等を記述しない
自律テストをする場合は ChildDriver としてUpdate内で自身に着いた子用コンポーネントを自動取得して自前Updateを呼び出す仕組みにしてテストしたら良いと思われる。

具体的には

マネージャとして以下の様なコンポーネントでUpdate呼び出し。ブログまま。

    public abstract class Manager<ChildType> : MonoBehaviour
        where ChildType : IManagedMember
    {
        protected ChildType[] members;
        protected void Update(){
            int count = members.Length;
            for (var i = 0; i < count; i++) members[i].UnmmanagedUpdate();
        }
    }

呼び出される側はこんな感じでインターフェースを用意。

    public interface IManagedMember{
        void UnmmanagedUpdate();
    }
    public abstract class ManagedMember : MonoBehaviour,IManagedMember {
        public abstract void UnmmanagedUpdate();
    }

独立して子の挙動をテストしたいこ時は子にこれを追加してあげる。

    public class ManagedMemberDriver : MonoBehaviour {
        IManagedMember[] components;
        void Start () {
           this.components = GetComponents<IManagedMember>();
        }
        void Update () {
            int count = components.Length;
            for (var i = 0; i < count; i++) components[i].UnmmanagedUpdate();
        }
    }

あとは必要に応じてManager側には子作りメソッドを用意したりで色々できる。