poi’s tech blog

3D多人数同時接続型球体アクション成人向けゲーム開発のためのアイデア、ナレッジ

Unity3DでH◯L研ジャンプが作りたかったお話

Unity 2020.2.7

参考

qiita.com

www.hallab.co.jp

モチベーション

一言でジャンプといっても色んな手法がある。

思いつくもので3通り

  1. 重力が働く環境下でジャンプボタン押下時にy軸に初速を与える方法
  2. 放物運動の公式を使う方法
  3. 物理挙動を無視した方法

この3通りのジャンプにおいて、ロジックはこのように分けられると思う

番号 ロジック
1と2 常に同じ計算処理が走っていて、ボタンを押したときに初期値が与えられる
3 地面にいる時とジャンプ中で移動ロジックが切り替わる

それぞれメリットデメリットがあると思うが、個人的に単純に放物線を描くジャンプはつまらないので3の物理挙動を無視したジャンプを作りたかった。

その中でも参考記事のH◯L研ジャンプが「高さ」「持続時間」「sin波の軌道のゆがみ」の調整が柔軟にでき、理想のジャンプが作りやすそうだったためUnity3Dで動くものを作った。

前提

  • キーボードのXキーを押してジャンプする
  • 接地中かどうかの判定方法がある(CharacterControllerのisGroundedでもいいはず)
  • 重力加速度はOFF

とりあえず動くコード

適当に3Dモデルのゲームオブジェクトにアタッチすれば動くはず。

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

public class MyJumpController : MonoBehaviour
{
    bool isJumping = false;
    float t = 0f; //経過時間 ( 0.0 -> 1.0 )
    Vector3 nextPos; //次に設定される座標
    Vector3 firstPos; //動作開始した座標
    Vector3 targetPos; //目標位置
    float height = 1f; // ジャンプの高さ
    float distortion = 1f; // 曲線のゆがみ

    private void Start()
    {
        gr = GetComponent<MyGroundCheck>();  // CharacterControllerのisGroundedでもいい
    }

    void Update()
    {
        if(isJumping)
        {
            Jump();
            return;
        }
        
        if (Input.GetKeyDown(KeyCode.X))
        {
            isJumping = true;
            firstPos = transform.position;
        }
    }

    void Jump()
    {
        nextPos = transform.position;
        t += Time.deltaTime;

        float pow = (float)Math.Pow(1.0 - Math.Sin(Math.PI * t), distortion);
        nextPos.y = firstPos.y + (1.0f - pow) * height;
        transform.position = nextPos;

        if (gr.isGrounded)
        {
            t = 0f;
            isJumping = false;
        }
    }
}

結果

f:id:poipoipoip:20210326002808g:plain

着地をさせたかったのでジャンプの終了判定をt>1.0からisGroundedに無理やり変えた。

そのため同じ高さ~高いところへの着地はこれでいいが、崖からジャンプした時などはsin波を描いてしまう。

ユーザーからの操作の介入がない、敵キャラクターなどの動きではこのようなカーブの計算式で十分だったりします。

とのことなのでユースケースに合わせたジャンプ手法を採用しよう。