Unityでキャラの移動を制御する方法まとめ
19/02/11 14:33:27 19/02/17 19:56:48
Unityではキャラを自由に動かすことができますが、自由に動かし過ぎるとゲームが簡単すぎて面白くなくなってしまうかもしれません。ゲームにもよりますが、たとえばアクションゲームで完全に自由自在に動けたら難易度を上げるためのオブジェクトや敵の設定が大変になります。
そこでキャラの移動を制御するのが一般的で、ほとんどのゲームでそのようになっています。無制限にキャラを動かせるゲームがあったらやってみたいですが、おそらくゲーム性がなくなってすぐに面白くなくなるでしょう。
制限があるからこそ面白いのです。そこでこのページでは、Unityでキャラの移動を制御する方法を紹介します。
Mathf.Clampを使う
Mathf.Clampはオブジェクトの動きを制御する関数で、引数を含めた文法は以下のようになります。
Mathf.Clamp(value, min, max);
オブジェクトの指定と最小値、最大値を指定すればそのオブジェクトはその範囲内でしか動けなくなります。コード自体は自分で書いていますが、Unityで用意されているクラス関数を使えば簡単に制御できてしまいます。
サンプルコードは以下です。キャラの移動制御を含め全体のコードをまず紹介しますが、あとから制御部分のみのピックアップも紹介します。そのため下のコードはざっと見て、後述するキャラ制御の部分を重点的に確認してください。
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
GameObject Player;
GameObject wall_Left;
GameObject wall_Right;
GameObject wall_Bottom;
GameObject wall_Top;
bool MoveRight;
bool MoveLeft;
void Start () {
Player = GameObject.Find ("Player");
wall_Left = GameObject.Find ("Wall Left");
wall_Right = GameObject.Find ("Walll Right");
wall_Bottom = GameObject.Find ("Wall Bottom");
wall_Top = GameObject.Find ("Wall Top");
}
void Update () {
if (Input.GetKey (KeyCode.RightArrow)) {
MoveRight = true;
MoveLeft = false;
} else if (Input.GetKey (KeyCode.LeftArrow)) {
MoveLeft = true;
MoveRight = false;
}else {
MoveRight = false;
MoveLeft = false;
}
Player.transform.position = (new Vector3(Mathf.Clamp(Player.transform.position.x, wall_Left.transform.position.x, wall_Right.transform.position.x),
Mathf.Clamp(Player.transform.position.y, wall_Bottom.transform.position.y, wall_Top.transform.position.y),
Player.transform.position.z));
}
void FixedUpdate(){
if (MoveRight) {
Player.GetComponent ().velocity = (transform.up * 2);
Player.transform.Rotate (new Vector3 (0, 0, -5));
} else if (MoveLeft) {
Player.GetComponent ().velocity = (transform.up * 2);
Player.transform.Rotate (new Vector3 (0, 0, 5));
} else {
Player.GetComponent ().velocity = (transform.up * 0);
}
}
}
詳細に把握する必要はありませんが、キャラクターが動いて壁があったらそれ以上進めないようなコードになっていることがなんとなくわかるかと思います。
実際に作りこむときは細かくトレースした方が良いですが、最初はとりあえずざっくり把握するだけで良いかと思います。
全体の流れは上記の通りですが、このなかでキャラ制御の部分は以下です。
Player.transform.position = (new Vector3(Mathf.Clamp(Player.transform.position.x, wall_Left.transform.position.x, wall_Right.transform.position.x),
Mathf.Clamp(Player.transform.position.y, wall_Bottom.transform.position.y, wall_Top.transform.position.y),Player.transform.position.z));
rigidbodyを使ってキャラクターを動かす
rigidbodyは物理演算を行うためのツールですが、キャラの移動を制御しつつなおかつ物理演算も扱ったサンプルコードは以下です。
using UnityEngine;
using System.Collections;
public class RigidChara : MonoBehaviour {
private Animator animator;
private Vector3 velocity;
[SerializeField]
private float jumpPower = 5f;
[SerializeField]
private Transform charaRay;
[SerializeField]
private float charaRayRange = 0.2f;
private bool isGround;
private Vector3 input;
[SerializeField]
private float walkSpeed = 1.5f;
private Rigidbody rigid;
private bool isGroundCollider = false;
void Start () {
animator = GetComponent<Animator>();
velocity = Vector3.zero;
isGround = false;
rigid = GetComponent <Rigidbody> ();
}
void Update () {
if(!isGroundCollider) {
if(Physics.Linecast(charaRay.position, (charaRay.position - transform.up * charaRayRange))) {
isGround = true;
rigid.useGravity = true;
} else {
isGround = false;
rigid.useGravity = false;
}
Debug.DrawLine(charaRay.position, (charaRay.position - transform.up * charaRayRange), Color.red);
}
if(isGroundCollider || isGround) {
if(isGroundCollider) {
velocity = Vector3.zero;
animator.SetBool("Jump", false);
rigid.useGravity = true;
} else {
velocity = new Vector3(0f, velocity.y, 0f);
}
input = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
if(input.magnitude > 0f) {
animator.SetFloat("Speed", input.magnitude);
transform.LookAt(transform.position + input);
velocity += input.normalized * walkSpeed;
} else {
animator.SetFloat("Speed", 0f);
}
if(Input.GetButtonDown("Jump")
&& !animator.GetCurrentAnimatorStateInfo(0).IsName("Jump")
&& !animator.IsInTransition(0) ) {
animator.SetBool("Jump", true);
velocity.y += jumpPower;
rigid.useGravity = false;
}
}
if (!isGroundCollider && !isGround) {
velocity.y += Physics.gravity.y * Time.deltaTime;
}
}
void FixedUpdate() {
rigid.MovePosition(transform.position + velocity * Time.deltaTime);
}
void OnCollisionEnter() {
Debug.DrawLine(charaRay.position, charaRay.position + Vector3.down, Color.blue);
if (Physics.Linecast (charaRay.position, charaRay.position + Vector3.down, LayerMask.GetMask ("Field", "Block"))) {
isGroundCollider = true;
} else {
isGroundCollider = false;
}
}
void OnCollisionExit() {
isGroundCollider = false;
}
}
長めのサンプルコードですが、物理演算処理も行っています。以上、キャラの移動を制御する方法を紹介しました。
【Unity関連記事】
▼Unityの基礎編
・ 【unityのフリーランス求人・案件情報】エンジニア需要や開発単価、未経験でもいける?
・ 【unity入門】ゲーム開発だけじゃない、Unityで出来ること
▼Unityの外部アセット、リソース編
・ UnityでMMDモデルを自由自在に動かしてみよう!
・ Unity adsを使って簡単に広告を導入しよう
・ Unityのアセットストアの上手な使い方
・ Unityで作られているARアプリをまとめてみました
▼Unityのコンポーネント編
・ Unityのrigidbodyを使って物理演算を導入してみよう
・ コードを使わずにUnityでキャラ追従のカメラを作る方法
・ Unityで簡単にアニメーションを作成する方法をまとめました
・ Unityでオブジェクトを回転させる方法をわかりやすくまとめました
・ Unityのtransformを使ってオブジェクトの座標や回転を操作する
・ Unityのアニメーターを簡単に作成する方法まとめ
・ UnityのShaderの解説と使い方まとめました
・ Unityで「当たり判定」(衝突判定)を付ける方法
・ Unityのgetcomponentの上手な使い方と使用時の注意点まとめ
・ (この記事)Unityでキャラの移動を制御する方法まとめ
・ Unityのraycastを使って出来ることをまとめました
▼Unityのデフォルト機能、ゲーム製作編
・ blenderで作ったオブジェクトをUnityで組み込んでみよう
・ Unityのコルーチンとは?使い方をまとめました
・ Unityで作られているRPGゲームを作るための6つのステップ
・ Unityのパーティクルを使って演出できるエフェクト例
・ UnityでのUIデザインの基礎をまとめてみました
・ Unityのcloud buildの便利な点をまとめました
・ Unityを使って半日でFPSゲームを作ってみよう
人気記事