1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【二日目】Unity でモブプログラミング[C02_NosePush]

Last updated at Posted at 2019-05-15

Unity でペアプロ

2019/05/11、本日は勉強会の参加人数が少ないためチームは2つに分かれ各チーム2人ずつのペアプログラミングによる体制になりました。

サンプル

【Youtubeの参考動画】(クリックするとYoutubeに移動)
IMAGE ALT TEXT HERE

4:30くらいからが該当のゲームです

そして出来上がったゲーム

GIFで飛び飛びですが実際はヌルヌルなカンジです。結構、雰囲気がイイカンジに緩くできました。デザインのことはトヤカク言わない約束です。

込み入った部分の説明

実はゲーム部分だけならスクリプトが1つだけというシンプルな内容です。以下にそのままソースを貼っておきます。
同じ画面にクリア成否のキャラを出すようにしていた名残が残っています。
本来は削除すべきですが、ナレッジ的に残しておきます。人と同じ作業する場合はキレイにして置いた方がイイですね。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class C02_HandMove : MonoBehaviour {
    float rightMax = 2.0f; //左へ移動可能 (x)最大値
    float leftMax = -2.0f; //右へ移動可能 (x)最大値
    float currentPositionX; //現在の位置(x)保存
    float currentPositionY; //現在の位置(y)保存
    public float sideMoveSpeed = 3.0f; //移動速度+方向

    public float pushSpeed = 10.0f; //打ち出されるスピード

    bool isTouched = false; //タッチされたか
    bool isGameEnd = false; //タッチ後、ゲーム完了したか

    private float stayTime = 0;

    public string nextSceneName = "C02_Result";
    public GameObject successChara;
    public GameObject failureChara;

    List<GameObject> colList = new List<GameObject> ();

    void Start () {
        currentPositionX = transform.position.x;
        currentPositionY = transform.position.y;
    }
    void Update () {
        if (!isTouched) {
            currentPositionX += Time.deltaTime * sideMoveSpeed;
            if (currentPositionX >= rightMax) {
                sideMoveSpeed *= -1;
                currentPositionX = rightMax;
            }
            //現在の位置(x) 右へ移動可能 (x)最大値より大きい、もしくは同じの場合
            //移動速度+方向-1を掛けて反転、現在の位置を右へ移動可能 (x)最大値に設定
            else if (currentPositionX <= leftMax) {
                sideMoveSpeed *= -1;
                currentPositionX = leftMax;
            }
            transform.position = new Vector3 (currentPositionX, currentPositionY, 0);
        }

        TouthPushHand ();

        if (isTouched) {
            stayTime += Time.deltaTime;
            if (stayTime > 1.0f) {
                if (colList.Count == 1) {
                    foreach (GameObject checkObj in colList) {
                        if (checkObj.name == "PushHole") {
                            C02_Result.isGameClear = true;
                        } else {
                            C02_Result.isGameClear = false;
                            //ResultCharaCreate (false);
                        }
                    }
                }
                if (colList.Count > 1) {
                    C02_Result.isGameClear = true;
                    //ResultCharaCreate (true);
                }
                if (colList.Count == 0) {
                    C02_Result.isGameClear = false;
                    //ResultCharaCreate (false);
                }
                SceneManager.LoadScene (nextSceneName);
            }
        }
    }

    //同じ画面にゲームクリア成否のキャラを出すときは以下のメソッドを使う
    void ResultCharaCreate (bool result) {
        if (result && !GameObject.Find (successChara.name)) {
            GameObject sucessObj = Instantiate (
                successChara,
                successChara.transform.position,
                successChara.transform.rotation
            );
            sucessObj.name = successChara.name;
            if (GameObject.Find (failureChara.name)) {
                Destroy (GameObject.Find (failureChara.name));
            }

        } else if (!GameObject.Find (successChara.name) && !GameObject.Find (failureChara.name)) {
            GameObject failerObj = Instantiate (
                failureChara,
                failureChara.transform.position,
                failureChara.transform.rotation
            );
            failerObj.name = failureChara.name;
        }
    }

    void TouthPushHand () {
        Vector3 PushForse = new Vector3 (0, pushSpeed, 0);
        if (Input.GetMouseButtonDown (0)) {
            gameObject.GetComponent<Rigidbody2D> ().AddForce (PushForse, ForceMode2D.Impulse);
            isTouched = true;
        }
    }

    private void OnCollisionEnter2D (Collision2D col) {
        colList.Add (col.gameObject);
    }
}

イケてないところをチェック

いろいろ他のスクリプトを参考にしたりしているので、つぎはぎフランケンなソースになっています。
まずなんかイケてないな~という部分は、左右の移動が「transform.position」で行っているのに対し、上への発射は 「Rigidbody」で行っているところです。
何がイケてないのかというと上への発射も 「transform.position」で行った方が統一されてイイかなと思いました。

「transform.position」と「Rigidbody」の混在のリスク

「transform.position」はその都度指定された位置に移動させています。
もし後から「Rigidbody」などで加速させたい場合、「transform.position」で位置が代入されていれば「transform.position」の方が優先され位置が上書きされます。そうじゃねぇ~っていう悲しい動きをすることになります。

でも、こちらのソース混在されてますよね?

なのでダサいことではありますが、「transform.position」での移動については、タッチ後フラグで動作しないよう無効にしています。その後に「Rigidbody」で上に発射するようにしています。まあ「transform.position」で統一したとしてもフラグで優先する必要があるかもしれません。

1つのオブジェクトに対して複数の当たり判定

鼻の穴ってどうしてるの?っていう人がいるかもしれません。
とってもカンタンなことなので以下の画像でネタバラシです。

鼻colider.png

画像のうっすい緑色の部分が当たり判定です。上2つが穴に入ったときの当たり判定。下3つに当たった場合はゲーム失敗になります。それじゃあ、両方に当たった場合はどうなんのよ?
これについては別の記事にでもまとめて投稿しようと思います。transform.positionとRigidbodyも基本的なことではあるので別記事にしようかと思いましたが、とりあえずこちらの記事に書いてみました。

振り返り

今回は人数が少なかったためペアプロで取り組むことになりました。また、あまり作業を分担せずに結構サクサク書いてしまったため、ペアの相手に考えてもらう時間が少なかったように思われます。

もう一方のチームの素材準備のフォローも行ったためお互いのペアを行き来しながら作業を進めました。通常のペアプロとはかなり違ったカンジになりましたが、差し迫る時間を感じながらも集中した形でお互いのチームでの作業に取り組めたと思います。

実はお昼にNintendo Switchで「1-2-Switch(ワンツースイッチ)」を実習?のようなカンジで遊びたかったのですが全然余裕がなかったです。結局夕方くらいにノンビリした時間に疲れを感じつつフムフム言いながら遊びましたが・・・。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?