(1)unity キャラクターにレベルアップ、経験値の要素を実装するぞ スクリプト間の変数のやりとり、シーンチェンジの時に破棄されたら困るぞ編

別のスクリプトと変数をやりとりする、シーンチェンジで変数保管用のオブジェクトが破棄されないようにする

敵を倒すと、経験値が入り、一定値以上になるとレベルアップ、そして、キャラクターが強くなる、これをつくっていきます。今回は、2ページ構成です

https://fumimin40.com/post-443/こちらもみてください

今回は、初実装なのでHP 攻撃力 経験値 レベル これくらいのデータだけにしようと思います
目次
1.必要そうなパーツ集め
スクリプト間の変数のやりとり、シーンチェンジでオブジェクトを破棄しない方法
2.試す前にじゅん準備するもの
デバッグログ使ってもいいんだけど、メインメニューにスクリプトを使って
テキストを表示させてみます
3.インターフェースを使って経験値とHPを反映してみます。

先に今回の範囲の動画からどうぞ

攻撃食らったところを、撮り忘れてますが、ちゃんとできました

このページ作った時に買ったものではないですが、僕の買ったやつの2019版ですかね、どうせ買うなら、最新版、自分の使ってるunityのバージョンと合わせて買いましょう、安心ですよ※このページの内容が丸ごと乗っているわけではないです、この本プラスネット検索が大事かもです、でも1冊以上は、買ったほうがいいかもですので、おすすめのやつを紹介

 

今回は、2ページ構成ですレベルアップ要素を実装するぞ2へ

必要そうなパーツ集め

シーンチェンジで破棄されないオブジェクトを作り、それに変数置き場用のスクリプトを作る

DontDestroyOnLoad

statickという変数の使い方でも破棄されない変数を作れるみたいだが、今回は、数が多すぎるので、一つのオブジェクトにADDしたスクリプトを変数置き場にして、破棄されないようにして、使いまわしていく予定です

void Awake()
{
DontDestroyOnLoad(this.gameObject);
}

void Awake()って何、ちょっと調べてきます

ちょっとわかったのがAwake,Startは、Awakeの方が先に読み込まれる、処理されるらしい、どう使い分けるの?僕のイメージでは、一つのスクリプトならいいけど複数のスクリプトがあると、同じAwakeでも処理の順番によって色々起きそうだし、値の参照や、それに伴う代入とかは、気をつけた方がいいかも、くらいしかわからなかった、けど今は、これでよしとしよう、上の書き方を採用することにします

DontDestroyOnLoad(this.gameObject);

多分シーンチェンジで破棄したくないオブジェクトにアタッチしてあるスクリプトにこれを書くだけで解決するはず

スクリプト間での変数のやりとり

基本的には、それを探してゲットコンポーネントして参照の流れっぽいですね

前に作ったスクリプトから取って来たパーツです
private hakoste_02 hakosteyou;  
//hakoste_02(前に作った敵キャラのスクリプトです

 hakosteyou = transform.root.GetComponent<hakoste_02>();

hpslider.value = hakosteyou.hako_hp;

上の列挙されたパーツは、敵キャラにつけているHPバーを動かすためのスクリプトですがhakoste_02というスクリプトから変数を参照するために

まずhakosteyouという名前でhakost_02というスクリプトを参照するためのものを宣言します

その宣言したものに、transform.root.GetComponent<hakoste_02>();別のスクリプトから変数を参照するための準備をしますtransform.rootで親子関係のオブジェクトならこれで良かったのですが、今回は、これは、使えないです、(親子関係ではないオブジェクトからの参照なので)

static int aiueo;

staticを使うこれだと特に何もしなくても参照できるっぽいですが、むやみに使っていいのか?とか今回は、山ほど変数を使うので、今回これの勉強は、見送ります

本題の全く(厳密には、違うけど)関係のないオブジェクトにAddされているスクリプトのデータを参照する方法

スクリプトのパーツを列挙してみます
GameObject aiueo;

aiueo=GameObject.Find("オブジェクト名");

aiueo = GetComponent<そのオブジェクトにADDされているスクリプト名>(); 

hpslider.value = aiueo.参照したい変数名;
//hpslider.valueは前に作ったスライダーのバリューを変更するためのものです
この場合それの値に他のスクリプトの変数を代入しています
GameObject aiueo=GameObject.FInd("オブジェクト名");

hpslider.value = aiueo.GetComponent<スクリプト名>().変数名;

これでいいと思うんだけどなー、早く実験してみたい

下のやつなら2行でいける?

片方だけの参照でいいかと思ったら、お互いに参照し合わないといけないな、なんとかならないかなー

経験値の加算は、せっかくだから覚えたてのインターフェイス使おう

結局static変数を使うことにしました、理由は、全部では、ないですがいろんなところから値を参照する、気がしたからです、文字数も少ないし、簡単だし、デメリットがないような気もする、もしかしたら、使いすぎると重くなる?とか?とりあえず初心者のうちは、便利に使っておくことにします。勉強もしたいのでたまには、上で出てきたやつも使用します、でも今回は、static

ページ内の目次へ戻る

試す前に準備するもの

この実験をする前にメインメニューにテキストでそれぞれの数値を表示させるものを作ります

ゲームが始まると最初に開かれるシーンの空のオブジェクトに次のスクリプトを貼り付けます

数字は、あとで変更するの適当に入れておきました

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

public class sutekanri_m : MonoBehaviour {
    public static int Lv_p=1;
    public static float HP=100;
    public static float HP_max=100;
    public static float ATK=10;
    public static float EXP_rui=0;
    public static float EXP_nextrui=20;
    public static float EXP_next=20;
 // Use this for initialization
 void Start () {}

 public static int Lv_p=1;

こうしておくとオブジェクトが消えても変数が破棄されないし、ほかのスクリプトから簡単に参照できるようになります。

参照の仕方は、次のスクリプトで説明します。ちなみに僕は、そのままほかのスクリプトでも変数名だけで呼び出せると思っていました。

 

メインメニューにこれを表示させますテキストをエディターで貼り付けてそれにこのスクリプトをいれてください

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //これ忘れたらだめだよ
public class LV_cs : MonoBehaviour
{
    // Use this for initialization
    void Start(){}
    // Update is called once per frame
    void Update()
    {
        GetComponent<Text>().text = "LV  " + sutekanri_m.Lv_p;
    }
}

GetComponent<Text>().text = “LV  ” + sutekanri_m.Lv_p;

UIのテキストに貼り付けてゲットコンポーネントして.text=とするとゲーム画面に表示することができます””で囲むと文字列そのまま表示されます「+」を付けてつぎの文字を表示させます、変数を使えばその数値等を表示させることができました。

sutekanri_m.EXP_nextrui + sutekanri_m.EXP_nextrui

こんな実験もしてみましたが足し算は、されずにそのままその値を表示してました
ページ内の目次へ戻る

インターフェースを使って経験値とHPを反映してみます。

インターフェース

エディターのオブジェクトのところに何にもアタッチしないスクリプトに下の赤文字のみのスクリプトをつくります

using UnityEngineとかもなにもなしです

public interface exp_tekiatk_cs
{
    void yoexp_I(int yoexp);
    void yoatk_I(int yoatk);
}
//インターフェース 敵が倒れた時用のEXP
//敵の攻撃用あわせてふたつの作りました

注意点としてインターフェースは、作った機能を使う側が全部使わないといけないらしいので、たくさんいれるとわけわかんなくなるかも

インターフェースを使う側を作ります

上で作ったstatic変数たくさん入れていたスクリプトを編集します、わかりにくくなりそうなので全部はります

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

public class sutekanri_m : MonoBehaviour ,exp_tekiatk_cs{
    public static int Lv_p=1;
    public static float HP=100;
    public static float HP_max=100;
    public static float ATK=10;
    public static float EXP_rui=0;
    public static float EXP_nextrui=20;
    public static float EXP_next=20;
void Awake()
{
DontDestroyOnLoad(this.gameObject);
}
 // Use this for initialization
 void Start () {}
  // Update is called once per frame
 void Update () {}

    void exp_tekiatk_cs.yoexp_I(int yoexp)    
    {                                  
        EXP_rui += yoexp;
    }

    void exp_tekiatk_cs.yoatk_I(int yoatk)
    {                                  
        HP -= yoatk;
    Debug.Log("あいてー");

    }
}

赤いところが追加したところです

public class sutekanri_m : MonoBehaviour ,exp_tekiatk_cs

この赤字を追加するとインターフェースの文が使えるようになります。

void exp_tekiatk_cs.yoatk_I(int yoatk)
    {  HP -= yoatk;}

void ファイル名(インターフェース)その中の使う機能名(インターフェースの中に作ったやつ)次に作るスクリプトでint yoatkに数値が入ると{}の中の文が実行されます。

インターフェースに数字を入れる側のスクリプト

ぼくの、作った敵は、2種類しかいないので2種類にそれぞれ好きな数値を好きな条件で与えていきます

敵の体力がなくなったらオブジェクトを消す前に経験値を与える処理を入れる
 void Update()
    {
        if (tama_hp <= 0)
        {
            var yoexp_tama = GameObject.Find("sutekanri_m").GetComponent<exp_tekiatk_cs>();  
 
            yoexp_tama.yoexp_I(10); 
      //Destroyで破棄する前にこれやっとかないとと思った         
            Destroy(this.gameObject);
            //hpがゼロより少なくなったら、消去
        }
    }

 

private void OnCollisionEnter(Collision col)
    {
        var yodame_kakunin = col.gameObject.GetComponent<exp_tekiatk_cs>();
        if (yodame_kakunin != null)
        {
            yodame_kakunin.yoatk_I(10);
        }
    }//これ間違いです プレイヤーキャラこれと当たってほしいキャラには、
インターフェースついてないので
条件を当たったコライダーがプレイヤーならに変更
インターフェース使った意味なくなっちゃったね

やっとなおりました、インターフェースの意味もあるように作れましたー

 private void OnCollisionEnter(Collision col)
    {
        if (col.gameObject.tag == "Player")  //ここも修正
        {
            var atkatk = GameObject.Find("sutekanri_m").GetComponent<exp_tekiatk_cs>();//ここも修正
            if (atkatk != null)
            {
                atkatk.yoatk_I(10);
            }
        }

    }

説明しまーす、まずonCollisionEnterであたったオブジェクトのタグがPlayer(プレイヤーキャラのタグ設定に設定しておいてください)なら、というif文を作りその中にGameobject.Findでステータス管理用に作ったオブジェクトのsutekanri_mを見つけてゲットコンポーネントそれをatkatkにいれて次のif文でちゃんとゲットコンポーネントされているか、確認します。されているならその中にあるyoatk_Iに10を入れてという流れです

ながくなったので次回へつづくー

(2)unity キャラクターにレベルアップ要素を実装するぞ Next経験値Lvup時のステータスUP等を を自動で計算編

レベルアップ要素を実装するぞ2へ

 

 

ページ内の目次へ戻る

コメント

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