スマートデバイスプログラミング 第7回
ネットワーク機能を使ってみよう

k07_web.zip(サーバに置くファイル群)

課題

(1)通信により、画像を取得して表示してみましょう。 (2)パラメータを送信してみましょう。 (3)簡単なクリックゲームを作って、スコアを送信できるようにしてみましょう。 (4)その他、プログラムを改良したり、学んだ技術を駆使して、何か面白いことをやってみましょう。
作ったC#のプログラムを添付してください。
(プロジェクトを保存したフォルダのasset以下にあると思います。
コメント欄には、どこまでやったかと、(3)のハイスコア書いてください。

  1. 新規プロジェクトを作る(「2D」プロジェクトを選びましょう)
  2. スクリプトを貼りつける、空のゲームオブジェクトを作りましょう
  3. 表示用のイメージを作りましょう(GameObject→UI→Image)
  4. 座標はx0,y0にしましょう。サイズはそのまま(w100h100)。
  5. スコア表示用のテキストを作りましょう(GameObject→UI→Text)
  6. 座標はx0,y0にしましょう。サイズはそのまま(w160h30)。
  7. 通信結果表示用のテキストを作りましょう(GameObject→UI→Text)
  8. 座標はx0,y0,サイズはw300,h300にしましょう
  9. 新規スクリプトを作成しましょう。名前はGameManagerで。
  10. スクリプトを編集しましょう。
    
    //3行目に追加
    using UnityEngine.UI;
    
    //class名が違っていたら上書き
    public class GameManager : MonoBehaviour {
    
    //入ってすぐのところに
    public Image image;
    
    //Start内を下記に
    void Start () {
      // コルーチンを開始する
      IEnumerator coroutine = LoadImage("http://web.sfc.keio.ac.jp/~wadari/sdp/k07_web/Player.png");
      StartCoroutine(coroutine);
    }
    
    //Classが終わる直前にメソッドを追加
    IEnumerator LoadImage(string url)
    {
      // WWWインスタンスを作成する
      WWW loader = new WWW(url);
    
      // ダウンロードが終わるまで待つ
      yield return loader;
    
      // 結果を処理する
      if (!string.IsNullOrEmpty(loader.error)) {
        // エラーがあった場合
        print("WWW Error");
      }
      else
      {
        // 正常にダウンロードを終えた場合
        // テクスチャ画像として貼る
        Texture2D tex = loader.texture;
        Rect rect = new Rect(0, 0, tex.width, tex.height);
        Vector2 pivot = new Vector2(0.5f, 0.5f);
        image.sprite = Sprite.Create(tex, rect, pivot);
      }
    }
    
  11. GameObjectにスクリプトをaddComponentして、imageの欄に作ったImageをドラッグ&ドロップしましょう。
  12. UnityRemoteの設定をしましょう。Edit→ProjectSetting→EditorでDeviceの項目を変更します。
  13. 端末をUSBケーブルでつないでunityRemote4を起動
  14. アプリを実行してみましょう。
  15. 最初は白い画像ですが、暫く待つとPlayerが表示されます。
  16. (web上からダウンロードして表示しています)
  17. うまく動かない時は、端末を再接続、再起動、Unityの再接続、再起度を試みましょう。(Scene名はTouchGameとして保存しておきましょう)
  1. 次に、スコア送信を試してみましょう。
  2. ボタンを追加します。(GameObject→UI→Button)
  3. ボタンの名前はSendScoreなどに変えましょう(Buttonに付いているtextを編集)
  4. Scriptを再度編集します。
  5. 
    //変数の宣言を追加
    public Text webt;
    public Text t;
    int score=0;
    string pname="nanashi";
    float time= 20.0f;
    
    //Classが終わる前に、ボタンを押した時のメソッドを追加
    public void sendScore ()
    {
      // コルーチンを開始する
      string send_url = "http://web.sfc.keio.ac.jp/~wadari/sdp/k07_web/score.cgi?score="+score+"&name="+pname;
      IEnumerator coroutine = LoadText(send_url);
      StartCoroutine(coroutine);
    }
    
    //Classが終わる前に、通信して結果をテキストに格納するメソッドを追加
    IEnumerator LoadText(string url)
    {
      // WWWインスタンスを作成する
      WWW loader = new WWW(url);
    
      // ダウンロードが終わるまで待つ
      yield return loader;
    
      // 結果を処理する
      if (!string.IsNullOrEmpty(loader.error))
      {
        // エラーがあった場合
        print("WWW Error");
      }
      else
      {
        // 正常にダウンロードを終えた場合			
        webt.text = loader.text;
      }
    }
    
    
  6. 保存して、tの欄にスコア表示用テキストをとwebtの欄に通信結果表示用のテキストをドラッグ&ドロップしましょう。
  7. ボタンのヒエラルキービューで、ボタンを押された時に呼び出されるメソッドを指定しましょう。(具体的な操作は次の項目から)
  8. OnClickの欄の+を押します。
  9. Runtimeの下の「None」選んで「GameObject」を選択(Sceneから選んでください)
  10. 「No Function」を選んで「GameManager」の中にある「sendScore」を指定
  11. 保存して実行してみましょう。
  12. ボタンを押すと、通信結果が表示されます。
  13. (ハイスコア、名前、スコア、名前、カウンター)です。
  14. カウンターはcgiが起動された回数です。(ゲーム的には意味は無い値ですが、応用する際、参考にしてください)
  15. k07_webを解凍して設置して、cgiファイルとdatファイルのパーミッションを755にすると、自分のHP上でも動くようになります。試してみましょう。
  16. ブラウザでscore_web.cgiにアクセスすると、ブラウザからも確認できます。
  17. score=-1で送信すると、ハイスコアが初期化されます(0になります)
  1. Player.csを新規に作りましょう
  2. 
    
    //class名が違っていたら上書き
    public class Player : MonoBehaviour {
    
    //変数の宣言に追加
    GameManager gm;
    
    //Start内に2行書く
    GameObject go = GameObject.Find ("GameObject");
    gm = go.GetComponent(typeof(GameManager)) as GameManager;
    
    //Updat内に追加
    if (Input.GetMouseButton (0)) {
      Vector3 pos = Input.mousePosition;
      float x = transform.position.x -pos.x;
      float y = transform.position.y - pos.y;
      if(x > -50 && x < 50 && y > -50 && y < 50){
        transform.localPosition = new Vector3 ((Random.value - 0.5f) * 300.0f, (Random.value -0.5f) * 300.0f, 0);
        gm.addScore();
      }
    }
    
  3. Imageにドラッグ&ドロップしましょう。
  4. GameManagerにも追記します。
  5. 
    //Updateに足す
    time -= Time.deltaTime;
    if (time >= 0.0f) {
      t.text = string.Format ("score:{0} time:{1:f1}", score, time);
    } else {
      t.text = string.Format ("score:{0} finished!", score);
    }
    
    //メソッドを2個追加
    public void addScore(){
      if (time > 0) {
        score++;
      }
    }
    
    public void restart(){
      score = 0;
      time = 20.0f;
    }
    
  6. リスタートボタンを作って、押すとrestartが呼ばれるようセッティングしましょう。
  7. キャラをクリックするとスコアが上がってキャラがワープするようになると完成です。
  8. 文字色も見やすく変えましょう。

よくある質問

スクリプトを更新したのに、InspectorViewの変数が増えない

プログラムが間違っていてビルドエラーが出ている可能性が高いです。

エディタ上でbuildしてみましょう。

{}の対応が間違っていないか、全角スペースが入っているかなど、確認してみましょう

ビルドエラーが出ていないのに、スクリプトをobjectに追加できない

classの大文字と小文字が違っている可能性があります。

エディタのbuildエラーが出ませんが、Unityでは読み込めない、という状況が確認されています。

保存して再度開いたらブロックやボールが消えた

unityの仕様(不具合)かなと思います。

BG(背景画像)の描画優先度を下げることで解決します。

BGのInspectorViewでOrder in Layerを-1にしてください

(テキストの手順にも追記しておきました)