Help us understand the problem. What is going on with this article?

【Unity】Rigidbodyを用いたキャラ操作の実装

概要

UnityでRigidbodyとColliderを用いたキャラクターの操作を実装します。
テンプレ的に6パターン作ってみました。

移動方法その1

まずはふつうの移動。
Locomotion1.csというC#スクリプトを作成し、操作したいキャラクターにアタッチします。
Rigidbodyで重力を付け、Colliderで衝突と着地判定しています。
十字キーで前後左右移動

Locomotion1.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Locomotion1 : MonoBehaviour {

    public float speed = 3f;
    public float jumpSpeed = 3f;

    private Rigidbody rb;
    private float h, v;
    private Vector3 moveDirection = Vector3.zero;

    void Start() {
        //Rigidbodyを取得し,回転しないように固定
        rb = GetComponent<Rigidbody>();
        rb.constraints = RigidbodyConstraints.FreezeRotation;
    }

    void Update() {

        h = Input.GetAxis ("Horizontal");
        v = Input.GetAxis ("Vertical");

        if (h != 0 || v != 0) {
            moveDirection = speed * new Vector3 (h, 0, v);
            moveDirection = transform.TransformDirection (moveDirection);
            rb.velocity = moveDirection;
        }
        if (Input.GetButtonDown ("Jump")) {
            rb.velocity = new Vector3 (rb.velocity.x, 5, rb.velocity.z);
        }
    }

}

移動方法その2

こちらはLocomotion1.csの操作方法をすこし変更したものです。
Locomotion2.csというC#スクリプトを作成し、操作したいキャラクターにアタッチします。
十字キーで前後移動
マウスで回転と視点移動

Locomotion2.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Locomotion2 : MonoBehaviour {

    public float speed = 3f;
    public float jumpSpeed = 3f;
    public float rotateSpeed = 3.0F;
    public float camRotSpeed = 5.0f;

    private float lookUpAngle;
    private Rigidbody rb;
    private float h, v;
    private float mX, mY;
    private Vector3 moveDirection = Vector3.zero;

    void Start() {
        //Rigidbodyを取得し,回転しないように固定
        rb = GetComponent<Rigidbody>();
        rb.constraints = RigidbodyConstraints.FreezeRotation;
    }

    void Update() {

        h = Input.GetAxis ("Horizontal");
        v = Input.GetAxis ("Vertical");
        mX = Input.GetAxis ("Mouse X");
        mY = Input.GetAxis ("Mouse Y");

        //カメラのみ上下に回転させる,180-140=60より上下60度まで見ることができる
        lookUpAngle = Camera.main.transform.eulerAngles.x - 180 + camRotSpeed * mY;
        if (Mathf.Abs (lookUpAngle) > 140)
            Camera.main.transform.Rotate (new Vector3 (camRotSpeed * mY, 0, 0));

        gameObject.transform.Rotate (new Vector3 (0, rotateSpeed * mX, 0));

        if (h != 0 || v != 0) {
            moveDirection = speed * new Vector3 (h, 0, v);
            moveDirection = transform.TransformDirection (moveDirection);
            rb.velocity = moveDirection;
        }
        if (Input.GetButtonDown ("Jump")) {
            rb.velocity = new Vector3 (rb.velocity.x, 5, rb.velocity.z);
        }
    }

}

移動方法その3

今度はRayを使って着地判定します。
Locomotion3.csというC#スクリプトを作成し、操作したいキャラクターにアタッチします。
Rigidbodyで重力を付け、Colliderで衝突。
地面に向けて直線のRayを飛ばし着地判定しています。
台の上に乗ったときに端で着地判定ができずにフリーズしてしまうことがあります。
十字キーで前後左右移動

Locomotion3.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Locomotion3 : MonoBehaviour {

    public float speed = 3f;
    public float jumpSpeed = 3f;

    private Rigidbody rb;
    private float h, v;
    private Vector3 moveDirection = Vector3.zero;
    private bool isGrounded = false;

    void Start() {
        rb = GetComponent<Rigidbody>();
        rb.constraints = RigidbodyConstraints.FreezeRotation;
    }

    void Update() {

        h = Input.GetAxis ("Horizontal");
        v = Input.GetAxis ("Vertical");

        //足元から下へ向けてRayを発射し,着地判定をする
        isGrounded = Physics.Raycast (gameObject.transform.position + 0.1f * gameObject.transform.up, -gameObject.transform.up, 0.15f);
        //デバッグ用にシーンにRayを表示する
        Debug.DrawRay (gameObject.transform.position + 0.1f * gameObject.transform.up, -0.15f*gameObject.transform.up, Color.blue);

        if (isGrounded || Mathf.Abs (rb.velocity.y) < 0.01f) {
            if (h != 0 || v != 0) {
                moveDirection = speed * new Vector3 (h, 0, v);
                moveDirection = transform.TransformDirection (moveDirection);
                rb.velocity = moveDirection;
            }
            if (Input.GetButtonDown ("Jump")) {
                rb.velocity = new Vector3 (rb.velocity.x, 5, rb.velocity.z);
            }
        }

    }

}

移動方法その4

操作方法3にマウス操作を追加します。
Locomotion4.csというC#スクリプトを作成し、操作したいキャラクターにアタッチします。
Rigidbodyで重力を付け、Colliderで衝突。
地面に向けて直線のRayを飛ばし着地判定しています。
やはり台の上に乗ったときに端で着地判定ができずにフリーズしてしまうことがあります。
十字キーで前後左右移動
マウスで回転と視点移動

Locomotion4.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Locomotion4 : MonoBehaviour {

    public float speed = 3f;
    public float jumpSpeed = 3f;
    public float rotateSpeed = 1.5f;
    public float camRotSpeed = 3.5f;

    private float lookUpAngle;
    private Rigidbody rb;
    private float h, v;
    private float mX, mY;
    private Vector3 moveDirection = Vector3.zero;
    private bool isGrounded = false;

    void Start() {
        rb = GetComponent<Rigidbody>();
        rb.constraints = RigidbodyConstraints.FreezeRotation;
    }

    void Update() {

        h = Input.GetAxis ("Horizontal");
        v = Input.GetAxis ("Vertical");
        mX = Input.GetAxis ("Mouse X");
        mY = Input.GetAxis ("Mouse Y");

        //カメラのみ上下に回転させる,180-140=60より上下60度まで見ることができる
        lookUpAngle = Camera.main.transform.eulerAngles.x - 180 + camRotSpeed * mY;
        if (Mathf.Abs (lookUpAngle) > 140)
            Camera.main.transform.Rotate (new Vector3 (camRotSpeed * mY, 0, 0));

        //足元から下へ向けてRayを発射し,着地判定をする
        isGrounded = Physics.Raycast (gameObject.transform.position + 0.1f * gameObject.transform.up, -gameObject.transform.up, 0.15f);
        //デバッグ用にシーンにRayを表示する
        Debug.DrawRay (gameObject.transform.position + 0.1f * gameObject.transform.up, -0.15f*gameObject.transform.up, Color.blue);

        if (isGrounded || Mathf.Abs (rb.velocity.y) &l 0.01f) {
            gameObject.transform.Rotate (new Vector3 (0, rotateSpeed * mX, 0));
            if (h != 0 || v != 0) {
                moveDirection = speed * new Vector3 (h, 0, v);
                moveDirection = transform.TransformDirection (moveDirection);
                rb.velocity = moveDirection;
            }
            if (Input.GetButtonDown ("Jump")) {
                rb.velocity = new Vector3 (rb.velocity.x, 5, rb.velocity.z);
            }
        }

    }

}

移動方法その5

今度は球状のRayを使って着地判定します。
Locomotion5.csというC#スクリプトを作成し、操作したいキャラクターにアタッチします。
Rigidbodyで重力を付け、Colliderで衝突。
地面に向けて球状のRayを飛ばし着地判定しています。
おそらく最もきれいに着地判定が可能。
十字キーで前後左右移動

Locomotion5.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Locomotion5 : MonoBehaviour {

    public float speed = 3f;
    public float jumpSpeed = 3f;

    private Rigidbody rb;
    private float h, v;
    private Vector3 moveDirection = Vector3.zero;
    private bool isGrounded = false;
    private Ray ray;

    void Start() {
        rb = GetComponent<Rigidbody>();
        rb.constraints = RigidbodyConstraints.FreezeRotation;
    }

    void Update() {

        h = Input.GetAxis ("Horizontal");
        v = Input.GetAxis ("Vertical");

        //足元から下へ向けて球状のRayを発射し,着地判定をする
        //rayで中心と方向を指定,SphereCastで球の半径と,球を飛ばす距離を指定
        ray = new Ray(gameObject.transform.position+0.18f*gameObject.transform.up, -gameObject.transform.up);
        isGrounded = Physics.SphereCast (ray, 0.13f, 0.08f);
        //着地判定の範囲をシーンに示す
        Debug.DrawRay (gameObject.transform.position+0.2f*gameObject.transform.up, -0.22f*gameObject.transform.up);

        if (isGrounded) {
            if (h != 0 || v != 0) {
                moveDirection = speed * new Vector3 (h, 0, v);
                moveDirection = transform.TransformDirection (moveDirection);
                rb.velocity = moveDirection;
            }
            if (Input.GetButtonDown ("Jump")) {
                rb.velocity = new Vector3 (rb.velocity.x, 5, rb.velocity.z);
            }
        }

    }

}

移動方法その6

移動方法その5にマウス操作を追加します。
Locomotion6.csというC#スクリプトを作成し、操作したいキャラクターにアタッチします。
十字キーで前後左右移動
マウス操作で回転と視点移動

Locomotion6.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Locomotion6 : MonoBehaviour {

    public float speed = 3f;
    public float jumpSpeed = 3f;
    public float rotateSpeed = 1.5f;
    public float camRotSpeed = 3.5f;

    private float lookUpAngle;
    private Rigidbody rb;
    private float h, v;
    private float mX, mY;
    private Vector3 moveDirection = Vector3.zero;
    private bool isGrounded = false;
    private Ray ray;

    void Start() {
        rb = GetComponent<Rigidbody>();
        rb.constraints = RigidbodyConstraints.FreezeRotation;
    }

    void Update() {

        h = Input.GetAxis ("Horizontal");
        v = Input.GetAxis ("Vertical");
        mX = Input.GetAxis ("Mouse X");
        mY = Input.GetAxis ("Mouse Y");

        //カメラのみ上下に回転させる,180-140=60より上下60度まで見ることができる
        lookUpAngle = Camera.main.transform.eulerAngles.x - 180 + camRotSpeed * mY;
        if (Mathf.Abs (lookUpAngle) > 140)
            Camera.main.transform.Rotate (new Vector3 (camRotSpeed * mY, 0, 0));

        //足元から下へ向けて球状のRayを発射し,着地判定をする
        //rayで中心と方向を指定,SphereCastで球の半径と,球を飛ばす距離を指定
        ray = new Ray(gameObject.transform.position+0.18f*gameObject.transform.up, -gameObject.transform.up);
        isGrounded = Physics.SphereCast (ray, 0.13f, 0.08f);
        //着地判定の範囲をシーンに示す
        Debug.DrawRay (gameObject.transform.position+0.2f*gameObject.transform.up, -0.22f*gameObject.transform.up);

        if (isGrounded) {
            gameObject.transform.Rotate (new Vector3 (0, rotateSpeed * mX, 0));
            if (h != 0 || v != 0) {
                moveDirection = speed * new Vector3 (h, 0, v);
                moveDirection = transform.TransformDirection (moveDirection);
                rb.velocity = moveDirection;
            }
            if (Input.GetButtonDown ("Jump")) {
                rb.velocity = new Vector3 (rb.velocity.x, 5, rb.velocity.z);
            }
        }

    }

}
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away