作成中のゲーム「ぴぺっと」では
ジャンプするときの軌道が大事になります。
これを直観のみで行うと、
何度もミスして嫌気がさします(体験談)
ジャンプの弾道を予測軌道を表示したかった!
もう最初から軌跡を表示しよう!
なので、
- 軌跡を先に表示し、
- タイミングを見計らって、
- ジャンプ!
という仕様にしました。
※ 目標画像
次の土管に狙いを定めとジャンプします。
※ 実際の画像
かなりいい感じにできましたー(/・ω・)/
// 疑似コード
「鉛直投げ上げの公式」を使えばOK!
これです↓
y=v0t−12gt2
…いえ、ぶっちゃけよくわからなかったので、
サイト巡りをしたら見つけました。
→
【Unity勇者の奮闘記】Unityで物理の勉強3(弾道予測線を作成する)
まさにこれでOKでした。
こういうプログラムを思いつかないのが、
初心者にはつらい( ;∀;)
// 実際のプログラム
私の場合は2Dにしたかったので、
Rigidbody2Dに変更しました。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DrawLine : MonoBehaviour {
// 弾道を表示するための点のプレハブ
[SerializeField] private GameObject dummyObjPref = default;
// 弾道を表示する点の親オブジェクト
[SerializeField] private Transform dummyObjParent = default;
// 初速のベクトル
[SerializeField] private Vector3 v0 = default;
// 弾道予測の点の数
[SerializeField] private int dummyCount = 10;
// 弾道を表示する間隔の秒数
[SerializeField] private float secInterval = 0.2f;
private List<GameObject> dummySphereList = new List<GameObject>();
private Rigidbody2D rigid = default;
private bool drow = true;
void Start()
{
rigid = GetComponent<Rigidbody2D>();
if (!rigid) rigid = gameObject.AddComponent<Rigidbody2D>();
rigid.isKinematic = true;
dummyObjParent.transform.position = transform.position;
// 弾道予測を表示するための点を生成
for (int i = 0; i < dummyCount; i++)
{
var obj = (GameObject)Instantiate(dummyObjPref, dummyObjParent);
dummySphereList.Add(obj);
}
}
void Update()
{
if (!drow) return;
// 弾道予測の位置に点を移動
for (int i = 0; i < dummyCount; i++)
{
var t = i * secInterval;
var x = t * v0.x;
var z = t * v0.z;
var y = (v0.y * t) - 0.5f * (-Physics.gravity.y) * Mathf.Pow(t, 2.0f);
dummySphereList[i].transform.localPosition = new Vector3(x, y, z);
}
// マウスクリックで球の弾道を確認
if (Input.GetMouseButtonDown(0))
{
drow = false;
rigid.isKinematic = false;
}
}
/// <summary>
/// プレイヤーから送られてくる
/// 移動方向と、パワーをかけたもの
/// rigidbody2d.AddForce() と同じ
/// </summary>
public void Set(Vector3 v3)
{
v0 = v3;
}
}
■ プレイヤーのプログラムも改良
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
[SerializeField] private DrawLine dLine = default; // 予測軌道を表示
private UI ui = default;
private Rigidbody2D rigidbody2d = default; // これがないと
private float jumpPower = 1; // ジャンプのパワー
private float power = 10; // 全体のパワー
private float upDownSpeed = 0.5f; // ジャンプ力の上げ下げ
// Start is called before the first frame update
void Start()
{
ui = GameObject.Find("GM").GetComponent<UI>();
rigidbody2d = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
// UI
ui.PowerGage(jumpPower);
ui.GagePosition(this.transform);
// 予測軌道
dLine.Set(new Vector3(0.25f, jumpPower) * power);
// ジャンプ力を上げ下げ
jumpPower = Mathf.PingPong(upDownSpeed * Time.time, 1);
// マウスクリック
if (Input.GetMouseButtonDown(0))
{
// 重力を戻す
rigidbody2d.gravityScale = 1;
// パワーに応じてジャンプ
rigidbody2d.AddForce(new Vector3(0.25f, jumpPower) * power, ForceMode2D.Impulse);
}
}
}
前回のプログラムに
dLine.Set(new Vector3(0.25f, jumpPower) * power);
の項目を追加。
ジャンプするときのAddForceの部分、
rigidbody2d.AddForce(new Vector3(0.25f, jumpPower) * power, ForceMode2D.Impulse);
と、全く同じですね。
LineBallは、当たり判定なしのスプライトのプレハブです。
軌道を示す黒い点です。これは任意でOKです。
■ まとめ
先人の知恵、様様でした!
ここから学んで自分の成長につなげたい。
■ 参考にしたHP