Last Updated 2024.03.24
エルツヴァーユ的な画面端のシステムを作ってみます。
はじめに
「エルツ式の画面端」が普通のと「どう違うの?」
という、根っこの部分から触れてみます。
普通の3D格闘ゲームだと、大体は障害物か見えない壁で仕切られています。
バーチャや闘神伝など、問答無用でリングアウトみたいな作品もあれば、近年だと壁に張り付いて壁コンボが狙えたり──というのが自分のイメージです。
じゃあ、エルツはどうなっているかというと……
ステージ端自体は勿論あるのですが、それとは別に、後退を続けると見えない壁にあたって(7~8ステくらい)それ以上後退できなくなる制限みたいなものがあるのです。
要するに、ガン逃げ防止用の移動制限ですね。
今回はこのシステムを再現してみたいと思います。
仕組みを考える
1Pと2Pキャラクター間の距離が一定以上開いたら、「キャラクターの後ろに見えない壁を出現させる」というのが今回のやりたいことになります。
仕組み自体は単純に思えるんですが、作ってる最中に、壁のインスタンス化とか、突入角度によるズレを考慮すると、途端に難易度が上がってしまってると感じました。
具体的には、ただインスタンス化するだけだと、連続後退した時に段々軸ズレが生じるので(おそらく物理的な接触挙動やアニメーションの移動値を有効化してるせい)、壁は常にキャラに対して直角でないといけないっぽいんですよね。なので、見えない壁を逐一角度制御する部分がネックになってきます。あと不要になった際の消去方法も作らないといけません。
なので、初心者なりに、もっとシンプルな方法で解決しようと思います。
実際のアプローチ
以前、カメラ制御のために『キャラクター同士の中間点を彷徨う空のゲームオブジェクト』を作ったことがあって、それを再利用したら思い通りの挙動になってくれました。
具体的には、中間点を彷徨う空のオブジェクトの「子要素」に壁を設定し、制限距離を超えたら有効化する。というものです。
実際のスクリプト
▼中間点オブジェに設定するスクリプト
using UnityEngine;
public class HalfPoint : MonoBehaviour
{
public GameObject Player1;
public GameObject Player2;
void Update()
{
transform.position = (Player1.transform.position + Player2.transform.position) / 2;
//中間点の向きを固定
transform.LookAt(Vector3.forward);
}
}
▼後退制限の壁を出現させるスクリプト
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Corner : MonoBehaviour
{
private GameManager gameManager;
[SerializeField]
private GameObject _1PCorner;//手動で設定
[SerializeField]
private float moveRestrictions = 8;//後退制限距離
void Start()
{
gameManager = GetComponent<GameManager>();
}
void Update()
{
float playerDistance = Vector3.Distance(gameManager.SidePlayer1.transform.position, gameManager.SidePlayer2.transform.position);
if (playerDistance > moveRestrictions)//プレイヤー間の距離が制限範囲を超えたら
{
_1PCorner.gameObject.SetActive(true);
}
else
{
_1PCorner.gameObject.SetActive(false);
}
}
}
※12月31日追記
実はテストプレイ中に、なんらかの条件で「ズレ」が発生するケースが確認できたのですが、どうしたらそうなるのかが解らず修正案件入りです。中間点オブジェクトの、向きの固定方法を変更すればいけそうな気はするのですが……公開した手前、申し訳ありません。
動作確認
コライダーがちゃんと出たり消えたりしてるのを確認できます。
これで制限距離を超えた後退はできなくなりました。
この方法だと壁は常時有効化してても問題なかったのですが、コライダー2枚を常時有効化していると、心なしか挙動が重い感じがしたので、接近戦時には消えてもらっていた方が負荷的には優しそうです。