# ゲーム開発 ここではゲーム開発で行う作業や、学習内容を記述する。 # 環境設定 ## Unityのインストール https://school.dhw.co.jp/word/cg/Unity_install.html 上記のサイトを参考に作業を進める。 [公式サイト](https://unity3d.com/jp/get-unity/download)からUnityHubをインストールする。 バージョン2021.3.11f1のエディタをインストールする。 # 学習(10/7) 以下のものを学習した。 ## 基本操作 基本的な操作は[このサイト](https://unity3d.com/jp/get-unity/download)を参考に学習した。 物体の配置と物体の移動、視点操作などを学習した。 ## 物体の落下 InspectorウィンドウのAdd Componentから、Rigidbodyを追加する。Use Gravityのチェックを入れた状態で再生ボタンを押すと、物体に落下運動をさせることが出来る。 ## 衝突 Box Colliderのチェックを入れた状態では、物体はお互いに干渉し衝突する。 チェックを外すと、物体は衝突をせず通過する。 # 学習(10/12) [簡易ゲームの作成手順](https://hackmd.io/uToMjxxeRhKHxV1KYSV1JA)を使い実際にゲームを作成しながら、Unityの使い方を学習した。 学習内容は、以下の通りである。 ## Rigidbody inspectorのAdd Componentから追加する 重力を持たせる ## Collider inspectorのAdd Componentから追加する 当たり判定をつける Colliderを持つ物体同士は衝突する(基本すり抜けない) すり抜けるときの対処法 ## run 再生ボタンを押すとプロジェクトを実行できる run中に数値の変更などを行うと、数値はrun中にのみ反映され保存されない ## オブジェクトの親子関係 子オブジェクトにしたいものをHierarchyで親オブジェクトにドラッグアンドドロップする 子オブジェクトは、親オブジェクトとの相対位置を維持する (親オブジェクトを動かすと、子オブジェクトがついてくる.逆は相対位置の変更のみ) ## is Trigger colliderのis Triggerにチェックを入れると、他の物体との衝突が起きなくなる 物体がcollider内にあるかを判定する(特定の物体も可能) ## タグ タグを付けることで、物体に属性を持たせる ## Material 色や透明度の変更を行う ## Assets すでに作ってある素材を利用できる [Unity Asset Store](https://assetstore.unity.com/3d)から追加し、プロジェクト内でダウンロードとインポートを行う ## Sclipt * Unity特有の関数が多数存在する。 Start関数:最初の一回のみ呼び出し Update関数:毎フレームで呼び出し FixedUpdate:一定間隔で呼び出し * アクセス修飾子 どこからアクセスできるかを設定する private:クラス内でのみアクセス可能 public:クラス外でも有効 * 名前の変更時は注意が必要 名前を変更するときは、スクリプト内の名前も変更する 変更しないと、エラーが出る # 作成するもの(10/14) ## ほしい機能 * スコア表示 * 視点の切り替え * 複数種類の敵(1ステージで2,3種類) * スコアのランキング * ステージ選択 * 敵の配置をランダムにする(2,3パターン) * 複数種類の武器、武器の強化 ## 決定事項 * パソコンでプレイ * オフライン * ステージクリア型 * ボスを倒したらステージクリア ### 制作手順 1. プレイヤーの動作、銃 2. 弾の当たった時の処理 3. フィールド 4. 敵の種類、配置パターン 5. 武器の種類、強化のシステム(余裕があれば) # ゲーム制作(10/19) 一人称で銃を撃ち、移動できるようにする。 [参考サイト](https://programming.sincoston.com/unity-launcher/) ## 初めに * Planeを作成する * カメラをPlane上に移動させ、Playerの目線にしたい位置に調整 * Cubeを作成し、カメラの少し後ろに配置 * CubeにRigidbodyを付ける * 銃の代わりにCylinderを作成し、カメラ下部に映るように配置 ![](https://i.imgur.com/RBbYStv.png) お好みで色を変更(Materialを作成、付けることで変更可能) * カメラをCubeの子オブジェクトに設定 * Cylinderをカメラの子オブジェクトに設定 * ## カメラの動作 以下のスクリプトを作成し、カメラに付ける ``` using System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraController : MonoBehaviour { [Range(0.1f, 10f)] //カメラ感度、数値が大きいほどより直感的な操作が可能. public float lookSensitivity = 5f; [Range(0.1f, 1f)] //数値が大きいほどカメラが向きたい方向に向くまでの時間が長くなる. public float lookSmooth = 0.1f; public Vector2 MinMaxAngle = new Vector2(-65, 65); private float yRot; private float xRot; private float currentYRot; private float currentXRot; private float yRotVelocity; private float xRotVelocity; void Update() { yRot += Input.GetAxis("Mouse X") * lookSensitivity; //マウスの移動. xRot -= Input.GetAxis("Mouse Y") * lookSensitivity; //マウスの移動. xRot = Mathf.Clamp(xRot, MinMaxAngle.x, MinMaxAngle.y);//上下の角度移動の最大、最小. currentXRot = Mathf.SmoothDamp(currentXRot, xRot, ref xRotVelocity, lookSmooth); currentYRot = Mathf.SmoothDamp(currentYRot, yRot, ref yRotVelocity, lookSmooth); transform.rotation = Quaternion.Euler(currentXRot, currentYRot, 0); } } ``` ## 弾の発射 * Create Emptyで名前をBulletPosに変更 * BulletPosを銃の先端に配置する * BulletPosをSilinderの子オブジェクトにする * Sphereを作成し、名前をBulletに変更 * Materialを作成し、Bulletに付ける * BulletにRigidbodyを付ける * 色を変更しておく(見やすいように) * Bulletをasset<prefabにドラッグアンドドロップ * Hierarchy上のBulletは削除する * Create Enptyで名前をGunControllerに変更 * 以下のスクリプトを作成し、GunControllerに付ける ``` using System.Collections; using System.Collections.Generic; using UnityEngine; public class GunController : MonoBehaviour { //bulletプレハブ public GameObject bullet; //弾が生成されるポジションを保有するゲームオブジェクト public GameObject bulletPos; //弾丸のスピード public float speed = 1500f; // Update is called once per frame void Update() { //スペースが押されたとき if (Input.GetKeyDown(KeyCode.Space)) { //ballをインスタンス化して発射 GameObject createdBullet = Instantiate(bullet) as GameObject; createdBullet.transform.position = bulletPos.transform.position; //発射ベクトル Vector3 force; //発射の向きと速度を決定 force = bulletPos.transform.forward * speed; // Rigidbodyに力を加えて発射 createdBullet.GetComponent<Rigidbody>().AddForce(force); } } } ``` * inspectorから以下のように変更 ![](https://i.imgur.com/kWgTk8A.png) ## playerの移動 * 以下のMoveスクリプトを作成し、Cubeに付ける ``` public float speed = 3f; float moveX = 0f; float moveZ = 0f; Rigidbody rb; void Start(){ rb = GetComponent<Rigidbody> (); rb.constraints = RigidbodyConstraints.FreezeRotation; //転倒を防止 } void Update () { moveX = Input.GetAxis ("Horizontal") * speed; moveZ = Input.GetAxis ("Vertical") * speed; Vector3 direction = new Vector3(moveX , 0, moveZ); } void FixedUpdate(){ rb.velocity = new Vector3(moveX, 0, moveZ); } ``` ## メモ キー入力での移動方向とカメラで見える移動方向が異なる。 マウスでカメラの移動をなくすなどして、移動方向をそろえたい。 # ゲーム制作(10/21) 弾が当たった時の処理を設定する。 ## 敵を作る * cubeを作成し、Enemyと名前を変更 * Enemyタグを作成し、取り付ける * EnemyHPスクリプトを作成し、以下の内容を記述 ``` using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class EnemyHP : MonoBehaviour { int maxHP = 3; int HP; void Start() { HP = maxHP; } public void damage(int weaponPower) { HP -= weaponPower; //確認用 Debug.Log("enemyHP:" + HP); if (HP <= 0) { Destroy(this.gameObject); } } } ``` ## 当たり判定 弾が敵に当たったら、EnemyHPのdamegeを呼び出す処理を行う * balletプレハブを開く * Balletスクリプトを作成し、balletに取り付ける * スクリプトには、以下の内容を記述 ``` using System.Collections; using System.Collections.Generic; using UnityEngine; public class Ballet : MonoBehaviour { int weaponPower = 1; void OnCollisionEnter(Collision other) { if (other.gameObject.tag == "Enemy") { Debug.Log("敵に当たった"); Destroy(this.gameObject); other.collider.GetComponent<EnemyHP>().damage(weaponPower); } else { Debug.Log("他のものに当たった"); } } } ``` ## 敵のHPを表示 敵の現在のHPが表示されるようにする。 * create < UI < sliderをクリック * canvasの設定を変更 ![canbas < inspector](https://i.imgur.com/Nsx0X5f.png) * Backgroundの色、Fillの色を変更(どちらもslinderの子オブジェクト) * 位置とサイズを変更し、Enemyの上に表示 * EnemyHPスクリプトに追記 ``` using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class EnemyHP : MonoBehaviour { int maxHP = 3; int HP; //追記 public Slider slider; public GameObject HPUI; void Start() { //追記 slider.value = 1; HP = maxHP; } public void damage(int weaponPower) { HP -= weaponPower; //確認用 Debug.Log("enemyHP:" + HP); //追記 slider.value = (float)HP / (float)maxHP; if (HP <= 0) { Destroy(this.gameObject); HPUI.SetActive(false); } } } ``` * HPUIをUnity上でcanvasにする * SlinderをUnity上で選択 * Enemyをプレハブ化 ## HP表示の向きを動的に変更 今の設定だと、PlayerがEnemyの横に移動するとHP表示が見えなくなる。 これを回避するために、HP表示をカメラの向きに合わせる。 * Canvasスクリプトを作成、canvasに取り付ける * 以下の内容を記述 ``` using System.Collections; using System.Collections.Generic; using UnityEngine; public class Canvas : MonoBehaviour { void LateUpdate() { // カメラと同じ向きに設定 transform.rotation = Camera.main.transform.rotation; } } ``` # ゲーム制作(10/26) ## player操作の修正 FPSControllerスクリプトを作成し、playerに付ける(Cube) Moveスクリプト、CameraControllerスクリプトを外す ``` using System.Collections; using System.Collections.Generic; using UnityEngine; public class FPSController : MonoBehaviour { float x, z; float speed = 0.1f; public GameObject cam; Quaternion cameraRot, characterRot; float Xsensityvity = 3f, Ysensityvity = 3f; bool cursorLock = true; //変数の宣言(角度の制限用) float minX = -90f, maxX = 90f; // Start is called before the first frame update void Start() { cameraRot = cam.transform.localRotation; characterRot = transform.localRotation; } // Update is called once per frame void Update() { float xRot = Input.GetAxis("Mouse X") * Ysensityvity; float yRot = Input.GetAxis("Mouse Y") * Xsensityvity; cameraRot *= Quaternion.Euler(-yRot, 0, 0); characterRot *= Quaternion.Euler(0, xRot, 0); //Updateの中で作成した関数を呼ぶ cameraRot = ClampRotation(cameraRot); cam.transform.localRotation = cameraRot; transform.localRotation = characterRot; UpdateCursorLock(); } private void FixedUpdate() { x = 0; z = 0; x = Input.GetAxisRaw("Horizontal") * speed; z = Input.GetAxisRaw("Vertical") * speed; //transform.position += new Vector3(x,0,z); transform.position += cam.transform.forward * z + cam.transform.right * x; } public void UpdateCursorLock() { if (Input.GetKeyDown(KeyCode.Escape)) { cursorLock = false; } else if (Input.GetMouseButton(0)) { cursorLock = true; } if (cursorLock) { Cursor.lockState = CursorLockMode.Locked; } else if (!cursorLock) { Cursor.lockState = CursorLockMode.None; } } //角度制限関数の作成 public Quaternion ClampRotation(Quaternion q) { //q = x,y,z,w (x,y,zはベクトル(量と向き):wはスカラー(座標とは無関係の量)) q.x /= q.w; q.y /= q.w; q.z /= q.w; q.w = 1f; float angleX = Mathf.Atan(q.x) * Mathf.Rad2Deg * 2f; angleX = Mathf.Clamp(angleX, minX, maxX); q.x = Mathf.Tan(angleX * Mathf.Deg2Rad * 0.5f); return q; } } ``` ## アセットの準備 * [アセット](https://assetstore.unity.com/packages/3d/environments/flooded-grounds-48529)をダウンロード&インポート * Assets/Flooded_Grounds/Scenes/PreAsembeld_Buildingsを開く * plyaerを配置 * Rigidbody、capsuleCliderを付ける * FPSControllerをつける * FPSControllerのカメラを設定する # ゲーム制作(11/2) ## 敵の動き [参考サイト](https://futabazemi.net/unity/navmesh-ballet-move) 基本上記のサイトに従う 一部コードの変更 エリアをPlayer側に作成(敵からの攻撃用に→敵のコライダーと衝突するとダメージを負う予定) ### Areaスクリプトの内容 ``` using System.Collections; using System.Collections.Generic; using UnityEngine; public class Area : MonoBehaviour { void OnTriggerStay(Collider other) { if (other.gameObject.tag == "Enemy") { other.GetComponent<Collider>().GetComponent<EnemyMove>().IsArea_true(); } } void OnTriggerExit(Collider other) { if (other.gameObject.tag == "Enemy") { other.GetComponent<Collider>().GetComponent<EnemyMove>().IsArea_false(); } } } ``` ### EnemyMoveスクリプトの内容 ``` using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class EnemyMove : MonoBehaviour { NavMeshAgent agent; [SerializeField] GameObject target; bool isArea; void Start() { agent = GetComponent<NavMeshAgent>(); } void Update() { if (isArea) { agent.destination = target.transform.position; } else if (!isArea) { agent.destination = this.transform.position; } } public void IsArea_true() { isArea = true; } public void IsArea_false() { isArea = false; } } ``` ### メモ Playerが後ろに下がるときの跳ねる処理をなくす必要あり is kinematicですり抜け防止 11/2(水)の内容は後から書いておきます。すみません… # ゲーム制作(11/4) ## 敵の出現ポイントを作成 * Create Empty を選択 * 名前をEnemyPointに変更 * Box Collider をつける * 敵を出現させたい場所に移動 * タグをEnemyPointに変更 * EnemyPopスクリプトを作成 ``` using System.Collections; using System.Collections.Generic; using UnityEngine; public class EnemyPop : MonoBehaviour { public GameObject enemyPrefab; public void AppearEnemy() { GameObject enemy = Instantiate(enemyPrefab) as GameObject; enemy.transform.position = transform.position; Destroy(this.gameObject); } } ``` * 上記のスクリプトをEnemyPointに取り付ける * Enemyをプレハブ化する * Inspector>EnemyPint>EnemyPop>EnemyPrefabをEnemy(プレハブ)に変更 * 作成済みのAreaスクリプトを以下のように変更 ``` using System.Collections; using System.Collections.Generic; using UnityEngine; public class Area : MonoBehaviour { void OnTriggerStay(Collider other) { if (other.gameObject.tag == "Enemy") { other.GetComponent<Collider>().GetComponent<EnemyMove>().IsArea_true(); } } void OnTriggerExit(Collider other) { if (other.gameObject.tag == "Enemy") { other.GetComponent<Collider>().GetComponent<EnemyMove>().IsArea_false(); } } void OnTriggerEnter(Collider other) { if (other.gameObject.tag == "EnemyPoint") { //確認用 //Debug.Log("判定成功"); other.GetComponent<Collider>().GetComponent<EnemyPop>().AppearEnemy(); } } } ``` ## 出現させた敵にPlayerを追跡させる 現状では、敵が正常に出現してもエラーのため追跡できない。 正常に追跡させるために以下の操作を行う。 ~~* Playerをプレハブ化する~~ ~~* Enemy(プレハブ)>EnemyMove>TargetでPlayer(プレハブ)を選択~~ 正常に追跡されなかったので、以下の操作に変更 * EnemyMoveスクリプトの内容を変更 (start関数内に追記) ``` GameObject player = GameObject.Find("Player"); target = player; ``` ## 敵アセットを決定 敵アセットを決めてください(決定したら、以下にリンクを張る) [アセット](https://assetstore.unity.com/) [Easy FPS](https://assetstore.unity.com/packages/3d/characters/humanoids/sci-fi/easy-fps-73776) [アセット2](https://assetstore.unity.com/packages/3d/characters/robots/delivery-robot-185414) [アセット3]() * 敵にNav Mesh Agent と EnemyMove を取り付ける(おそらくRigidbodyも) * EnemyPoint をプレハブ化し、EnemyPrefabを敵アセットのプレハブにする ## 敵にアニメーションをつける アセットによる(おそらくEnemyMoveスクリプトに追記する) # ゲーム制作(11/9) ## GitHubの設定 皆さんのGitアカウント名を教えてください。(以下に記入) 大村:sorajoirosan 宇佐美:shiguma0 ホアン:kitarorpheus リポジトリに招待するので、メールが来たらリンクを踏んで承諾してください。 ## Gitを使ってみる(時間がかかるので最後にするかも) リポジトリをクローンしてみよう * コマンドプロンプトを起動 * `bash` * 作成したい場所に移動 * `git clone [リポジトリパス]` リモートの更新をローカルに反映 * `bash` * クローンしてきたディレクトリ(ShootingGame)に移動 * `checkout develop` * `git pull origin develop` ### リモートの変更内容 * プレイヤーが後ろに動くとき、跳ねる動作を修正 * カメラを一人称に限定 多少アセットなどのゴミがあるかもしれませんが、気にしないでください。 ## 敵のアセットをインポート [アセット](https://assetstore.unity.com/packages/3d/characters/robots/delivery-robot-185414)をインポート * 敵を配置 * Rigidbody、BoxColliderを取り付ける * 再生して正常に動作するか確かめる 敵がゆっくりと浮いていく場合は、その時指示します。(おそらくそうなる) ## 敵にアニメーションを付ける 通常時は歩いているアニメーション、攻撃が当たるとダメージを受けた時のアニメーション [参考](https://qiita.com/sanpeita/items/3864578e852801c15f80) * EnemyAnimスクリプトを作成 * 敵に作ったスクリプトを取り付ける ``` ``` * 新しいフォルダ(Animation)を作る * animatorで以降の作業をする * Emptyを作成x3 * それぞれをWalk,Attack,Dieにする * それぞれにアニメーションを設定 少しトラブったので続きは次回にします ![](https://i.imgur.com/yrw5kkw.png) ## プレイヤーのダメージ処理 敵がコライダーに当たると * PlayerHPスクリプトを作成 * playerに作成したスクリプトを付ける ``` using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerHP : MonoBehaviour { public int MaxHP = 3; private void OnCollisionEnter(Collision collision) { if(collision.gameObject.tag == "Enemy") { Debug.Log("敵に衝突した"); damage(); } } public void damage() { MaxHP = MaxHP-1; if(MaxHP <= 0) { Debug.Log("死んでしまった"); } } } ``` * GgmeOverと表示されるようにする ## メモ 僕のプロジェクトだけかもですが、NavMeshAgentの使用でエラーが出たので次回修正します。 # ゲーム制作(11/18) ## 敵のアニメーション設定 敵がプレイヤーと衝突しているときに攻撃モーションを再生 (前回やった内容を含む) * 新しいフォルダを作成し、Animatorに変更 * フォルダ内でAnimatorControllerを作成し、EnemyAnimに変更 * EnemyAnimを開き、右クリック<Create state<Empty (×4回) ![](https://i.imgur.com/RT0X5zJ.png) * 上のように名前を変更 * Walk、Attack、Dieにそれぞれアニメーションを取り付ける * Triggerを2つ作成し、isAttackとisDieに変更 * Boolを1つ作成し、isWalkに変更 * NewState→Walk遷移にisWalkのtrueを設定 * NewState←Walk遷移にisWalkのfalseを設定 * Walk→Attack遷移にisAttackを設定 * Walk→Die遷移にisDieを設定 * 新しくスクリプトを作成し、EnemyAnimに変更 ``` using System.Collections; using System.Collections.Generic; using UnityEngine; public class EnemyAnim : MonoBehaviour { Animator anim; int i = 0; // Start is called before the first frame update void Start() { anim = gameObject.GetComponent<Animator>(); } private void OnCollisionStay(Collision collision) { if(collision.gameObject.tag == "Player") { i = (i+1)%100; if (i == 1) { anim.SetTrigger("isAttack"); } } } private void OnCollisionExit(Collision collision) { if(collision.gameObject.tag == "Player") { i = 0; } } public void isWalk_anim() { anim.SetBool("isWalk", true); } public void noWalk_anim() { anim.SetBool("isWalk", false); } } ``` * Areaスクリプトを変更 ``` using System.Collections; using System.Collections.Generic; using UnityEngine; public class Area : MonoBehaviour { void OnTriggerStay(Collider other) { if (other.gameObject.tag == "Enemy") { other.GetComponent<Collider>().GetComponent<EnemyMove>().IsArea_true(); } } void OnTriggerExit(Collider other) { if (other.gameObject.tag == "Enemy") { other.GetComponent<Collider>().GetComponent<EnemyMove>().IsArea_false(); } if(other.gameObject.tag == "Robot") { other.GetComponent<Collider>().GetComponent<EnemyAnim>().noWalk_anim(); } } void OnTriggerEnter(Collider other) { if (other.gameObject.tag == "EnemyPoint") { //確認用 //Debug.Log("判定成功"); other.GetComponent<Collider>().GetComponent<EnemyPop>().AppearEnemy(); } if (other.gameObject.tag == "Robot") { other.GetComponent<Collider>().GetComponent<EnemyAnim>().isWalk_anim(); } } } ``` ここではEnemyMoveを取り付けていないため、ロボットの敵にRobotタグを付けて再生する。 ## GameOver表示 前回PlayerHPスクリプトを作成し、死亡判定が正常に動作することを確認した。 ここでは死亡判定時に画面にGameOverと表示されるようにする。 * PlayerHPスクリプトの内容を変更 ``` using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class PlayerHP : MonoBehaviour { public int MaxHP = 3; public GameObject text; Text GameOvertext; private void Start() { GameOvertext = text.GetComponent<Text>(); } private void OnCollisionEnter(Collision collision) { if(collision.gameObject.tag == "Enemy") { Debug.Log("敵に衝突した"); damage(); } } public void damage() { MaxHP = MaxHP-1; if(MaxHP <= 0) { Debug.Log("死んでしまった"); GameOvertext.text = "GameOver"; } } } ``` このままでは、当たっている間(離れないと)ダメージがないので変更する。 ## 銃を装備 [銃](https://assetstore.unity.com/packages/3d/props/guns/guns-pack-low-poly-guns-collection-192553) 上記のアセットを使用 # 学習(11/18) ## collisionとTrigger OnCollisionEnter や OnTriggerEnter などの似た関数が存在する 今日のゲーム制作でどちらも出てきたので、ここで整理しておきましょう! [参考](https://www.sejuku.net/blog/83742) * collisionはコライダー同士の衝突(isTriggerにチェックが付いていない) * Triggerはすり抜けた時(どちらかのisTriggerにチェックが付いている) # 担当決め(12/7) 希望する欄に名前を書いてください。 効果系:谷﨑[(作業記録)](https://hackmd.io/hxXPh-DuQhKP2un_6loa6Q) スタート画面:宇佐美[(作業記録)](https://hackmd.io/ZouhOSgoSXaUqe2bdGKkrA) ステージ:大村[(作業記録)](https://hackmd.io/@AD415ZtIR1C5cfXjOXkZoA/BkKGqFl_s) ナビゲーション制作:谷﨑 [(作業記録)](https://hackmd.io/5b7FTkzsStW4z0CQwPk-Sw) Mesh_Bugブランチに切ってpull 自分のブランチを作成し,ブランチの移動を行う ## 今後の進め方 * サークル活動時に調べながら作業する。(当然家で作業しても構いません。むしろ歓迎) * 自分の行った作業内容を記録 * 更新をこまめにpushする * MaterialフォルダやScriptフォルダなどの既存フォルダには新しいものを入れない(新しくフォルダを作成する) 例 Navigationファルダを作成し、その中に各フォルダを作成 Navigation---┬-Script       ├-Material * 次回する予定のことも作業記録に記述する * gitを更新する ``` git add -A git commit -m "コメント" git push origin ブランチ名 ``` * 大まかに完成したら報告(谷﨑へ) # 12/9(金) * 役割分担 * ルール説明 * git説明 # メモ 最終的に各々で作ったものを一人がまとめる作業を行うと思うので、作業内容がわかるようにしておいてください。(例:参考サイトのリンクを置いておく、scriptにその役割をコメントアウトで書くなど) マップ作成がほぼ終わったので、効果系の担当も谷﨑がします。(ただの報告) # 今後の活動 ## ??/??(?) 各自での開発