Assetsのところで右クリック→「Show in Exprorer」 AssetsフォルダをUSBメモリにコピーする 他の環境で開きたい場合,一度プロジェクトを作成し,そのプロジェクトのAssetsフォルダを上の方法で開き,USBからコピーする.
Assetsのところで右クリック→「Show in Exprorer」→Assetsフォルダを右クリック →送る→ZIP(圧縮フォルダ)
http://cho.is.meisei-u.ac.jp/cho/jikken1/ の「透過PNGの作成アプリ」をダウンロード
左下のGame(シーンの実行画面) -> Free Aspect を 3:2○○ など任意の比率に変更
ボタンやテキストオブジェクトを追加後、Canvasを選択し、「Render Mode」を 「Screen space- camera」に選択する。 すると「Render Camera」というフィールドが現れるので、HierarchyからMain Cameraをドラッグ&ドロップする。
float width; public GameObject seed; void Start() { // Spriteの幅を取得. // 高さの取得はsize.yでできます. width = seed.GetComponent<SpriteRenderer>().bounds.size.x; }
オブジェクト一つだけ変更する場合 Hierarchyから重力を変更したいオブジェクトを選ぶ -> InspectorのRigidbody 2D の中にあるGravity Scaleの値をいじる オブジェクト全体を変更する場合 Edit -> Project Settings -> Physics 2D -> Gravityをいじる スクリプトで記述する場合(オブジェクト全体の重力が変わる) Physics2D.gravity = new Vector2 (0, -5.5f); // new Vector2(x方向の重力,y方向の重力) ちなみに元の重力は(0,-9.81f)
衝突判定を行う場合、両方のキャラクタにColliderを忘れずにつけてください void OnCollisionEnter2D(Collision2D collision) { // 衝突時の処理例1:このスクリプトがついているキャラ自身を消す Destroy(gameObject); // 衝突時の処理例2:このスクリプトがついているキャラとぶつかったオブジェクトを消す Destroy(collision.gameObject); }
衝突判定を行うキャラをHierarchyから選ぶ -> InspectorのTagを選び、Add Tag -> Elementに適当なタグ名を入力(敵の場合はEnemyなど) void OnCollisionEnter2D(Collision2D collision){ if(collision.gameObject.tag=="Enemy"){ // 衝突時の処理 } }
すり抜けられるオブジェクトのcolliderのis Triggerにチェックを入れる スクリプトを追加し、衝突判定は次のように書く (例は"neko"という名前のオブジェクトと当たっていたら"neko"を消すという処理) void OnTriggerEnter2D(Collider2D col){ if(col.gameObject.name=="neko"){ GameObject.Destroy (col.gameObject); } } 何かとぶつかった瞬間にOnTriggerEnter2Dが実行されるので、ぶつかったオブジェクトによって行う動作を記述する
プレハブ化したいキャラを作る -> ProjectのCreateからPrefabを選択。するとAssetsの中に新しいPrefabができるので、「(出したいキャラ名)Prefab」などとする -> Hierarchyからプレハブ化したいキャラを、今名前を付けたPrefabにドラッグする
はじめに一定間隔で出現させたいキャラをプレハブ化させておく(Prefab化参照) Hierarchy -> Create -> Create Empty -> するとHierarchyにGameObjectというのができる。 それをgeneratorなどに名前を変えて、選択 -> InspectorからAdd Component -> New Script -> Generatorのように名前を付ける MonoDevelopでスクリプトを記述する public class Generator : MonoBehaviour { int counter=0; public GameObject seed; // ★ void Start () { } void Update () { counter++; if (counter%100==0) { // Instantiate(ゲームオブジェクト,出現位置☆,回転) Instantiate (seed, new Vector3 (0, 0, 0), Quaternion.identity); counter=0; } } } Unity画面に戻り、先程作ったゲームオブジェクトのInspector のSeed(スクリプトの★マークと同じ名前)と書いてある横の欄に出したいキャラのプレハブをドラッグする このスクリプトでは一定間隔でキャラが出てくる ランダムな場所に出現させるには「乱数を取得する」を参考に、☆の部分の出現位置を変更する
キャラクタ(敵など)を一定間隔で出すを参照し、スクリプトを書く直前まで進める スクリプトに次のように書く public GameObject seed; void Start() { StartCoroution("CreateChara"); } private IEnumerator CreateChara() { while(true){ Instantiate(seed, new Vector3(0.0f, 0.0f, 0.0f), Quaternion.identity); // WaitForSecondsに与える引数が待つ秒数 yield return new WaitForSeconds(2.0f); } } キャラクタ(敵など)を一定間隔で出すのスクリプトより下の部分(Unity画面に戻り~)を行う、
弾のオブジェクトをプレハブ化(Prefab化参照) 弾を出すキャラのScriptを追加し弾を発射させる、ここでは、updateで適当な確率で弾を撃つようにさせる例を示す。 public GameObject gen; void Update () { if (Random.Range (0, 100) < 1) { Vector3 genPos=this.transform.position; Instantiate(gen,genPos,Quaternion.identity); } } 弾を出すキャラのInspectorのScriptのなかのGenと書いてある横の欄に出したいキャラのプレハブをドラッグする。
※オブジェクトを出現させる方法についてはキャラクタを一定間隔で出すなどを参照のこと オブジェクトを出現させる側のスクリプトに次のように書く GameObject s=Instantiate(seed,transform.position,Quaternion.identity) as GameObject; var b=s.GetComponent<Rigidbody2D> (); b.velocity=new Vector2(1.0f,0); 1行目でオブジェクトを生成し、そのオブジェクトをsという名前で保持する 2行目で、sという名前で保持したオブジェクトのvelocity(=速度)を設定する
HierarchyからCreate -> UI -> Button でCanvasの下にButtonができる。Buttonを選択しInspectorを表示させる。 Inspector -> Add ComponentでScriptを追加(または新しく作る) -> Scriptにボタンが押された時に行うメソッドを記述する。 public void onTouch(){ Debug.Log("test Touched"); } ここからはコードを実行するタイミングによって作り方が異なる *1 Buttonを押して離した瞬間に動作させる場合 ButtonのInspector -> Button(Script)の中にあるOn Click() -> None(Object)と書かれたところに、HierarchyからButton(自分自身)をドラッグしてくる。 最後にOn Click()の右側のNo Function -> 先程記述したスクリプトの名前 -> 先程記述したメソッドの名前(ここでは onTouch() )と選択する。 実行するとButtonを押して、離した瞬間にメソッドが実行される。 *2 Buttonを押した瞬間に動作させる場合 ButtonのInspectorからAdd Component -> Event -> Event Trigger これでEvent Triggerが追加される。 次にEvent Trigger から Add New Event Typeを選択し、PointerDownを選ぶと、PointerDown (Base EventData)というのがでてくる。 その中のNone(Object)と書かれた場所にHierarchyからButton(自分自身)をドラッグしてくる。 最後にPointer Down()の右側のNo Function -> 先程記述したスクリプトの名前 -> 先程記述したメソッドの名前(ここでは onTouch() )と選択する。 実行するとButtonを押した瞬間にメソッドが実行される。 *3 Buttonを離した瞬間に動作させる場合 ButtonのInspectorからAdd Component -> Event -> Event Trigger これでEvent Triggerが追加される。 次にEvent Trigger から Add New Event Typeを選択し、PointerUpを選ぶと、PointerUp (Base EventData)というのがでてくる。 その中のNone(Object)と書かれた場所にHierarchyからButton(自分自身)をドラッグしてくる。 最後にPointer Up()の右側のNo Function -> 先程記述したスクリプトの名前 -> 先程記述したメソッドの名前(ここでは onTouch() )と選択する。 実行するとButtonを離した瞬間にメソッドが実行される。 使用例:ボタンを押したらキャラクタが左に動きだし、ボタンを離したら止まる 押されたときに行われるメソッドをOnButtonDown()、離されたときに行われるメソッドをOnButtonUp()とする。 ここでは、neko1という名前のオブジェクトを動かしている public void OnButtonDown(){ // neko1という名前のオブジェクトを取得する GameObject neko1=GameObject.Find ("neko1"); // 取得したオブジェクトの速度(velocity)を-1にする var b=neko1.GetComponent<Rigidbody2D> (); b.velocity = new Vector2 (-1.0f, 0); } public void OnButtonUp(){ GameObject neko1=GameObject.Find ("neko1"); // 取得したオブジェクトの速度(velocity)を0にする var b=neko1.GetComponent<Rigidbody2D> (); b.velocity = new Vector2 (0, 0); }
スクリプトを作って void Update () { //座標の用意 Vector3 dir = transform.position; //横方向の傾き具合を座標に加算 dir.x += Input.acceleration.x; //縦方向の傾き具合を座標に加算 dir.y += Input.acceleration.y; //オブジェクトに座標を改めて入れる //(このスクリプトを関連付けているオブジェクトが傾きに影響されて位置が変わる) gameObject.transform.position = dir; } スマフォの傾き度は Input.acceleration.軸名 で取得できる。 傾けた時のスピードを変更したい場合は、Input.acceleration.xとかに数字を掛けてあげよう。 上のプログラムでは、傾き具合をそのままオブジェクトの座標に加算しているから、 傾けっぱなしだとオブジェクトが戻ってこなくなる。 ちなみに、傾きセンサーの値は、 xの場合、画面を正面から見て左に傾けると-になり、右に傾けると+になる。 yの場合、画面を正面から見て下に傾けると-になり、上に傾けると+になる。 特にyの値の変化には注意。
効果音ファイルをAssetsにいれる -> 効果音を鳴らすキャラ(弾を撃つときの音ならPlayerなど)のInspectorから Add Component -> Audio -> Audio Sourceでコンポーネントが追加される。 スクリプトを作って public AudioClip audio; AudioSource aSource; // Use this for initialization void Start () { aSource = gameObject.GetComponent<AudioSource> (); aSource.clip = audio; aSource.PlayOneShot (audio); } // Update is called once per frame void Update () { } と書いてセーブすると、InspectorのScriptの下にAudioと書かれた欄が登場するので、そこにAssetsから効果音ファイルをドラッグする。 このプログラムだと起動時に一回なるだけなので鳴らしたいタイミングで命令を記述する aSource.PlayOneShot(audio); // 重複してならせる(弾を撃つ効果音などに) aSource.Play(); // 呼ばれるたびに最初から鳴らす(BGMなどに)
力を加えたいオブジェクトのスクリプトの、力を加えたいタイミングで var r = GetComponent<Rigidbody2D> (); r.AddForce(new Vector2(x方向への力,y方向への力),ForceMode2D.Impulse); と記述する
反発や摩擦をつけるオブジェクトにはあらかじめCollider 2Dをつけておく Project -> Create -> Physics2D Material -> InspectorにFrictionとBouncinessとでるので、この値を設定する Friction … 摩擦を0から1の範囲で設定する。0だと摩擦がかからず、1に近づくにつれて摩擦力が大きくなる Bounciness … 反発係数を0から1の範囲で設定する。0だとまったく弾まず、1に近づくにつれて大きく弾むようになる 係数を設定するオブジェクトを選び、Inspectorの中にある○○ Collider 2DのMaterialに、今作ったPhysics2D Materialをセットする
Random.Range(min,max) // minには最小値,maxには最大値+1を渡す 整数を取得する Random.Range(0,10) //0以上10未満の値からランダムで値を返す 小数を取得する Random.Range(0.0f,0.1f) // 0.0以上0.1以下の値からランダムで値を返す
File -> Build Settings -> Player Settings -> Resolution and Presentation -> Allowed Orientations For Auto Rotation 縦置きの場合は、Landscapeチェックを外し、横置きの場合はPortraitのチェックを外す。
カメラがオブジェクトを追跡してスクロール 画面の中心でスクロールさせたいキャラクタ(プレイヤー等)のスクリプトのUpdateメソッドに追加: Camera.main.transform.position = new Vector3 (transform.position.x, transform.position.y, -10); ※Main Cameraオブジェクトを選択し、Tag「MainCamera」が設定されているか確認すること カメラが強制スクロール メインカメラのスクリプトのUpdateメソッドに追加(例では徐々に右側へスクロールする): transform.position += new Vector3 (0.01f, 0, 0);
File -> New Sceneで別のシーンを作成する ただし、File→Build Settingsにもそのシーンを追加しておくこと Application.LoadLevel("シーン名"); でそのシーンに移動できる
(上記「複数のシーン(面)を作る」も参考にすること) mainのほかにタイトル画面とゲームオーバー画面用のシーンを2つ作成する ここでは title , gameover とする。 適当なスクリプトを作成(ここではGameStateと名前をつける)に、staticなフィールド変数leftを追加 public class GameState { public static int left; } titleでは、適当なオブジェクトに適当なスクリプトを追加し、 GameState.left=3; を実行する。 mainでは、ミスした(残機が1つへる状況になった)ときに、GameState.leftの値を1減らし、 GameState.leftが0より大きい場合は、mainを読み込む。 0以下の場合は、gameoverを読み込む。
-スクリプトに、static変数でint型のフィールドscoreを作成。 -メソッドの判定条件内(例えば衝突判定条件のif文内)などに、scoreの値を増やす記述をする。 -scoreの内容を画面に表示する。 --例:このスクリプトを関連付けているオブジェクトが、タグEnemyとぶつかった場合にスコアが増える。 public static int score = 0; void Update () { var g = GameObject.Find("mytext"); var t = g.GetComponent<UnityEngine.UI.Text> (); t.text = score.ToString(); } void OnCollisionEnter2D(Collision2D collision){ if(collision.gameObject.tag=="Enemy"){ score++; } } -public static とすることで、他のクラスからもこの変数を変更・参照できるようになる。 --他のクラスからscoreの値を変更・参照したい場合には、クラス名.scoreとする。 ---例:countクラスにあるscoreの値をマウスが押されているときに増やす。 if (Input.GetMouseButton (0)) { count.score++; } -キャラクタなどに体力を設定する場合には、scoreの宣言と同じように、変数hpを用意する。 --衝突判定の中でhpの値を減らし、hpが0以下になった場合にプレイヤーを消す。 ---詳しくは「衝突判定を行う(衝突したキャラや自分を消す)」を参照。
「スコア表示」で変数scoreを追加したクラスに、rankという変数(配列)を追加する public static int[] rank=new int[3];//ランキングを3位まで格納 ゲームオーバーになった瞬間(あるいは、Application.LoadLevelでゲームをやり直す瞬間)に、 ランクインの処理を行なう。 if (score > rank [2]) {//もし現在のスコアがランキングが最下位より大きかったら rank [2] = score;//とりあえず最下位にランクイン //rankを並び替え for (int i = rank.Length-1; i>0; i--) { for (int j = 0; j < i; j++) { if (rank [j] <= rank [j+1]) { int c=rank [j]; rank [j] = rank [j + 1]; rank [j + 1] = c; } } } } -ランキング表示用のテキストオブジェクトをランキングのエントリ数(1位から3位までなら3つ)だけ作成する -ランキング表示のためのスクリプトを作成する public class Rank : MonoBehaviour { public int index;//順位をあらわす数値。0が1位 void Start () { } void Update () { var t=GetComponent<UnityEngine.UI.Text> (); t.text = "Rank "+index+"=" + XXXXX.rank [index];//XXXXXは、rank配列を宣言したクラスの名前にする } } このスクリプトをテキストオブジェクトに追加し、indexの値をそれぞれ設定する。
void Update () { //テキストのオブジェクトを取得 var g = GameObject.Find("テキストオブジェクトの名前(mytextなど)"); var o = g.GetComponent<UnityEngine.UI.Text> (); //経過時間を取得 var tt = Mathf.Floor(Time.timeSinceLevelLoad); //テキストの内容を経過時間に o.text = tt.ToString(); } Time.timeSinceLevelLoadで経過時間を取得できる。取得する値はfloat型。 float型における小数点以下の切り捨てはMathf.Floor()で行える。 小数点以下も表示したい場合は、そのまま var tt = Time.timeSinceLevelLoad; Text形式として表示する場合には.ToString()を付けて値を文字化するのを忘れずに。
-ジャンプさせるキャラクタのスクリプトに、int型のフィールド jumpcountを作成。最初は値を1(※)で初期化 -マウス等が押されたときに、上方向に力を加える(「力を加える」参照) --ただし、上に力が加わるのは jumpcountが0より大きいときのみとする。 --ジャンプしたときには、jumpcountを1減らす -「衝突判定」を用いて、床にあたったらjumpcountを1(※)にする (※)の部分を2にすると2段ジャンプができる
「ジャンプ」も参照。 ジャンプさせるキャラクタのスクリプトに記述。 int jumpcount = 1; // ジャンプできる回数「ジャンプ」を参照 int jumptime = 0; // ジャンプし続けられる時間 void Update () { // ジャンプ可能なときにタッチされたら、jumptimeを10にする if (Input.GetMouseButtonDown(0) && jumpcount >= 1) { jumpcount--; jumptime = 10; } // タッチされている間jumptimeが0より大きいなら、上方向に力を加える if (Input.GetMouseButton (0) && jumptime > 0) { jumptime--; var r = GetComponent<Rigidbody2D> (); r.AddForce (new Vector2 (0, 1), ForceMode2D.Impulse); } // タッチされていなければ、jumptimeは0になる if (!Input.GetMouseButton (0)) { jumptime = 0; } } // 床と接触したときの処理(ジャンプカウントをリセットする) // …… //「衝突判定」を参照 「ジャンプ」の要素に加え、ジャンプし続けられる時間(上方向に力を加え続ける時間)を表す変数jumptimeを用意する。 このjumptimeの値を変更することで、ジャンプし続けられる時間を設定できる。 タッチされている間jumptimeが0より大きいなら、上方向に力を加え続け、jumptimeを減らす。 jumptimeが0以下になると、タッチし続けていても力が加わらず、自然落下を始める。 また、AddForce関数の値を変えることで、一フレームの間にどれだけ上に力を加えるかを設定できる。
OnCollisionEnter2Dで衝突判定をしたときに,衝突(接地)した点を取得できる.これを覚えておくことで,ジャンプ時にかかる力の向きを変更できる. (斜めの床でジャンプしたら斜めにジャンプする) using UnityEngine; using System.Collections; public class Neko : MonoBehaviour { // Use this for initialization void Start () { } // cp: 着地点を覚えておく変数.着地点がない(つまり,空中にいる)場合はnullが入っている Collision2D cp; // Update is called once per frame void Update () { if (Input.GetMouseButtonDown (0) ) {//ボタンが押されたとき if (cp!=null) { var r = GetComponent<Rigidbody2D> (); //自分の位置から接地した場所を引き算 → ジャンプしたときにかかる力 var force = new Vector2 (transform.position.x, transform.position.y) - cp.contacts[0].point; r.AddForce (force*5, ForceMode2D.Impulse);//力を加える(掛け算の値でジャンプ力を調節) } } } void OnCollisionStay2D(Collision2D c) { //床に衝突したとき:着地点を覚えておく cp=c; } void OnCollisionExit2D(Collision2D c) { //床から離れたとき:着地点をnullにする cp = null; } }
*「重力を変更する」を参考に重力を0にする。 *画面の四隅に壁のオブジェクトを配置する(BoxCollider)。 *ボールを作成(CircleCollider、RigidBody) *壁とボールの反発係数を1にする。
シーソー・フリッパー・バット等にしたいオブジェクトにPhysics2D -> Hingejoint 2Dを追加する (予めRigidBodyとBoxColliderも追加しておくこと) -Enable Collision: 衝突判定を行なうにはチェックを入れる -Anchor:回転の中心(オブジェクトの中心からの相対位置)。フリッパーの場合Xの値を正の値(右側)や負の値(左側)にする -Connected Anchor: 回転の中心(絶対座標) -Use Limits: 回転角の制限。Lower Angleに最小値 Upper Angleに最大値 ※スクリプトを加える前に、Use Limitの角度を調整しておくこと(下に少し傾いたところで止まるようにする) スクリプトから回転を加えるには var rigidbody2D=gameObject.GetComponent<Rigidbody2D> (); rigidbody2D.AddTorque(回転力); //回転力:正なら左回転・負なら右回転 例:ボタンを押したときに回転を加える if (Input.GetMouseButton (0)) { var rigidbody2D=gameObject.GetComponent<Rigidbody2D> (); rigidbody2D.AddTorque(-200); } ※補足 AnchorとConnected Anchorの座標を入力して回転の中心を決めることが難しい場合は、 1.空のオブジェクトを作成後、そのオブジェクトにRigidBodyを追加。 2.そのオブジェクトのRigidBodyのIs Kinematicにチェックを入れる。 3.回転させたいオブジェクトのHingejoint 2DのConnected Rigid Bodyの欄にそのオブジェクトをドラッグする。 これにより、回転させたいオブジェクトは、空のオブジェクトを中心に回転するようになる。
上記「シーソー・フリッパー・バット等(固定された軸を中心に回転するオブジェクト)」を参考に、 シーソーを1つ作る。ここではこのシーソーをbaseFloorという名前で作る。 もう一つ、BoxCollider を追加したオブジェクトを作る。ここではfloorという名前にする。 floorの回転角度 をbaseFloorの回転角度にあわせるには、floorにスクリプトを追加し、次のように記述する void Update () { var g=GameObject.Find ("baseFloor"); transform.rotation=g.transform.rotation; }
スクリプトを作って void Update () { float z = transform.eulerAngles.z; //ラジアンに変換 z = Mathf.PI * z / 180; transform.position += new Vector3 (Mathf.Cos(z)*0.1f, Mathf.Sin(z)*0.1f, 0); } transform.eulerAnglesでオブジェクトのInspectorで設定した角度を取得できる。 その角度をラジアンに変換して、x軸とy軸それぞれの移動方向を計算し加算する。
スクリプトを作って void Update () { Vector3 pos = Input.mousePosition; Vector3 p= Camera.main.ScreenToWorldPoint (pos); transform.position = new Vector3(p.x,p.y,0); } でオブジェクトがタッチした場所に移動する。 Camera.main.ScreenToWorldPoint(pos)と経由するのは作品全体の座標を、 カメラ内(Android画面上)の座標に変換を行っているため。 ※Main Cameraオブジェクトを選択し、Tag「MainCamera」が設定されているか確認すること
スクリプトを作って float t; float speedX = 0; float speedY = 0; float toX; float toY; // Use this for initialization void Start () { } // Update is called once per frame void Update () { Vector3 pos = Input.mousePosition; pos = Camera.main.ScreenToWorldPoint (pos); //ここでスピードを加算 transform.position += new Vector3 (Mathf.Cos (t) * speedX, Mathf.Sin (t) * speedY, 0); if (Input.GetMouseButtonDown(0)) { toX = pos.x; toY = pos.y; t = Mathf.Atan2 (pos.y - transform.position.y, pos.x - transform.position.x); speedX = 0.2f; //この値を変えるとスピードが変化する。 speedY = 0.2f; } //タッチした場所に近づいたら静止 if ((Mathf.Abs (toX - transform.position.x)<speedX) && (Mathf.Abs (toY - transform.position.y)<speedY)) { speedX = 0; speedY = 0; } } Mathf.Atan2 (pos.y - transform.position.y, pos.x - transform.position.x)とすると、 オブジェクトの場所とクリックした場所の位置を元に、オブジェクトの場所とクリックした場所のなす角度を取得できる。 また、transform.position += new Vector3 (Mathf.Cos (t) * speedX, Mathf.Sin (t) * speedY, 0)で、 取得した角度から、x軸方向とy軸方向の移動量を計算して、現在のオブジェクトの位置に加算している。 Mathf.Abs (値)とすると値の絶対値が取得できるので、目的地近くにオブジェクトの座標がある場合に、オブジェクトのスピードを0にすることで、タッチ場所に到着したら、動きが止まるようになる。 ※移動量の誤差の関係で、近づいても静止の条件に当てはまらず、オブジェクトが行き過ぎてしまう場合には、範囲を広めに修正する ※Main Cameraオブジェクトを選択し、Tag「MainCamera」が設定されているか確認すること
// Update is called once per frame void Update () { Vector3 mpos = Input.mousePosition;//マウスの位置(スクリーン座標) Vector3 mposw = Camera.main.ScreenToWorldPoint (mpos);//マウスの位置(ワールド座標) if (transform.position.x < mposw.x) { transform.position += new Vector3 (0.1f, 0, 0); } if (transform.position.x > mposw.x) { transform.position -= new Vector3 (0.1f, 0, 0); } }
物理運動や衝突を検知させながら移動させたい場合、速度を設定しながら移動させる void Update() { Vector3 pos = Input.mousePosition; Vector3 p= Camera.main.ScreenToWorldPoint (pos); var r = GetComponent<Rigidbody2D> (); r.velocity = p - transform.position; } ※Main Cameraオブジェクトを選択し、Tag「MainCamera」が設定されているか確認すること
void OnMouseDown(){ Destroy (gameObject); } このスクリプトを関連付けているオブジェクトがタッチされたときに、そのオブジェクトを消す。 オブジェクトには何らかのColliderをつけておくこと
void Start () { Vector3 pos = Input.mousePosition; Vector3 p= Camera.main.ScreenToWorldPoint (pos); var t = Mathf.Atan2 (p.y - transform.position.y, p.x - transform.position.x); var r=GetComponent<Rigidbody2D>(); r.AddForce(new Vector2(Mathf.Cos (t)*2, Mathf.Sin (t)*2), ForceMode2D.Impulse); } このスクリプトを関連付けているオブジェクト(弾)が生成されたときにタッチした方向へ飛ぶ。 タッチした場所を取得して、Mathf.Atan2()でオブジェクトの現在の位置との成す角を計算。 Mathf.Cos (t)*2はx軸方向に加える力の強さ、Mathf.Sin (t)*2はy軸方向に加える力の強さ、 掛ける値を変えることで力の強さを変更できる。 (「弾を撃つ」、「力を加える」、「タッチした場所に移動」も参照のこと) ※Main Cameraオブジェクトを選択し、Tag「MainCamera」が設定されているか確認すること
void Start () { GameObject neko=GameObject.Find ("neko"); Vector3 pos = neko.transform.position; var t = Mathf.Atan2 (pos.y - transform.position.y, pos.x - transform.position.x); var r=GetComponent<Rigidbody2D>(); r.AddForce(new Vector2(Mathf.Cos (t)*2, Mathf.Sin (t)*2), ForceMode2D.Impulse); } このスクリプトを関連付けているオブジェクト(弾)が生成されたときに指定したオブジェクトに向けて飛ぶ。 (例では、nekoというオブジェクトに向けて一直線に弾が飛ぶ) (「弾を撃つ」、「力を加える」、「タッチした場所に移動」「タッチした場所をめがけて弾が移動する」も参照のこと) なお,物理オブジェクトでない場合は,Updateメソッド内で同様の処理を行う(次の「物理オブジェクトでないキャラクタを移動させる」も参照) void Update () { GameObject neko=GameObject.Find ("neko"); Vector3 pos = neko.transform.position; var t = Mathf.Atan2 (pos.y - transform.position.y, pos.x - transform.position.x); transform.position+=new Vector3(Mathf.Cos (t)*2, Mathf.Sin (t)*2, 0); }
transform.position += new Vector3 (0.2f, 0, 0); Vector3の中身は(xの移動量,yの移動量,zの移動量)
画像を切り替えたいオブジェクトにスクリプトを追加する。 SpriteRenderer MainSpriteRenderer; public Sprite imageA; // 一つ目の画像 public Sprite imageB; // 二つ目の画像 void Start () { MainSpriteRenderer = gameObject.GetComponent<SpriteRenderer>(); } // この関数が呼ばれたとき、オブジェクトの画像をimageAに切り替える。 void ChangeA() { MainSpriteRenderer.sprite = imageA; } // この関数が呼ばれたとき、オブジェクトの画像をimageBに切り替える。 void ChangeB() { MainSpriteRenderer.sprite = imageB; } 追加後、このスクリプトのInspectorのimageA,imageBの欄に、画像をドラッグ&ドロップすれば準備完了。 Update関数などの適切な場所で、ChangeAまたはChangeBの関数を呼び出せば、呼び出されたタイミングでオブジェクトの画像がそれぞれに切り替わる。
void OnBecameInvisible() { Destroy (this.gameObject); } このスクリプトを関連付けているオブジェクトが画面外に出たときに、そのオブジェクトは消滅する。
1.Rigidbodyを二つのオブジェクトに設ける。 2.二つのオブジェクトの Rigidbody の Gravity Scale を0にする。 3.片方のオブジェクトに Inspector から Add Component -> Physics2D -> Distance Joint を追加。 4.Distance Joint の Connected Rigid Body の欄に、もう片方のオブジェクトを Hierarchy からドラッグして追加。 5.Distance Joint の Distance の欄でひもの長さを設定。 →これで、片方のオブジェクトが移動したときに、もう片方のオブジェクトがそれに引っ張られる。 6.1.Distance Joint の Max Distance Only にチェックを入れるとオブジェクト間の引っ張り合いがひものようになる。 6.2.Distance Joint の Max Distance Only にチェックを入れないととオブジェクト間の引っ張り合いが棒のようになる。
rigidbody2dを追加したオブジェクトにおいて、次のようにすると速度が変えられる。 var rigidbody2D=gameObject.GetComponent<Rigidbody2D> (); rigidbody2D.velocity = new Vector2(x方向, y方向); 例: // Use this for initialization void Start () { //最初の移動方向を決める var rigidbody2D=gameObject.GetComponent<Rigidbody2D> (); rigidbody2D.velocity = new Vector2 (Random.Range(-3,3), Random.Range(-3,3)); } // Update is called once per frame void Update () { var rigidbody2D=gameObject.GetComponent<Rigidbody2D> (); if (Random.Range (0, 100) < 5) {// 5%の割合で向きを変える rigidbody2D.velocity = new Vector2 (Random.Range (-3, 3), Random.Range (-3, 3)); } if (transform.position.x < -2) {//左にはみ出そうなときに、速度を変更して右に移動するようにする rigidbody2D.velocity = new Vector2 (Random.Range (1, 3), Random.Range (-3, 3)); } // 同様に、右、上、下にはみ出そうなときの処理も書く }
スクリプトに次を追加する。 bool colliding=false; void OnCollisionEnter2D(Collision2D c) { colliding = true; } void OnCollisionExit2D(Collision2D c) { colliding = false; } void Update() { if (colliding) { // 衝突しているときの処理 } else { // 衝突していないときの処理 } }
スクリプトを作って // 差の初期値 float offsetX = 0; float offsetY = 0; void Update () { Vector3 pos = Input.mousePosition; pos = Camera.main.ScreenToWorldPoint (pos); // ボタンが押されたとき、オフセット(差の初期値)に現在のマウスの値を代入 if (Input.GetMouseButtonDown(0)) { offsetX = pos.x; offsetY = pos.y; } // ボタンが押され続けている間、マウスが移動したら、マウスとオフセットとの差分だけ移動 if (Input.GetMouseButton(0)) { transform.position += new Vector3 (pos.x - offsetX, pos.y - offsetY, 0); offsetX = pos.x; offsetY = pos.y; } // ここから画面外に出ないようにする処理 // オブジェクトの座標を取得 Vector3 opos = transform.position; // 画面左下のワールド座標をビューポートから取得 Vector3 min = Camera.main.ViewportToWorldPoint(new Vector3(0, 0, 0)); // 画面右上のワールド座標をビューポートから取得 Vector3 max = Camera.main.ViewportToWorldPoint(new Vector3(1, 1, 1)); // オブジェクトの位置が画面内に収まるように制限をかける opos.x = Mathf.Clamp (opos.x, min.x, max.x); opos.y = Mathf.Clamp (opos.y, min.y, max.y); // 制限をかけた値をプレイヤーの位置とする transform.position = opos; } このスクリプトを関連付けているオブジェクトは、自身の位置とタッチした場所が違っていても、 タッチした場所からスライドした分だけそのオブジェクトも移動する。 始めに、画面のタッチされた座標をoffsetに格納しておく。 次に、スライドが行われた場合に、オブジェクトの現在の座標を、現在触れている座標とoffsetの差分だけ修正する。 画面外に出ないようにする処理では、画面の左下の座標をmin=(0,0,0)、右上の座標をmax=(1,1,1)と置いて、 関数Mathf.Clamp()を用いて、オブジェクトの座標がminとmaxの間に収まるようにし、オブジェクトの座標を修正している。 ※Main Cameraオブジェクトを選択し、Tag「MainCamera」が設定されているか確認すること
1.透過処理が行われているGIF形式のイメージをProjectとHierarchyとSceneに用意する。 2.Hierarchyのイメージ名 -> Inspector -> Add Component -> Physics2D -> Polygon Collider 2D 3.Sceneのイメージを見てみると、イメージの形に沿った当たり判定が作成されていることがわかる。 注意:イメージの透過部分と本体のしきいがはっきりしていない場合などは、綺麗な当たり判定が作成されないことがある。
破壊したときに出現させる破片オブジェクトをプレハブにしておく。 破壊されるオブジェクトのスクリプトに次のように追加する // 破壊されたら出現する破片オブジェクト public GameObject seed; void Update () { if(破壊されたら) { // 例では左右に破片のオブジェクトを飛ばす GameObject s1=Instantiate(seed,transform.position,Quaternion.identity) as GameObject; var rigidbody2D=s1.GetComponent<Rigidbody2D> (); rigidbody2D.velocity=new Vector2(5.0f,0); GameObject s2=Instantiate(seed,transform.position,Quaternion.identity) as GameObject; rigidbody2D=s1.GetComponent<Rigidbody2D> (); rigidbody2D.AddForce(new Vector2(-5.0f,0),ForceMode2D.Impulse); // 飛ばした後に自分自身をゲームから消す GameObject.Destroy(gameObject); } }
スクリプトを作って // マウスを押したときと離したときの座標 float startX; float startY; float endX; float endY; //マウスを押したときと離したときの時間 float startTime; float endTime; // タッチが行われているか bool isTouch = false; void Update () { Vector3 pos = Input.mousePosition; pos = Camera.main.ScreenToWorldPoint (pos); // マウスを押したとき if (Input.GetMouseButtonDown(0)) { isTouch = true; // 座標を取得 startX = pos.x; startY = pos.y; // 時間を取得 startTime = Time.time; } // マウスを離したとき if (Input.GetMouseButtonUp(0)) { if (isTouch) { // 座標を取得 endX = pos.x; endY = pos.y; // 時間を取得 endTime = Time.time; // 各軸のベクトル(移動量)は、各軸のマウスを離した位置と押した位置の差により取得できる // x軸のベクトル = endX - startX; // y軸のベクトル = endY - startY; // 押されていた時間は、マウスを離した時間と押した時間の差により取得できる // 押されていた時間 = endTime - startTime; // 例:移動量と押されていた時間を利用して、シュッ!って感じのフリックのみを検出する条件文 // 押されていた時間が0.1fより大きく0.3f未満だった場合かつ // x,yどちらかもしくは両方の移動量が1f以上だった場合のみフリックとみなす if (((0.1f < endTime - startTime) && (0.3f > endTime - startTime)) && ((1f < Mathf.Abs(endX - startX)) || (1f < Mathf.Abs(endY - startY)))) { // ここからシュッ!っとフリックされたときの処理 Debug.Log ("Flick!!"); // シュッ!っとフリックされたときの処理終わり } } isTouch = false; } } マウスを押したときと離したときのそれぞれの座標と時間を利用する。 フリックした分のベクトル(移動量)は、各軸のマウスを離した位置と押した位置の差により取得できる。 また、フリックした時間は、マウスを離した時間と押した時間の差により取得できることから、 フリックの種類(素早い・距離が長い)は、条件文を作成し、移動量と時間の範囲を設定することで、検出することができる。 ※Main Cameraオブジェクトを選択し、Tag「MainCamera」が設定されているか確認すること
敵のオブジェクトには、共通のTagを付けておく。 Updateメソッド内で敵のオブジェクトが存在しているかを確認する。 void Update () { // EnemyというTagのGameObjectが配列になって返ってくる。 GameObject[] objs=GameObject.FindGameObjectsWithTag ("Enemy"); // 返ってきた配列の長さを見ると、ゲーム上に敵が何体いるかを確認できる。 Debug.Log (objs.Length); } objs.Lengthが0になると、ゲーム上にそのキャラがいないことがわかる。
スクリプトの例は、画面中心を境に二つのオブジェクトを別々に動かすプログラム。 (中心より左側であればplayer1のオブジェクトがタッチした位置に移動、右側ではplayer2が同様の動きをする) public GameObject player1, player2; void Update () { // タッチされている数だけループ for (int i = 0; i < Input.touchCount; i++) { var id = Input.touches[i].fingerId; var pos = Input.touches[i].position; pos = Camera.main.ScreenToWorldPoint (pos); if (pos.x < 0) // 画面中心より左側のタッチではplayer1が動く player1.transform.position = pos; else // 画面中心より右側のタッチではplayer2が動く player2.transform.position = pos; } } このスクリプトのInspectorのplayer1,player2の欄に、それぞれのプレイヤーであるオブジェクトをドラッグ&ドロップする。 Input.touchCountで現在タッチされている数を取得し、その数分だけそれぞれの座標を取得する。 ※マルチタップの確認はスマホでしか行えないため時間がかかるので、デバッグ中は以下のようにマウス座標を利用するとよい。 (ただし、同時には動かせない) void Update () { //マウスの座標を取得 Vector3 mp = Input.mousePosition; Vector3 pos = Camera.main.ScreenToWorldPoint (mp); if (pos.x < 0) // 画面中心より左側のマウスの動きではplayer1が動く player1.transform.position = new Vector3(pos.x, pos.y, 0); else // 画面中心より右側のマウスの動きではplayer2が動く player2.transform.position = new Vector3(pos.x, pos.y, 0); } ※Main Cameraオブジェクトを選択し、Tag「MainCamera」が設定されているか確認すること
背景画像をassetsに追加し、シーンにその画像を追加する。 Sprite Rendererの項目の「Order in layer」にマイナスの値を設定すると、ほかのオブジェクトの背後に表示されるようになる。
var objs = GameObject.FindGameObjectsWithTag("mytag"); foreach (GameObject obj in objs) { //objについて処理を行なう }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class Drag : MonoBehaviour{ bool dragging=false;//ドラッグ中ならtrue Vector3 prev;// 直前のマウスの座標 void Update () { if (!dragging) { // ドラッグしていないときの動作 if (Input.GetMouseButtonDown (0)) { // マウスが押された点をposに代入 var pos = Input.mousePosition; pos = Camera.main.ScreenToWorldPoint (pos); pos.z = 0;// z座標をオブジェクトに合わせる // 押された点と自分の距離が近かったら,ドラッグ開始 if ((transform.position - pos).magnitude < 1) { Debug.Log ("Drag Start!"); prev = pos;//現在の点を覚える dragging = true; } } } else { // ドラッグ中の動作 var pos = Input.mousePosition; pos = Camera.main.ScreenToWorldPoint (pos); pos.z = 0;// z座標をオブジェクトに合わせる transform.position += (pos-prev); // 前の点との差分だけ動かす prev = pos;//前の点を現在の点に更新 // ボタンが離れたらドラッグ終了 if (!Input.GetMouseButton (0)) { Debug.Log ("Drag End!"); dragging = false; } } } void Start(){ } }
//プレイヤーのスクリプト using System.Collections; using System.Collections.Generic; using UnityEngine; public class Neko : MonoBehaviour { // プレイヤーキャラクターのスクリプトに追加 public static Listtrace=new List ();//位置の履歴を保存する配列 public static int followers = 0;// ついてきているキャラクターの数 //---- // Use this for initialization void Start () { } // Update is called once per frame void Update () { //---位置の履歴を追加 var p = transform.position; trace.Add(new Vector3(p.x,p.y,p.z)); if (trace.Count > followers * 60) {//古い履歴から消していく trace.RemoveAt (0); } //--- } } //ついてくるキャラクターのスクリプト using System.Collections; using System.Collections.Generic; using UnityEngine; public class Follower : MonoBehaviour { public int delay;//プレイヤーから何フレーム遅れてついてくるか void Start () { Neko.followers++; delay = Neko.followers * 60; } void Update () { var i = Neko.trace.Count - delay; if (i >= 0) { transform.position = Neko.trace [i]; } } }
アニメーションさせたい画像を用意し,Assetに追加する(この例では2枚). 次のようなスクリプトを作り,オブジェクトにスクリプトを追加する. Inspectorに pat1 と pat2 の欄ができるので,それぞれ画像をドラッグ&ドロップする. public class Animator : MonoBehaviour { SpriteRenderer MainSpriteRenderer; public Sprite pat1; public Sprite pat2; void Start () { MainSpriteRenderer = gameObject.GetComponent<SpriteRenderer>(); } int animCount=0; void Update () { if (animCount % 10 < 5) { MainSpriteRenderer.sprite = pat1; } else { MainSpriteRenderer.sprite = pat2; } animCount++; } }
// プレイヤーなど,操作するオブジェクトをA, AについていくオブジェクトをBとする // 次のスクリプトを作成・Buildを行う // Bにインスペクタ上でこのスクリプトを追加し, // 「target」にAをドラッグ // 「offset」のXとYにAの位置からのずれを設定 using System.Collections; using System.Collections.Generic; using UnityEngine; public class Sticker : MonoBehaviour { public GameObject target; public Vector3 offset; void Start () { } void Update () { transform.position = target.transform.position + offset; } }