Unityをスクリプトで動かしたい!

Unityでオブジェクトを操作する方法を紹介してます!

unity エレベーターの実装(動画あり)

今回紹介するのは、エレベーター(だんだんと上昇させる処理)です。

プレイヤーに与える動きを作ってみました。

~
public class Elevator : MonoBehaviour
{
    //処理を与えたいオブジェクトのタグ名
    string CachedTag;
    //エレベーターの速度
    [SerializeField]
    float Speed;

    // Start is called before the first frame update
    void Start()
    {
        //タグ名を"Player"に設定
        CachedTag = "Player";
    }
    //エレベーターの処理
    void ElevatorMove(GameObject _obj)
    {
        //上昇させたいオブジェクトのY軸の値を加算する
        _obj.transform.position += new Vector3(0, Speed*Time.deltaTime, 0);
    }
    private void OnTriggerStay(Collider col)
    {
        //当たったオブジェクトのタグがPlayerなら
        if(col.gameObject.CompareTag(CachedTag))
        {
            //エレベーターの移動処理を行う
            ElevatorMove(col.gameObject);
        }
    }
}
~

f:id:SugieSan:20210221142039g:plain

実装の手順

エレベーター
新しくエレベーターオブジェクト(今回は円柱)を作成。

エレベーターオブジェクトに

をアタッチ

プレイヤー
移動処理があるplayerを作成
今回はこの記事のおまけの移動処理を行っています。
unitystudy.hatenadiary.com

  • rigidbody(Use Gravity をoff)
  • capsule collider(is Triggerをoff)


f:id:SugieSan:20210221142015p:plain
画像のTagをPlayerに設定

エレベーターの紹介は以上になります。

Unityジャンプの実装(動画あり)

今回はジャンプの実装を紹介します。

~
public class Jump : MonoBehaviour
{
    [SerializeField]
    bool JumpFlag;          //ジャンプ中にたてる
    [SerializeField]
    float Gravity;          // 重力
    [SerializeField]
    float JumpPow;          // ジャンプ力
    float StartTime;        //ジャンプし始めの時間を入れる

    // Start is called before the first frame update
    void Start()
    {
        JumpFlag = false;
    }

    // Update is called once per frame
    void Update()
    {
        if(!JumpFlag)
        {
            if(Input.GetKey(KeyCode.Space))
            {
                JumpFlag = true;
                StartTime = Time.time;  //ゲーム開始からの時間を入れる
            }
        }
        else
        {
            PlayerGravity(Gravity); // 重力
            PlayerJump(JumpPow);    // ジャンプ
            PlayerLand();           // 着地処理
        }
    }
    //重力移動
    void PlayerGravity(float _Gravity)
    {
        //落下量=滞空時間×加速度(-重力)
        //重力の力を時間が経つにつれて強くする
        var YAxis = (Time.time-StartTime) * (-1 * _Gravity * Time.deltaTime);
        //重力の移動
        transform.position += new Vector3(0, YAxis, 0);
    }
    //ジャンプ
    void PlayerJump(float _JumpPower)
    {
        var YAxis = _JumpPower * Time.deltaTime;
        //重力を考えないで上に行く処理のみ
        transform.position += new Vector3(0, YAxis, 0);
    }
    //着地の判定
    void PlayerLand()
    {
        //今回は高さが0以下になった場合
        if(transform.position.y<=0)
        {
            JumpFlag = false;
        }
    }
}
~

f:id:SugieSan:20210220181203g:plain

ジャンプをさせたいオブジェクトにアタッチをして

  • Gravity(重力の大きさ)
  • JumpPow(ジャンプ力)

の数値を入れれば動きます。

着地はY軸(高さ)が0以下になったらという条件にしてますが、コライダーやスクリプトで当たり判定をすると段差でのジャンプも可能です。

Unityカメラから目標が離れたら追従する処理の紹介(動画あり)

今回はタイトル通りカメラの追従処理を紹介していきたいと思います。

カメラをプレイヤーの子オブジェクトにすれば割と簡単に追従をしてくれますが、少し面白いカメラワークができると思いますので是非ご覧ください。

この処理の良いところは、プレイヤーの移動速度とカメラの移動速度をそれぞれ分けることができます。

~
public class CameraMove : MonoBehaviour
{
    [SerializeField]
    GameObject TargetObj;   // カメラの中心(目標)
    [SerializeField]
    float KeepDis;          // 目標から保つ距離
    [SerializeField]
    float CameraSpeed;      // カメラの速度
    [SerializeField]
    Vector2 CameraVec;      // カメラのxz位置
    [SerializeField]
    Vector2 TargetVec;      // 目標のxz位置
    [SerializeField]
    float DefaultHeight = 0;
    [SerializeField]
    bool NearFlag;          // 保つ距離よりも近い場合
    [SerializeField]
    bool FarFlag;           // 保つ距離よりも遠い場合


    void Start()
    {
        DefaultHeight = transform.position.y;
        // 目標を中心に見る
        transform.LookAt(TargetObj.transform.position);
        // カメラxz座標
        CameraVec = new Vector2(this.transform.position.x, this.transform.position.z);
        // 目標のxz座標
        TargetVec = new Vector2(TargetObj.transform.position.x, TargetObj.transform.position.z);
        // 目標から保つ距離を目標からカメラの距離の初期値を格納する
        KeepDis = Vector2.Distance(CameraVec, TargetVec);

        NearFlag = false;
        FarFlag = false;
    }
    void Update()
    {
        // 目標を中心に見る
        transform.LookAt(TargetObj.transform.position);


        // フラグが立っていないで、目標との距離が離れた場合
        if(!FarFlag&&Vector3.Distance(TargetObj.transform.position, this.transform.position)>KeepDis)
        {
            FarFlag = true;
        }
        // フラグが立っていないで、目標との距離が近い場合
        else if(!NearFlag&&Vector3.Distance(TargetObj.transform.position, this.transform.position)< KeepDis)
        {
            NearFlag = true;
        }


        // 遠い場合
        if(FarFlag)
        {
            // カメラxz座標
            CameraVec = new Vector2(this.transform.position.x, this.transform.position.z);
            // 目標のxz座標
            TargetVec = new Vector2(TargetObj.transform.position.x, TargetObj.transform.position.z);
            // カメラから目標のベクトル(x,z)
            Vector2 C_TVec = TargetVec - CameraVec;

            // カメラと目標の距離が1フレームの移動量よりも近くなった場合
            if (Vector2.Distance(TargetVec, CameraVec) - KeepDis<CameraSpeed)
            {
                // 保つ距離に移動
                this.transform.position = new Vector3(C_TVec.normalized.x * -1 * KeepDis, DefaultHeight, C_TVec.normalized.y* -1 * KeepDis)+TargetObj.transform.position;
                FarFlag = false;
            }
            else
            {
                // 目標に向かって進行
                this.transform.position += new Vector3(C_TVec.normalized.x * CameraSpeed,0, C_TVec.normalized.y * CameraSpeed);
            }
        }
        // 近い場合
        else if(NearFlag)
        {
            // カメラxz座標
            CameraVec = new Vector2(this.transform.position.x, this.transform.position.z);
            // 目標のxz座標
            TargetVec = new Vector2(TargetObj.transform.position.x, TargetObj.transform.position.z);
            // カメラから目標のベクトル(x,z)
            Vector2 C_TVec = TargetVec - CameraVec;

            // カメラと目標の距離が1フレームの移動量よりも遠くなった場合
            if (Vector2.Distance(TargetVec, CameraVec) - KeepDis < CameraSpeed)
            {
                // 保つ距離に移動
                this.transform.position = new Vector3(C_TVec.normalized.x * -1 * KeepDis, DefaultHeight, C_TVec.normalized.y * -1 * KeepDis) + TargetObj.transform.position;
                NearFlag = false;
            }
            else
            {
                //目標に向かって進行
                this.transform.position -= new Vector3(C_TVec.normalized.x * CameraSpeed, 0, C_TVec.normalized.y * CameraSpeed);
            }
        }
    }
}
~

f:id:SugieSan:20210220002126g:plain
目標との距離を常に計算して

  • 遠い場合は近付く
  • 近い場合は離れる

といった処理を書いています。

Y軸の位置を計算に入れてしまうと保つべき距離の戻し方が難しかったので基本的にXZ軸の位置を計算で使用しました。(一度Y軸も計算しながら書いてみましたが直せそうもないので諦めました。)

おまけ

プレイヤーのカメラの方向を見て移動するスクリプト

~
public class DireMove : MonoBehaviour
{
    [SerializeField]
    float Speed;            // 速度
    [SerializeField]
    GameObject CameraObj;   // カメラのオブジェクト

    float Horizontal;       // 横の入力用
    float Vertical;         // 縦(前後)の入力用
    // Update is called once per frame
    void Update()
    {
        //横移動キーが押されている場合右なら1が左なら-1が加算されり
        Horizontal = Input.GetAxisRaw("Horizontal");
        //上の前後版
        Vertical = Input.GetAxisRaw("Vertical");

        // カメラの前方方向(xz軸)ベクトルを取得
        Vector3 cameraForward = Vector3.Scale(CameraObj.transform.forward, new Vector3(1, 0, 1)).normalized;

        // 方向キーの値とカメラの向きから、移動方向を決定
        Vector3 moveForward = cameraForward * Vertical + CameraObj.transform.right * Horizontal;

        //移動
        transform.position+= moveForward * Speed;
    }
}
~

カメラの方向と入力の値で移動しています。

今回は以上です。



オブジェクトを加速移動させる(動画あり)

今回はオブジェクトを加速移動する方法を紹介します。

~
public class AcceleMove : MonoBehaviour
{
    [SerializeField]
    float XSpeed;    // 現在のX軸のスピード
    [SerializeField]
    float YSpeed;    // 現在のY軸のスピード
    [SerializeField]
    float addSpeed; // 1フレーム毎にスピードに加算する量
    [SerializeField]
    float subSpeed; // 1フレーム毎にスピードに減速する量
    [SerializeField]
    float SpeedMax; // 最大速度

    void Update()
    {
        //右の矢印キーが押された場合
        if (Input.GetKey(KeyCode.RightArrow))
        {
            //プラスX軸の速さが最大ではない場合
            if (XSpeed < SpeedMax)
            {
                //X軸のプラス(右)方向に加算
                XSpeed += addSpeed;
            }
        }

        //左の矢印キーが押された場合
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            //マイナスX軸の速さが最大ではない場合
            if (XSpeed > -SpeedMax)
            {
                //X軸のプラス(左)方向に加算
                XSpeed += addSpeed * -1;
            }
        }

        //上の矢印キーが押された場合
        if (Input.GetKey(KeyCode.UpArrow))
        {
            //プラスY軸の速さが最大ではない場合
            if (YSpeed < SpeedMax)
            {
                //Y軸のプラス(上)方向に加算
                YSpeed += addSpeed;
            }
        }

        //下の矢印キーが押された場合
        if (Input.GetKey(KeyCode.DownArrow))
        {
            //マイナスY軸の速さが最大ではない場合
            if (YSpeed > -SpeedMax)
            {
                //Y軸のマイナス(下)方向に加算
                YSpeed += addSpeed * -1;
            }
        }

        //左右の矢印キーが押されていない場合
        if (!Input.GetKey(KeyCode.RightArrow) && !Input.GetKey(KeyCode.LeftArrow))
        {
            //右側に加速している場合
            if(XSpeed>0)
            {
                //減速させる //Mathf.Maxは二つの引数のうち大きい値が取得される
                XSpeed = Mathf.Max(0, XSpeed - subSpeed);
            }
            //左側に加速している場合
            else if(XSpeed<0)
            {
                //減速させる //Mathf.Minは二つの引数のうち小さい値が取得される
                XSpeed = Mathf.Min(0, XSpeed + subSpeed);
            }
        }

        //上の上下版
        if (!Input.GetKey(KeyCode.UpArrow) && !Input.GetKey(KeyCode.DownArrow))
        {
            if (YSpeed > 0)
            {
                YSpeed = Mathf.Max(0, YSpeed - subSpeed);
            }
            else if (YSpeed < 0)
            {
                YSpeed = Mathf.Min(0, YSpeed + subSpeed);
            }
        }

        //X,Y軸ともにその速度分加算される
        this.transform.position += new Vector3(XSpeed, YSpeed, 0);
    }
}
~

f:id:SugieSan:20210219001816g:plain
addSpeedに加速値
subSpeedに減速値
SpeedMaxに最大速度
を記入すると動きます。

Mathf.Max(num1,num2)は二つのうちの大きい値が取得できます。
Mathf.Min(num1,num2)は二つのうちの小さい値が取得できます。
今回は減速の計算で、速度を0に近づけるために使用しました。
詳しくはリファレンスを参照してください。

Mathf.MaxリファレンスMathf-Max - Unity スクリプトリファレンス

Mathf.MinリファレンスMathf-Min - Unity スクリプトリファレンス





Unityスクリプトでオブジェクトを移動させる(動画あり)

Unityでのオブジェクトの移動方法を紹介します。

~
public class Move : MonoBehaviour
{
    [SerializeField]
    float Speed;    // 進むスピード
    void Update()
    {
        //右の矢印キーが押された場合
        if(Input.GetKey(KeyCode.RightArrow))
        {
            //x軸のプラス方向にSpeedの値を加算
            this.transform.position += new Vector3(Speed,0,0);
        }
        //左の矢印キーが押された場合
        if(Input.GetKey(KeyCode.LeftArrow))
        {
            //x軸のマイナス方向にSpeedの値を加算
            this.transform.position += new Vector3(-Speed,0,0);
        }
        //y軸のプラス方向にSpeedの値を加算
        if (Input.GetKey(KeyCode.UpArrow))
        {
            this.transform.position += new Vector3(0, Speed, 0);
        }
        //y軸のマイナス方向にSpeedの値を加算
        if (Input.GetKey(KeyCode.DownArrow))
        {
            this.transform.position += new Vector3(0, -Speed, 0);
        }
    }
}
~

f:id:SugieSan:20210218222308g:plain
キーボードのアローキーが押された場合その方向に移動するようにしました。
押されたキーが分かりやすい様に赤く表示されるようにしました。