ぐーるらいふ

底辺。

【Unity】アクションゲームの「動く床」を実現するには【Tips】

最近ゲームを作ってまして、そこから何かネタが無いかなーと思うのですが、
これと言って目新しいものが無く…。
その開発過程でちょっとだけ気になった個所をメモ代わりに残しておこう。

動く床

アクションゲームにはよくあるギミックとして、

動く床

というものがある。
地面が動き、タイミングを合わせてジャンプしないと先に進めないというよくあるやつだ。

f:id:ghoul_life:20171008233955g:plain

これをunityで作ってみよう。

床を作る

cubeを作成してスケールを10,1,10。これを動く床とします。

f:id:ghoul_life:20171008234236p:plain

アニメーションを床に付与する

animation > createして適当にtransform.positonのxを動かすようなものを作成

f:id:ghoul_life:20171008234404p:plain

プレイヤーを作る

その上に乗っかるプレイヤーを適当に用意する。
今回はQueryChanを使いました。

f:id:ghoul_life:20171008234655p:plain

Control.cs
(仮実装なんでとりあえずやっつけ…。)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Control : MonoBehaviour {

    private const float SPEED = 5.0f;
    public Animator anim;
    private float jumpTime = 0;
    private bool isJump = false;
	
	// Update is called once per frame
	void Update () {

        var hz = Input.GetAxis("Horizontal");
        var vt = Input.GetAxis("Vertical");

        if(Mathf.Abs(hz + vt) > 0)
        {
            anim.SetBool("Walk", true);
        }
        else
        {
            anim.SetBool("Walk", false);
        }




        if (Input.GetButtonDown("Jump"))
        {
            if (!isJump)
            {
                anim.SetTrigger("Jump");
                isJump = true;
                jumpTime = 0;
            }
        }

        float jumpVal = 0;

        if (isJump)
        {
            if (jumpTime < 1.0f)
            {
                jumpVal += 2 * SPEED * Time.deltaTime;
            }
            else if (jumpTime < 2.0f)
            {
                //pos.y -= Time.deltaTime;
            }
            else
            {
                isJump = false;
            }
            jumpTime += Time.deltaTime;
        }

        var pos = this.transform.position;
        pos.x += hz * SPEED * Time.deltaTime;
        pos.y += jumpVal;
        pos.z += vt * SPEED * Time.deltaTime;
        
        this.transform.position = pos;

        if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            transform.eulerAngles = new Vector3(0,0,0);
        }
        if (Input.GetKeyDown(KeyCode.DownArrow))
        {
            transform.eulerAngles = new Vector3(0, 180, 0);
        }
        if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            transform.eulerAngles = new Vector3(0, 270, 0);
        }
        if (Input.GetKeyDown(KeyCode.RightArrow))
        {
            transform.eulerAngles = new Vector3(0, 90, 0);
        }

    }
}
とりあえず実行してみる

早速実行してみるとこうなる。

f:id:ghoul_life:20171008235015g:plain

おかしい。おかしいぞ。
上に乗っかった時は動く床の影響を受けて欲しい。

解決策

では、どうするか?こうすればOKだ。

子要素にする

コードにするとこんな感じ

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveFloor : MonoBehaviour {
    private void OnCollisionEnter(Collision collision)
    {
        collision.gameObject.transform.SetParent(this.transform);
    }

    private void OnCollisionExit(Collision collision)
    {
        collision.gameObject.transform.SetParent(null);
    }
}

これを床に付与して実行してみよう

f:id:ghoul_life:20171008235406g:plain

これでよくある動く床を実装出来た。

別の手段

別の手段としては床をRigidbodyにして、AddForceで動かす
(PhysicsMaterialで滑りを低く)
という手もあるらしいけど、ちょっと試していない。

凄い久しぶりにunityの事書けた…。最近更新も滞ってたし。
もっとメモ代わりにどんどん書きたい。