カテゴリー別アーカイブ: 超訳

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

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

第一問

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

ヒント

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

第二問

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

仕様

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

ヒント

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

続きを読む

ミノタウロスまとめ

[wp_ad_camp_1]

ミノタウロスとは

スカイネット 立体パズル 4D VISION 動物解剖 No.03 牛解剖モデル

めずらしく企画業に通ずる内容をば。せっかく調べたのでメモ化。

まとめ

主にwikipedia::マラトーンの牡牛より。

  • ミノス王がポセイドンに要求して王権を保証してくれる牛をくれと願う。
  • ミノスは権力者になるが、牛をポセイドンに捧げるのを拒否する。
  • ポセイドンは怒ってミノス王の妻パーシパエーに呪いをかけ牛に欲情するようにする。
  • パーシパエー、ダイダロスに頼んで雌牛の模型を作り、クレタの牡牛とまぐわう。
  • パーシパエー、アステリオスを出産。のちのミノタウロス。
  • ミノス王、アステリオスを隠すためにダイダロスに迷宮建造を命令
  • ヘラクレスがエウリュテウスの命令で牡牛を捉えてエウリュテウスに見せた後に放逐する。
  • 放逐された牛がアテナイで暴れるのでミノス王の息子アポロドートスに捉える様に命ずるがアポロドートス死亡。
  • この牛はアテナイ王アイゲウスの息子テセウスが捉える。
  • ミノス王がアポロドートスの死に怒りアテナイを攻める。が、陥落はメガラーまで。
  • ミノス王、アテナイを落とせないのでゼウスに泣きつく。
  • ゼウスがアテナイを飢饉とか疫病にさらす。
  • アテナイ王アイゲウスが神託に従って7人の少年と7人の少女を毎年ミノス王に送る。
  • ミノス王は送られた14人の少年少女をミノタウロスの迷宮に生け贄として送る。
  • テセウスが生け贄システムに怒って生け贄に紛れ込む。
  • 出奔の際、船は悲しみの黒い帆を掲げる習慣だったが、アテナイ王アイゲウスはテセウスに帰ってくる時は白い帆で生存を知らせろと約束する。
  • テセウスはミノス王の娘アリアドネの助けで迷宮のミノタウロスを殺傷、迷宮から離脱、アリアドネと駆け落ちする。
  • テセウス帰還時に白い帆を掲げるのを忘れて黒いまま帰還。
  • アイゲウス王、黒い帆をみてテセウス死亡と勘違いして身投げ。
  • アイゲウス王の名にちなんでエーゲ海と名付けられる。

インセプション [DVD]

[C#]ListをRemoveAll( c => !c.MoveNext());する意味のまとめ

※いろいろと間違っていたのを修正。

数ヶ月前に参加したUnity仙人のセミナー、Unityで覚えるC#のサンプルで挙動がよくわからなかったもののまとめ。

サンプルは前述のスライドの56ページ。

ここで何が起こってるのかをまとめる。

まずListの言語仕様を整理

参考:http://www.atmarkit.co.jp/fdotnet/special/generics01/generics01_02.html

ListGenericClassは内容物の型を宣言する形式のArrayListクラス(のようなもの)。

Listという形で使用する。

ArrayListもListGenericも共に.Add()で内容を追加する。

この処理速度はListGenericの方が上。

理由はArrayListの場合はオブジェクトに変換するボックス化処理が挟まるから。

ジェネリッククラスの記述方法

参考:http://www.atmarkit.co.jp/fdotnet/special/generics01/generics01_03.html

山括弧内の型指定をTにすることで型を後付けにして汎用化できる。

ただ、複数の型を混在させる事が出来るわけではない。これをしたいのであればDictionaryClassを使用する。

Whereキーワード

型指定はTにしたいけれどもクラスであることは確実だったり、構造体であることが確実であったりと条件を幾分追加するキーワードで先の参考に示したページにその一覧が記述されている。

class MyGenericClass1 where T : struct {
  // 制約:Tは構造体
}

class MyGenericClass2 where T : class {
  // 制約:Tはクラス
}

class MyGenericClass3 where T : new() {
  // 制約:Tはインスタンス化可能
}

class MyGenericClass4 where T : MyOtherClass {
  // 制約:TはMyOtherClassクラスを継承
}

class MyGenericClass5 where T : IMyInterface {
  // 制約:TはIMyInterfaceインターフェイスを実装
}

class MyGenericClass6 where T : U {
  // 制約:Tは別の型パラメータUを継承
}

//////////////////////////////////////////////////
class MyOtherClass {
  // とあるクラス
}

interface IMyInterface {
  // とあるインターフェイス
}

また、複数の制約も可能ということなので試してみました。

class MyGenericClass where T:class,new()

こんな風にコロンで連結すれば良いです。

ゲームだと、出現したゴブリンとホフゴブリンとゴブリンアーチャー全員がゴブリンパンチ打てるよーって状況で全員がゴブリンパンチを採択するとかで使える。

例が限定的すぎるけれども。

ジェネリックに限らず、こういった書き方ができるのはC#の強み。

  public T this[int index] {
    get {
      return _list[index];
    }
    set {
      _list[index] = value;
    }
  }

で、ジェネリックについて整理したけどList型と必ずしも関連しないという事を注意したい。

List型はIEnumerableなのでforeachが使えるけれども、

前述した例だと独自実装なのでIEnumeratorを実装しておらず、foreachが使えない。

なんということでしょう・・・。

ListクラスのRemoveAllを理解する

RemoveAllメソッドは、特定の条件に一致する要素だけ削除する際に使用するメソッド。

RemoveAllの引数として、条件を判別するメソッドのハンドラ渡し、Trueが返る場合は削除を行う。

そこまでのサンプル。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class genericRemoveAll : MonoBehaviour {

     // Use this for initialization
     void Start () {
          List<orgString> stringList = new List<orgString>();

          for( int i =0 ; i < 10; i++){
               orgString tmp = new orgString( "string:"+i );
               stringList.Add( tmp );
          }

          stringList.RemoveAll( Method );
          foreach(orgString o in stringList)
          {
                o.Method();
          }

     }
     bool Method(orgString o){
          return o.str == "string:3";
     }
     // Update is called once per frame
     void Update () {

     }
     public class orgString{
          public string str;
          public orgString(string s){
               this.str = s;
          }
          public void Method()
          {
               Debug.Log("at method :"+this.str);
          }
     }
}

相変わらず起動確認はUnityで。

RemoveAllの中身をラムダ式にするとこうなる。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class genericRemoveAll : MonoBehaviour {

     // Use this for initialization
     void Start () {
          List<orgString> stringList = new List<orgString>();

          for( int i =0 ; i < 10; i++){
              orgString tmp = new orgString( "string:"+i );
              stringList.Add( tmp );
          }
          stringList.RemoveAll( s => s.str == "string:3" );
          foreach(orgString o in stringList)
          {
                o.Method();
          }

     }
     public class orgString{
          public string str;
          public orgString(string s){
               this.str = s;
          }
          public void Method()
          {
               Debug.Log("at method :"+this.str);
          }
     }
}

参考:http://www.atmarkit.co.jp/fdotnet/dotnettips/815listremove/listremove.html

ラムダ式をおさらい

ラムダ式はEventHandlerを省略したデリゲートをさらに省略した記述方式。

なのでラムダ式には左辺と右辺があり、左辺はdelegateとして呼び出されるメソッドのparameterが入り、右辺には式か文が入る。

左辺の記述は()にくくられていなければならないが、parameterが単一の場合は省略可能。

右辺の記述が式の場合、セミコロンで閉じない。

右辺の記述が文の場合、{ 文; 文; 文; }と記述し、{}にくくられていなければならないし、各文の最後に;が入ってなければ成らない。

(a, b) => {
a.transform.position = new Vector3( 0,0,0 );
b.transform.position = new Vector3( 1,1,1 );
}

また、以下の様な特徴もある。

http://d.hatena.ne.jp/seraphy/20120609

  • ラムダ式は括弧の外もスコープの対象。
  • スナップショットではなく、生きた参照。

まとめ

というわけで、RemoveAll()のparameterで記述されている件は…

列挙された内容をcというオブジェクトで代用し、MoveNext()が失敗する場合論理値を反転させTrueにし、RemoveAllの対象とする、という意味になる。

以下のサンプルが良い例になるだろうか。

         A a = new A ();
         a.Do ();
         a.Do ();
         a.Do ();
         a.Do ();
         a.Do ();

         public class A
         {
             List<IEnumerator> ien;
             public A ()
             {
                 this.ien = new List<IEnumerator>();
                 this.ien.Add (IenMethod1());
                 this.ien.Add (IenMethod2());
             }
             public void Do()
             {
                 this.ien.RemoveAll( c => !c.MoveNext() );
             }
             IEnumerator IenMethod1()
             {
                 Debug.Log ("befor1");
                 yield return null;
                 Debug.Log ("after1");
             }
             IEnumerator IenMethod2()
             {
                 Debug.Log ("befor2");
                 yield return null;
                 Debug.Log ("after2");
             }
         }

実行結果:

befor1
befor2
after1
after2

あーやっと終わった。スッキリ!

Unityの衝突処理最小構成

Unity教本の内容を整理。

最初は、gameObjectがどこからやってきたのかが分からなかったので理解するためにノートをまとめていた。そしたら変な方向に…。

原文

function OnCollisionEnter (collisionInfo : Collision) {
     if (collisionInfo.gameOnbect.tag == "Box"){
          Destroy(collisionInfo.gameObject);
     }
     Destroy(gameObject);
}

日本語訳

我に触れるものあれば即座に全うす。
  もし、当たる者の持つ遊戯物体が内に秘めたる”Box”と一致するならば全うす。
    死の呪文を触れた遊戯物体に喰らわせようぞ。
  さもなくばおわる
  死の呪文をば自ら喰らおうぞ。
これにて全うした。

死の呪文(Destroy()):オブジェクトをシーン上から破棄する効果がある。

おわり

良いよねこういう方向でも。

Unity入門 ~高機能ゲームエンジンによるマルチプラットフォーム開発~