【2일째】Unity에서 몹 프로그래밍 [C02_NosePush]

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"으로 통일한다고해도 플래그로 우선해야 할 수도 있습니다.

하나의 객체에 대해 여러 명칭 결정



코 구멍은 어때? 라는 사람이 있을지도 모릅니다.
매우 간단하기 때문에 다음 이미지로 스포일러입니다.



이미지의 희미한 녹색 부분이 당 판정입니다. 상부 2개가 구멍에 들어갔을 때의 당 판정. 아래 3개에 해당하면 게임 실패가 됩니다. 그럼 둘 다 맞았다면 어때?
이것에 대해서는 다른 기사에도 정리해 투고하려고 합니다. transform.position과 Rigidbody도 기본적인 것이기 때문에 다른 기사로 할까 생각했습니다만, 우선 이쪽의 기사에 써 보았습니다.

되돌아가다



이번에는 인원수가 적었기 때문에 페어 프로로 임하게 되었습니다. 또, 별로 작업을 분담하지 않고 상당히 바삭바삭하게 써 버렸기 때문에, 페어의 상대에게 생각해 받는 시간이 적었던 것 같습니다.

다른 팀의 소재 준비 팔로우도 갔기 때문에 서로의 쌍을 오가며 작업을 진행했습니다. 통상의 페어 프로와는 꽤 다른 칸지가 되었습니다만, 임박한 시간을 느끼면서도 집중한 형태로 서로의 팀에서의 작업에 임할 수 있었다고 생각합니다.

실은 점심에 Nintendo Switch로 「1-2-Switch(원투 스위치)」를 실습? 같은 칸지에서 놀고 싶었지만 전혀 여유가 없었습니다. 결국 저녁 정도에 논빌리한 시간에 피로를 느끼면서 흠흠 말하면서 놀았습니다만・・・.

좋은 웹페이지 즐겨찾기