Home –  Archive
Monthly Archives: 3月 2016

キャラクタ追従するカメラの話

Unity難しいですよねぇ。。。
キャラクタを出して、コントロールパッドで前後左右に動かすだけでも四苦八苦です。

とりあえず、なんとなくキャラクタが移動したものの視点が追従しないのです(;・∀・)
そりゃそうですよねということで、カメラをなんとか追従して動かしたく・・・。

勉強に使った「Unity5 3D/2Dゲーム開発 実践入門 -作りながら覚えるスマートフォンゲーム制作-」にキャラクタに
追従するカメラについての記載があったぞ・・・!
と思ったものの、カメラの方向は固定だった(;・∀・)

残念ながらこれだと、カメラの向きが固定だった。そうじゃないんだと試行錯誤したのです。

特に困ったのは
* カメラはキャラクタより高い位置にある
* キャラがバックした場合、カメラが下る事
* 常にキャラ方向(ただし、ちょっとキャラより遠くを見てる感じ)にする

カメラはキャラクタより高い位置にある

なんかよくわかってないけど、カメラをキャラクタより高い位置においたら、
キャラクタを追従して動かすときになんとなく変な挙動になった気がします。
(よーわかってないんですが(;・∀・))

色々考えたら、位置自体は上から見た平面で考えればいいので、yの値を追従するオブジェクトと
合わせて計算しました。

var current = new Vector3 (
    transform.position.x,
    target.transform.position.y,
    transform.position.z
);

キャラがバックした場合、カメラが下る事

カメラの到達位置をVector3.MoveTowards関数で位置計算してたんですが、
カメラのポジションをそのまま使うとカメラ位置から後ろに行かず・・・

ということで、チェック用に後ろに位置をずらした値を加える感じにしました。

current + Vector3.Normalize(current - target.transform.position) * distance

常にキャラ方向(ただし、ちょっとキャラより遠くを見てる感じ)にする

これが一番悩みの種でした。
単純に「transform.LookAt」だとターゲット方面にしか向かず、ちょっと遠くに向かせることが出来ません。
また、LookAtした後に、

transform.rotation = transform.rotation * Quaternion.Euler(new Vector3(-15, 0, 0));

したものの、ガクガクと画面が視点が上下に何故か揺れて・・・。
まあ、カメラの角度を固定する必要があるということで。

どこで見たのか覚えてないのですが下記のようにすることで解決しました。

var newRotation = Quaternion.LookRotation(target.transform.position - transform.position).eulerAngles;
newRotation.x = cameraAngle;
newRotation.z = 0;
transform.rotation = Quaternion.Euler(newRotation);

そんなわけで最終的には

こんな感じにつくりました。
ド素人なのでこれでいいのかなぁ。悩みはつきません。誰か助けて!っていう気持ちです。。。

using UnityEngine;
using System.Collections;

public class SimpleFollow : MonoBehaviour {

    private float distance;
    private float cameraHeight;
    private float yRotate;

    public GameObject target;
    public float followSpeed = 5;
    public int cameraAngle = 20;


    // Use this for initialization
    void Start () {
        //平面(X,Z)での距離を取得
        distance = Vector3.Distance(
            new Vector3(target.transform.position.x, 0, target.transform.position.z),
            new Vector3(transform.position.x, 0, transform.position.z));

        //カメラの高さの差分を取得
        cameraHeight = transform.position.y - target.transform.position.y;
    }

    void LateUpdate () {
        //カメラの位置を高さだけ、ターゲットに合わせて作成
        var current = new Vector3 (
            transform.position.x,
            target.transform.position.y,
            transform.position.z
        );

        //チェック用の位置情報を作成(バックした時にカメラが引けるようにdistance分位置を後ろにずらす)
        var checkCurrent = current + Vector3.Normalize(current - target.transform.position) * distance;

        //カメラが到達すべきポイントを計算(もともとのターゲットとの差分から計算します)
        var v = Vector3.MoveTowards (
            target.transform.position,
            checkCurrent,
            distance);

        //カメラ位置移動(位置計算後にカメラの高さを修正)
        transform.position = Vector3.Lerp(
            current,
            v,
            Time.deltaTime * followSpeed
        ) + new Vector3(0, cameraHeight, 0);

        //カメラの角度を調整
        var newRotation = Quaternion.LookRotation(target.transform.position - transform.position).eulerAngles;
        newRotation.x = cameraAngle;
        newRotation.z = 0;
        transform.rotation = Quaternion.Euler(newRotation);
    }

}