キャットエスケープからクラウドクライムまでのアプリを分解しています。
//tips
//プレイヤを移動させるボタンの作成
ボタンの作成はUIのButtonから作成できる。
デバイスによってサイズの違いがあることを考慮し、ボタンが画面内に必ず表示されるようにcanvas内の子としてオブジェクトを作成し、rect transformのアンカーポイントを基に操作しやすい表示場所に決める。
Button内のText要素は削除。
一つの方向のボタンが作成できたらヒエラルキーのオブジェクト項目上右クリックでDuplicate複製ができるので、rect transformの項目を変更して操作しやすい場所に配置する。
ボタンが押された判定をプレイヤーに反映するためにPlayerControllerに
public void LButtonDown()
{
transform.Translate(-3,0,0);
}
public void RButtonDown()
{
transform.Translate(3,0,0);
}
これらのスクリプトを追加し、再度Buttonのインスペクターに戻り、上記処理を紐付けるためにOn Click()欄の+ボタンを押し、None(Object)にヒエラルキーからplayerドラッグアンドドロップしてプレイヤーと紐付け、さらに、これによりプレイヤーに紐づくメソッドを使用できるようになるのでNo FunctionのところからPlayerControllerのRButtonDown()を選ぶことで、ボタンとコントローラーとプレイヤーを紐づけることができる。
PlayerControllerでLButtonDown()にpublic修飾子をつけたのは、Buttonからメソッドを使用するためであることがわかる。
新たに複雑なスクリプトを書く必要がないので、このようなunityの便利機能を使いこなすと効率的に作業できる。
//Unity搭載の物理エンジンPhysicsの使用
Physicsはオブジェクトの落下や衝突などを複雑なスクリプトなしで動作させることができる便利ツール。
PhysicsはRigidbodyコンポーネントとColliderコンポーネントからなり、Rigidbodyは力の計算、Colliderでは当たり判定を扱う。
Rigidbodyの使用方法としては、配置したオブジェクトにAddComponent→Physics→Rigidbodyをアタッチすれば良い。
そうすると、アタッチされたオブジェクトは物理法則に従い、重力によって下に落ちる。
Colliderの使用方法としては、配置したオブジェクトにAddComponent→Physics→Circle Colliderなどをアタッチすれば良い。
オブジェクトの形状によって、円、四角、カプセルなどのどれで当たり判定をつけるかは判断する。
RigidbodyコンポーネントとColliderコンポーネントを搭載したcatを落下させて雲に立たせるためには、雲の方にも両方のコンポーネントが必要となる。
ただ、雲にもRigidbodayをそのまま適用してしまうと、雲にも重力が作用し、落下してしまうので、その場から動かさないために、RigidbodyのBodyTypeから重力などの演算を無視するKinematicに変更することでcatが中に浮いた雲の上に乗ることができるようになる。
//Physics使用時の移動方法は座標の書き換えではなく、力を加えて移動
Physics使用時の移動方法は通常時と異なり、力を加えて移動させる必要がある。
Rigidbody2D rigid2D;
float jumpForce = 680.0f;
Rigidbody2DコンポーネントのAddForceメソッドを用いてオブジェクトを動かすので、まずrigid2Dの変数を宣言し、その後に、GetComponent<Rigidbody2D>();で取得したアクセスを変数に入れ、スペースキーが押されたら、rigid2Dの中のAddForceメソッドが()内の値で実行される。
void Start()
{
this.rigid2D = GetComponent<Rigidbody2D>();
}
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
this.rigid2D.AddForce(transform.up * this.jumpForce);
}
}
ちなみにtransform.upは(0,1,0)のことを指す。
https://docs.unity3d.com/ScriptReference/Transform-up.html
左右に動かしたい場合には
Rigidbody2D rigid2D;
float walkForce = 30.0f;
float maxWalkSpeed = 2.0f;
void Update()
{
・・・
int key = 0;
if(Input.GetKey(KeyCode.RightArrow))key=1;
if(Input.GetKey(KeyCode.RightArrow))key=-1;
float speedx = Mathf.Abs(this.rigid2D.velocity.x);
if(speedx < this.maxWalkSpeed)
{
this.rigid2D.AddForce(transform.right * key * this.walkForce);
}
}
Mathf.Abs(数字)は()内の数字の絶対値を返すのでマイナスの数字の場合、マイナスをとることができる。
ここは方向ではなく力を表したいのでマイナスをとっている。
speedxがmaxスピードより小さければAddForceで力を加えている。
transform.rightをかけているのはkeyで右側を正の値としているからである。
Mathfはいろいろな使い方ができるようなので参考を下記に貼る。
ちなみに、if文の条件を満たした時に実行するスクリプトが一文のみの場合{}を省略できる。
//画像を反転させて動きを自然に見せる
プラスの力を右側方向に与えた場合、体が右向きであれば問題ないが、マイナスの力を左側方向に与えた場合、体は右を向いているのに左側に進む現象が生じる。
これは画像のscaleで操作することができ、
if(key != 0)
{
transform.localScale = new Vector3(key,1,1);
}
Keyが0ではないということは、キーボードの矢印が押された場合のことで、その場合1または-1が代入される。
x方向の拡大率を-1とするとx軸を軸に画像が反転するので、左方向を画像が向くことになる。
//Animationの復習
UnityでAnimationを作成する段取りは以前記述したが、細部の補足も踏まえて記述する。
まずUnityでAnimationを作成するシステムの名前はMecanimというものが使われている。これは名前だけ知っておけば問題ない。
実際はwindowからAnimationを作成していくが、Mecanimを通して、AnimationClipファイルの生成→AnimationControllerの生成→AnimationControllerがAnimatorコンポーネントにセット→指定オブジェクトにAnimatorコンポーネントがアタッチまでが自動で行われる。
歩いている画像を3種類切り替えるWalkのアニメーションをAnimationClipのCreateで作成する。
AddPropertyからSprite Render→Spriteを設定し、各画像をタイムラインにドラッグアンドドロップしていく。
アニメーション全体の長さを最後の画像の後に設定したいときに、画面左上のAdd Keyframeボタンを押すことで最終地点を作ることができる。
このアニメーションとプレイヤーのキー操作により発生する実際の移動をリンクさせるために、PlayerControllerの中でanimator.speedをオブジェクトのrigid2D.velocity.xとの関係を数式化する。
Animator animator;
void Start()
{
・・・
this.animator = GetComponent<Animator>();
}
void Update()
{
・・・
this.animator.speed = speedx/2.0f;
}
最終文でアニメーションの再生速度がプレイヤの移動速度に比例するようになっている。
//カメラをプレイヤに追従させる。
カメラをプレイヤの動きに追従させる場合にはスクリプトが必要でCameraControllerを作る必要がある。
public class CameraController : MonoBehaviour
{
GameObject player;
void Start()
{
this.player = GameObject.Find(“cat”);
}
void Update()
{
Vector3 playerPos = this.player.transform.position;
transform.position = new Vector
(transform.position.x, playerPos.y, transform.position.z);
}
}
スクリプトはシンプルで、まずplayer変数を宣言し、Findでオブジェクトと変数を連結させ、アクセスを手に入れ、そのアクセスを通して、playerの現時点のポジションを取得、それをカメラの座標に反映されるようにしている。
反映しているのはy座標のみで、xとzはそのままにしている。これはカメラをどう動かしたいかによって変える。