Unity 2Dアクションの作り方【ステージ管理】【元の位置に戻る処理】

make 2d action thumbnail

今まで様々なものを制作してきました。今回はステージを管理するためのスクリプトを書いていこうと思います。最後までついて来て頂ければ↑のようなゲームを作る事ができます。

この記事は本のように順を追って解説しています。この記事は途中のページになります。
この記事を見ていて、現在の状況がわからない場合や忘れてしまった事などが出てきたら↓のリンクから目次ページへ飛べますので立ち戻って見てください。

<ステージを管理するスクリプトを作ろう>

スタート地点を決めよう

さて、ゲームをスタートするに当たって、スタートする地点を決めたいと思います。

最初からプレイヤーをスタート地点に置けばいいのでは?と思うかもしれませんが、プレイヤーがやられてしまった時にスタート地点に戻ってこないといけないのでスタート地点を決めます。

まずはカラのゲームオブジェクトを作成してください。適当にスタート地点とわかる名前に変えるといいと思います。

create empty

自分はStartPosという名前にしました。

そして、ゲームオブジェクトの左上の灰色の箱みたいな奴をクリックしてください。

↓のようなメニューが出てきたと思います。

game object color icon

適当に好きな色の奴を選んでください。できたら上2段の横長の物がいいと思います。

game object scene view

そうすると、カラだったゲームオブジェクトがシーンビュー上で映るようになります。

これは何かというとただの目印で、ゲームとは何の関係もありません。

ゲームとは関係ないただの目印であるという点が重要で、要は編集する上で「場所」を示すのに便利です。

これをスタート地点にしたいところに置きましょう。

start position select

ポイントとしては、キャラクターの中心座標分高い位置に置くことです。

このポジションを取得してキャラクターを配置します。

ステージコントローラーを作成しよう

それではステージをコントロールするスクリプトを書きましょう。

クリックすると展開します
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class StageCtrl : MonoBehaviour
 {
 
     [Header("プレイヤーゲームオブジェクト")]public GameObject playerObj;
     [Header("コンティニュー位置")]public GameObject[] continuePoint;
 
     void Start()
     {
         if (playerObj != null && continuePoint != null && continuePoint.Length > 0)
         {
             playerObj.transform.position = continuePoint[0].transform.position;
         }
     }
 
     void Update()
     {
         
     }
 }

さて、このスクリプトでポイントとなっているのはpublicに配列を持ってきている点です。

[Header("コンティニュー位置")]public GameObject[] continuePoint;

コンティニュー位置としていますが、0番目がスタート地点になります。

if (playerObj != null && continuePoint != null && continuePoint.Length > 0)

これは、インスペクターで設定し忘れた時用の対策です。

配列.Lengthというのは配列の中身が何個用意されているのかを知る事ができます。要は中身が1個も無かったら処理は行わないという事です。

playerObj.transform.position = continuePoint[0].transform.position;

そして、Startでプレイヤーの位置をスタート地点と同じ位置にするようにします。

これをカラのゲームオブジェクトを作って貼り付けると↓のようになります。

stage control inspector

配列のところにSizeとなっていますね。ここに数字を入れると

inspector element

このように中身を入れる箱が出来上がります。Sizeというのは配列の大きさになります。publicにすることによってインスペクターで大きさを指定できるようになったわけです。

これでコンティニューの作り方もだいたいわかったと思いますが、コンティニューポイントを作成するにはサイズを2以上にして、コンティニューポイントを通過した時、プレイヤーが戻ってくる位置を0から1に変えてあげればOKになります。

もちろんSizeの数は自由にできるのでステージによってコンティニューポイントを増やすことも可能になります。

set player object start object

あとはインスペクターにプレイヤーとスタート地点のゲームオブジェクトをはめ込んであげればOKになります。

スポンサーリンク

<スタート地点に戻ってこよう>

アニメーション終了判定を得よう

さて、では敵にやられたらスタート地点に戻ってくる処理を作ろうと思います。

今までのプレイヤーのスクリプトは↓のようになっています。

クリックすると展開します
using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 public class Player : MonoBehaviour
 {
     #region//インスペクターで設定する
     [Header("移動速度")] public float speed;
     [Header("重力")] public float gravity;
     [Header("ジャンプ速度")] public float jumpSpeed;
     [Header("ジャンプする高さ")] public float jumpHeight;
     [Header("ジャンプする長さ")] public float jumpLimitTime;
     [Header("接地判定")] public GroundCheck ground;
     [Header("天井判定")] public GroundCheck head;
     [Header("ダッシュの速さ表現")] public AnimationCurve dashCurve;
     [Header("ジャンプの速さ表現")] public AnimationCurve jumpCurve;
     [Header("踏みつけ判定の高さの割合(%)")] public float stepOnRate;
     #endregion

     #region//プライベート変数
     private Animator anim = null;
     private Rigidbody2D rb = null;
     private CapsuleCollider2D capcol = null;
     private bool isGround = false;
     private bool isHead = false; 
     private bool isJump = false;
     private bool isRun = false;
     private bool isDown = false;
     private bool isOtherJump = false;
     private float jumpPos = 0.0f;
     private float otherJumpHeight = 0.0f;
     private float dashTime, jumpTime;
     private float beforeKey;
     private string enemyTag = "Enemy";
     #endregion

     void Start()
     {
          //コンポーネントのインスタンスを捕まえる
          anim = GetComponent<Animator>();
          rb = GetComponent<Rigidbody2D>();
          capcol = GetComponent<CapsuleCollider2D>();
     }

     void FixedUpdate()
     {
          if (!isDown)
          {
              //接地判定を得る
              isGround = ground.IsGround();
              isHead = head.IsGround(); 

              //各種座標軸の速度を求める
              float xSpeed = GetXSpeed();
              float ySpeed = GetYSpeed();

              //アニメーションを適用
              SetAnimation();

              //移動速度を設定
              rb.velocity = new Vector2(xSpeed, ySpeed);
          }
        else
          {
              rb.velocity = new Vector2(0, -gravity);
          }
     }

     /// <summary>
     /// Y成分で必要な計算をし、速度を返す。
     /// </summary>
     /// <returns>Y軸の速さ</returns>
     private float GetYSpeed()
     {
          float verticalKey = Input.GetAxis("Vertical");
          float ySpeed = -gravity;

          //何かを踏んだ際のジャンプ
          if (isOtherJump)
          {
            //現在の高さが飛べる高さより下か
            bool canHeight = jumpPos + otherJumpHeight > transform.position.y;
               //ジャンプ時間が長くなりすぎてないか
               bool canTime = jumpLimitTime > jumpTime;

               if (canHeight && canTime && !isHead)
               {
                    ySpeed = jumpSpeed;
                    jumpTime += Time.deltaTime;
               }
               else
               {
                    isOtherJump = false;
                    jumpTime = 0.0f;
               }
           }
          //地面にいるとき
          else if (isGround)
          {
              if (verticalKey > 0)
              {
                  ySpeed = jumpSpeed;
                  jumpPos = transform.position.y; //ジャンプした位置を記録する
                  isJump = true;
                  jumpTime = 0.0f;
              }
              else
              {
                  isJump = false;
              }
          }
          //ジャンプ中
          else if (isJump)
          {
              //上ボタンを押されている。かつ、現在の高さがジャンプした位置から自分の決めた位置より下ならジャンプを継続する
              if (verticalKey > 0 && jumpPos + jumpHeight > transform.position.y && jumpTime < jumpLimitTime && !isHead)
              {
                  ySpeed = jumpSpeed;
                  jumpTime += Time.deltaTime;
              }
              else
              {
                  isJump = false;
                  jumpTime = 0.0f;
              }
          }

          if (isJump || isOtherJump)
          {
              ySpeed *= jumpCurve.Evaluate(jumpTime);
          }
          return ySpeed;
     }

     /// <summary>
     /// X成分で必要な計算をし、速度を返す。
     /// </summary>
     /// <returns>X軸の速さ</returns>
     private float GetXSpeed()
     {
          float horizontalKey = Input.GetAxis("Horizontal");
          float xSpeed = 0.0f;
          if (horizontalKey > 0)
          {
              transform.localScale = new Vector3(1, 1, 1);
              isRun = true;
              dashTime += Time.deltaTime;
              xSpeed = speed;
          }
          else if (horizontalKey < 0)
          {
              transform.localScale = new Vector3(-1, 1, 1);
              isRun = true;
              dashTime += Time.deltaTime;
              xSpeed = -speed;
          }
          else
          {
              isRun = false;
              xSpeed = 0.0f;
              dashTime = 0.0f;
          }

          //前回の入力からダッシュの反転を判断して速度を変える
          if (horizontalKey > 0 && beforeKey < 0)
          {
              dashTime = 0.0f;
          }
          else if (horizontalKey < 0 && beforeKey > 0)
          {
              dashTime = 0.0f;
          }
          beforeKey = horizontalKey;

          xSpeed *= dashCurve.Evaluate(dashTime);
          beforeKey = horizontalKey;
          return xSpeed;
     }

     /// <summary>
     /// アニメーションを設定する
     /// </summary>
     private void SetAnimation()
     {
          anim.SetBool("jump", isJump || isOtherJump);
          anim.SetBool("ground", isGround);
          anim.SetBool("run", isRun);
     }

     #region//接触判定
     private void OnCollisionEnter2D(Collision2D collision)
     {
          if (collision.collider.tag == enemyTag)
          {
              //踏みつけ判定になる高さ
              float stepOnHeight = (capcol.size.y * (stepOnRate / 100f));

              //踏みつけ判定のワールド座標
              float judgePos = transform.position.y - (capcol.size.y / 2f) + stepOnHeight;

              foreach (ContactPoint2D p in collision.contacts)
              {
                  if (p.point.y < judgePos)
                  {
                      ObjectCollision o = collision.gameObject.GetComponent<ObjectCollision>();
                      if (o != null)
                      {
                          otherJumpHeight = o.boundHeight;    //踏んづけたものから跳ねる高さを取得する
                          o.playerStepOn = true;        //踏んづけたものに対して踏んづけた事を通知する
                          jumpPos = transform.position.y; //ジャンプした位置を記録する 
                          isOtherJump = true;
                          isJump = false;
                          jumpTime = 0.0f;
                      }
                      else
                      {
                          Debug.Log("ObjectCollisionが付いてないよ!");
                      }
                  }
                  else
                  {
                      anim.Play("player_down");
                      isDown = true;
                      break;
                  }
              }
          }
      }
      #endregion
 }

スタート地点に戻る処理を作る前に、やられた時のアニメーションが終わっているかどうかの判定をとりたいと思います。いきなりスタート地点に戻ってしまっては何が起こったかわからなくなってしまいます。

プレイヤーのスクリプトに↓のメソッドを追加します。

クリックすると展開します
     /// <summary>
     /// ダウンアニメーションが終わっているかどうか
     /// </summary>
     /// <returns>終了しているかどうか</returns> 
     public bool IsDownAnimEnd()
     {
         if (isDown && anim != null)
         {
             AnimatorStateInfo currentState = anim.GetCurrentAnimatorStateInfo(0);
             if (currentState.IsName("player_down"))
             {
                 if (currentState.normalizedTime >= 1)
                 {
                     return true;
                 }
             }
         }
         return false;
     }

プレイヤーのアニメーションの情報を拾ってくるには↓のようにする必要があります。

AnimatorStateInfo currentState = anim.GetCurrentAnimatorStateInfo(0);

このAnimatorStateInfoというのが現在再生中のアニメーション情報になります。

if (currentState.IsName("player_down"))

これが、プレイヤーが再生中のアニメーションがplayer_downかどうかを判定しています。

if (currentState.normalizedTime >= 1)

これでアニメーションの終了判定をしています。normalizedTimeというのはアニメーションの全体の再生時間を1とした場合の数値になります。

1で100%再生、0.1で10%再生が終わったみたいな感じです。正規化と言います。

1以上を指定しているのでアニメーションの再生が完全に終わっていることを意味しています。「1」で完全に終了し、ループすると1より上になります。

ここで注意して欲しいのは、この「1」という数字になるのはアニメーションが他に矢印が設定されていない場合に限ります。

animation state

このようにplayer_downが他から孤立している為、この判定を取る事ができます。

矢印を設定していても遷移さえしなければ判定を取る事ができますが、ちょっとプログラムとしてわかりづらくなってしまうので注意が必要です。

この関数を用意することによって他のスクリプトからプレイヤーのダウンアニメーションが終わっている判定を取る事ができるようになりました。

やられたらスタート地点に戻ってこよう

今度はステージコントローラーからプレイヤーのスクリプトを見て、ダウンアニメーションが終わっていればスタート地点に戻す処理を入れていきます。

クリックすると展開します
using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;

 public class StageCtrl : MonoBehaviour
 {
     [Header("プレイヤーゲームオブジェクト")] public GameObject playerObj;
     [Header("コンティニュー位置")] public GameObject[] continuePoint;

     private Player p;
     
     void Start()
     {
          if(playerObj != null && continuePoint != null && continuePoint.Length > 0)
          {
              playerObj.transform.position = continuePoint[0].transform.position;
            p = playerObj.GetComponent<Player>();
              if(p == null)
              {
                  Debug.Log("プレイヤーが設定されていません");
                  Destroy(this);
              }
          }
          else
          {
              Debug.Log("ステージコントローラーの設定が足りていません");
              Destroy(this);
          }
     }

     // Update is called once per frame
     void Update()
     {
          //プレイヤーがダメージを受けた
          if (p.IsDownAnimEnd())
          {
              playerObj.transform.position = continuePoint[GManager.instance.continueNum].transform.position;
          }
     }
 }

初期設定が足りない場合、ログを残して自身を破棄します。

if(playerObj != null && continuePoint != null && continuePoint.Length > 0)
{
     playerObj.transform.position = continuePoint[0].transform.position;
     p = playerObj.GetComponent<Player>();
     if(p == null)
     {
           Debug.Log("プレイヤーが設定されていません");
           Destroy(this);
     }
}
else
{
     Debug.Log("ステージコントローラーの設定が足りていません");
     Destroy(this);
}

何か設定を忘れてしまった場合はログを確認する事で確認しやすくなります。

さらに、メソッドを用意した事で外から簡単にプレイヤーの情報を得られるようになりました。

if (p.IsDownAnimEnd())
{         playerObj.transform.position = continuePoint[GManager.instance.continueNum].transform.position;
}

プレイヤーのダウンアニメーションが終わったら現在のコンティニューポイントの位置に移動します。

0はスタート地点なのでゲームマネージャーのコンティニューポイントの数値をいじっていなければスタート地点に戻ります。

これで、ゲームマネージャーの値を変えてあげればコンティニューする位置も指定できるようになりました。

return start point

さて、戻ってきたはいいものの、ダウンしぱなっしなので、フラグを解除できるようにしましょう。

プレイヤーに↓のようなメソッドを追加します。

/// <summary>
/// コンティニューする
/// </summary>
public void ContinuePlayer()
{
    isDown = false;
    anim.Play("player_stand");
    isJump = false;
    isOtherJump = false;
    isRun = false;
}

ステージコントローラー側のスクリプトからコンティニューした事をプレイヤーに伝えるようにしましょう。

//プレイヤーがダメージを受けた
if (p.IsDownAnimEnd())
{
    playerObj.transform.position = continuePoint[GManager.instance.continueNum].transform.position;
    p.ContinuePlayer();
}

これでちゃんと戻ってくる事ができるようになりました。

<コンティニューした演出を加えよう>

さて、このままではやられたらパッと戻ってきてしまって実感があんまりわかないので、コンティニューしたという演出を加えてみましょう。

演出と言っても難しい事はせず、ただ点滅させたいと思います。

プレイヤーのスクリプトの中に↓の変数を追加します。

private bool isContinue = false; 
private float continueTime,blinkTime; 
private SpriteRenderer sr = null;

Start内で↓のようにインスタンスを捕まえるのを忘れずに

sr = GetComponent<SpriteRenderer>();

そしてUpdate内に↓を追加します。

クリックすると展開します
     private void Update()
    {
        if (isContinue)
        {
            //明滅 ついている時に戻る
            if(blinkTime > 0.2f)
            {
                sr.enabled = true;
                blinkTime = 0.0f;
            }
            //明滅 消えているとき
            else if (blinkTime > 0.1f)
            {
                sr.enabled = false;
            }
            //明滅 ついているとき
            else
            {
                sr.enabled = true;
            }

            //1秒たったら明滅終わり
            if(continueTime > 1.0f)
            {
                isContinue = false;
                blinkTime = 0f;
                continueTime = 0f;
                sr.enabled = true;
            }
            else
            {
                blinkTime += Time.deltaTime;
                continueTime += Time.deltaTime;
            }
        }
    }

今までFixedUpdateに処理を書いていましたが、今回はレンダリングに関する事なのでUpdateに書きます。

フラグがたったら0.1秒ごとにSpriteRendererをオンオフして点滅する処理を書いています。

blinkTimeというのが0.1秒ごとを測るのに使用している変数で、continueTimeというのが全体の時間になります。0.1秒の点滅を1秒間続けたらフラグを下ろして点滅終わりにします。

↓コンティニューした時にフラグをオンにするようにします。

/// <summary>
/// コンティニューする
/// </summary>
public void ContinuePlayer()
{
     isDown = false;
     anim.Play("player_stand");
     isJump = false;
     isOtherJump = false;
     isRun = false;
     isContinue = true;
}

これで再生すると

continue blink

このようにスタート地点に戻ってきて明滅します。

<まとめ>

今回の変更でプレイヤーのスクリプトは↓のようになりました。

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

 public class Player : MonoBehaviour
 {
     #region//インスペクターで設定する
     [Header("移動速度")] public float speed;
     [Header("重力")] public float gravity;
     [Header("ジャンプ速度")] public float jumpSpeed;
     [Header("ジャンプする高さ")] public float jumpHeight;
     [Header("ジャンプする長さ")] public float jumpLimitTime;
     [Header("接地判定")] public GroundCheck ground;
     [Header("天井判定")] public GroundCheck head;
     [Header("ダッシュの速さ表現")] public AnimationCurve dashCurve;
     [Header("ジャンプの速さ表現")] public AnimationCurve jumpCurve;
     [Header("踏みつけ判定の高さの割合(%)")] public float stepOnRate;
     #endregion

     #region//プライベート変数
     private Animator anim = null;
     private Rigidbody2D rb = null;
     private CapsuleCollider2D capcol = null;
     private bool isGround = false;
     private bool isJump = false;
     private bool isHead = false; 
     private bool isRun = false;
     private bool isDown = false;
     private bool isOtherJump = false;
     private float jumpPos = 0.0f;
     private float otherJumpHeight = 0.0f;
     private float dashTime, jumpTime;
     private float beforeKey;
     private string enemyTag = "Enemy";
     private bool isContinue = false;
     private float continueTime, blinkTime;
     private SpriteRenderer sr = null;
     #endregion

     void Start()
     {
          //コンポーネントのインスタンスを捕まえる
          anim = GetComponent<Animator>();
          rb = GetComponent<Rigidbody2D>();
          capcol = GetComponent<CapsuleCollider2D>();
          sr = GetComponent<SpriteRenderer>();
     }

     private void Update()
     {
          if (isContinue)
          {
              //明滅 ついている時に戻る
              if (blinkTime > 0.2f)
              {
                  sr.enabled = true;
                  blinkTime = 0.0f;
              }
              //明滅 消えているとき
              else if (blinkTime > 0.1f)
              {
                  sr.enabled = false;
              }
              //明滅 ついているとき
              else
              {
                  sr.enabled = true;
              }
              //1秒たったら明滅終わり
              if (continueTime > 1.0f)
              {
                  isContinue = false;
                  blinkTime = 0f;
                  continueTime = 0f;
                  sr.enabled = true;
              }
              else
              {
                  blinkTime += Time.deltaTime;
                  continueTime += Time.deltaTime;
              }
          }
     }
     
     void FixedUpdate()
     {
          if (!isDown)
          {
              //接地判定を得る
              isGround = ground.IsGround();
              isHead = head.IsGround(); 

              //各種座標軸の速度を求める
              float xSpeed = GetXSpeed();
              float ySpeed = GetYSpeed();

              //アニメーションを適用
              SetAnimation();

              //移動速度を設定
              rb.velocity = new Vector2(xSpeed, ySpeed);
          }
          else
          {
              rb.velocity = new Vector2(0, -gravity);
          }
     }

     /// <summary>
     /// Y成分で必要な計算をし、速度を返す。
     /// </summary>
     /// <returns>Y軸の速さ</returns>
     private float GetYSpeed()
     {
          float verticalKey = Input.GetAxis("Vertical");
          float ySpeed = -gravity;

          //何かを踏んだ際のジャンプ
          if (isOtherJump)
          {
             //現在の高さが飛べる高さより下か
             bool canHeight = jumpPos + otherJumpHeight > transform.position.y;
                //ジャンプ時間が長くなりすぎてないか
                bool canTime = jumpLimitTime > jumpTime;

                if (canHeight && canTime && !isHead)
                {
                    ySpeed = jumpSpeed;
                    jumpTime += Time.deltaTime;
                }
                else
                {
                     isOtherJump = false;
                     jumpTime = 0.0f;
                }
           }
          //地面にいるとき
          else if (isGround)
          {
              if (verticalKey > 0)
              {
                  ySpeed = jumpSpeed;
                  jumpPos = transform.position.y; //ジャンプした位置を記録する
                  isJump = true;
                  jumpTime = 0.0f;
              }
              else
              {
                  isJump = false;
              }
          }
          //ジャンプ中
          else if (isJump)
          {
              //上ボタンを押されている。かつ、現在の高さがジャンプした位置から自分の決めた位置より下ならジャンプを継続する
              if (verticalKey > 0 && jumpPos + jumpHeight > transform.position.y && jumpTime < jumpLimitTime && !isHead)
              {
                  ySpeed = jumpSpeed;
                  jumpTime += Time.deltaTime;
              }
              else
              {
                  isJump = false;
                  jumpTime = 0.0f;
              }
          }

          if (isJump || isOtherJump)
          {
              ySpeed *= jumpCurve.Evaluate(jumpTime);
          }
          return ySpeed;
     }

     /// <summary>
     /// X成分で必要な計算をし、速度を返す。
     /// </summary>
     /// <returns>X軸の速さ</returns>
     private float GetXSpeed()
     {
          float horizontalKey = Input.GetAxis("Horizontal");
          float xSpeed = 0.0f;
          if (horizontalKey > 0)
          {
              transform.localScale = new Vector3(1, 1, 1);
              isRun = true;
              dashTime += Time.deltaTime;
              xSpeed = speed;
          }
          else if (horizontalKey < 0)
          {
              transform.localScale = new Vector3(-1, 1, 1);
              isRun = true;
              dashTime += Time.deltaTime;
              xSpeed = -speed;
          }
          else
          {
              isRun = false;
              xSpeed = 0.0f;
              dashTime = 0.0f;
          }

          //前回の入力からダッシュの反転を判断して速度を変える
          if (horizontalKey > 0 && beforeKey < 0)
          {
              dashTime = 0.0f;
          }
          else if (horizontalKey < 0 && beforeKey > 0)
          {
              dashTime = 0.0f;
          }

          beforeKey = horizontalKey;
          xSpeed *= dashCurve.Evaluate(dashTime);
          beforeKey = horizontalKey;
          return xSpeed;
     }

     /// <summary>
     /// アニメーションを設定する
     /// </summary>
     private void SetAnimation()
     {
          anim.SetBool("jump", isJump || isOtherJump);
          anim.SetBool("ground", isGround);
          anim.SetBool("run", isRun);
     }

     /// <summary>
     /// ダウンアニメーションが終わっているかどうか
     /// </summary>
     /// <returns>終了しているかどうか</returns> 
     public bool IsDownAnimEnd()
     {
          if (isDown && anim != null)
          {
              AnimatorStateInfo currentState = anim.GetCurrentAnimatorStateInfo(0);
              if (currentState.IsName("player_down"))
              {
                  if (currentState.normalizedTime >= 1)
                  {
                      return true;
                  }
              }
          }
          return false;
     }
     
     /// <summary>
     /// コンティニューする
     /// </summary>
     public void ContinuePlayer()
     {
          isDown = false;
          anim.Play("player_stand");
          isJump = false;
          isOtherJump = false;
          isRun = false;
          isContinue = true;
     }

     #region//接触判定
     private void OnCollisionEnter2D(Collision2D collision)
     {
          if (collision.collider.tag == enemyTag)
          {
              //踏みつけ判定になる高さ
              float stepOnHeight = (capcol.size.y * (stepOnRate / 100f));
     
              //踏みつけ判定のワールド座標
              float judgePos = transform.position.y - (capcol.size.y / 2f) + stepOnHeight;
     
              foreach (ContactPoint2D p in collision.contacts)
              {
                  if (p.point.y < judgePos)
                  {
                      ObjectCollision o = collision.gameObject.GetComponent<ObjectCollision>();
     
                 if (o != null)
                      {
                          otherJumpHeight = o.boundHeight;    //踏んづけたものから跳ねる高さを取得する
                          o.playerStepOn = true;        //踏んづけたものに対して踏んづけた事を通知する
                          jumpPos = transform.position.y; //ジャンプした位置を記録する 
                          isOtherJump = true;
                          isJump = false;
                          jumpTime = 0.0f;
                      }
                      else
                      {
                          Debug.Log("ObjectCollisionが付いてないよ!");
                      }
                  }
                  else
                  {
                      anim.Play("player_down");
                      isDown = true;
                      break;
                  }
              }
          }
     }
     #endregion
 }

ステージコントラローラーは↓のような感じです。

using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 public class StageCtrl : MonoBehaviour
 {
     [Header("プレイヤーゲームオブジェクト")] public GameObject playerObj;
     [Header("コンティニュー位置")] public GameObject[] continuePoint;

     private Player p;

     void Start()
     {
          if(playerObj != null && continuePoint != null && continuePoint.Length > 0)
          {
              playerObj.transform.position = continuePoint[0].transform.position;
              p = playerObj.GetComponent<Player>();
              if(p == null)
              {
                  Debug.Log("プレイヤーが設定されていません");
                  Destroy(this);
              }
          }
          else
          {
              Debug.Log("ステージコントローラーの設定が足りていません");
              Destroy(this);
          }
     }

     // Update is called once per frame
     void Update()
     {
          //プレイヤーがダメージを受けた
          if (p.IsDownAnimEnd())
          {
              playerObj.transform.position = continuePoint[GManager.instance.continueNum].transform.position;
              p.ContinuePlayer();
          }
     }
 }

何かうまくいかない事があった場合は↓の記事を参考にしてみてください

最低限↓の動画の要件を満たしていない質問は受けかねるので、ご理解ください。

デバッグのやり方【Unity初心者入門講座】【ゲームの作り方】#31

また、筆者も間違えることはありますので、何か間違っている点などありましたら、動画コメント欄にでも書いていただけるとありがたいです。



タイトルとURLをコピーしました