【Unity】GetComponentを多用してました(お詫び)

2021/2/19タイトル修正・Transformについて追加



2021年初投稿となります。

年末は体重管理アプリ作成が思うように進展しなくて、
ブログをお休みしていました…

とは言っても、まだ完成してはいないのですが…
(;^o^) \(ToT )あんたほんとにそれでいいの


話は変わるのですが、
少し前にコメントを頂いて、プログレスバーのタイマー記事を修正しました。

過去記事を見ているとスクリプトに無駄が多くて恥ずかしくなるのですが、
間違ってる所が多々あったのでお詫び致します。

それは、GetComponentの使い方です _(._.)_ ユルシテ

無駄なGetComponentを組んでいるので、
間違いの部分をピックアップしていきたいと思います。

FindとTransformについても記事にしておきたい事があるので、
併せて、まとめてみたいと思います。

Unityのバージョンは、2020.2.3f1になります。

まずは、Findからまとめます。
Findって、ついつい使いがちにならないでしょうか?

例えば、メインキャラクターを取得して何かをさせたい場合、

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

public class MainCharacter : MonoBehaviour
{

private GameObject mainCharacter; //メインキャラ取得用
private Transform mainCharaTran; //メインキャラTransform

// Start is called before the first frame update
void Start()
{
mainCharacter = GameObject.Find("MainCharacter");
mainCharaTran = mainCharacter.GetComponent<Transform>();
}

}

こんなスクリプトになりそうですが、
これってどうなのかな~??
と良く考えます。

Findのコマンドは、ゲームオブジェクトをヒエラルキーから探す
コマンドになります。

Findで指定したゲームオブジェクトを見つけるまで
一つ一つチェックする事になります。

単純に、この処理だけなら重くもならないのですが、
例えば、10個のオブジェクトをFindしたりするとどうなるのかな~

100個なら?
1000個なら?

カクカクの動きになりそうですね (;^_^A アセアセ・・・

と言う事で検索するリソースを抑える為に

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

public class MainCharacter : MonoBehaviour
{
[Header("メインキャラ")]
public GameObject mainCharacter;

private Transform mainCharaTran; //メインキャラTransform

// Start is called before the first frame update
void Start()
{
mainCharaTran = mainCharacter.GetComponent<Transform>();
}

}

UIテスト①.jpg
パブリックな変数にしてインスペクターからアタッチする
これで検索のリソースを減らす事ができます。

結構、アタッチする数が増えると面倒ですが、
これは確実にやった方がいいと思っています。

では、Findを使う時って?となりますが…

やはり、プレイ中に生成したオブジェクトでしょうか。

プレハブには、他のオブジェクトをpublicで取り込む事ができないので、
他のスクリプトと連携させる場合はFindを使うしかありません。

できるだけ、見えてるオブジェクトはpublicで取得しておいて、
生成するオブジェクトにFindを使うようにすれば抑える事ができそうです。

さて、
Findについては、これくらいにしておいて…

続いて、Transformになります。
上のスクリプトでも使ってましたが、
mainCharaTran = mainCharacter.GetComponent<Transform>();
これって、今までなら当たり前だったのですが、
要らなくなってますね~ (~ヘ~;)ウーン

いつからなんでしょう?

以前は、スクリプトを組んで行くと
Transformを取得しないと赤波線が出てTransformを操作できなかった
と思っているのですが…

リファレンスを読んでないので、
いつから変わったのか分かりません(;^_^A アセアセ・・・

現時点では、Componentを取得しなくても、
Transformを操作できるようになっています。


ここからは、お詫びの内容になります。
過去記事のGetComponentの使い方の問題なんですが…

凄い無駄とリソースを使ったスクリプトを作っていました。
参考にして頂いてる方には、この場をお借りしてお詫びします。
(_ _(--;(_ _(--; pekopeko

過去記事の問題点を書いてみます。

まず、説明の為にSceneを作りました。
UIテスト②.jpg
uGUIとして、
・スコアtext
・フィールドImage
・キャラImage
・キャラの上にネームText
・ネーム入力InputField

このuGUI群をスクリプトから操作するのですが、
過去の知識でスクリプトを組んでみます。

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

public class UI_Test : MonoBehaviour
{
/// <summary>
/// オブジェクト・コンポーネント
/// </summary>

///パブリック
[Header("キャラ関連")]
public GameObject mainCharacter; //キャラ本体
public GameObject nameTxObj; //ネームTextオブジェクト

[Header("スコアtext")]
public GameObject scoreTxObj; //スコアTextオブジェクト

[Header("フィールドImage")]
public GameObject fieldImageObj; //フィールドImageオブジェクト

[Header("ネーム入力")]
public GameObject inputNameObj; //ネーム入力InputFieldオブジェクト


///プライベート
private Transform mainCharaTran; //メインキャラTransform
private Text nameTx; //キャラネームText

private Text scoreTx; //スコアText

private Image fieldImage; //フィールドImage

private Text inputNameTx; //ネーム入力Text(InputField内)


/// <summary>
/// メソッド
/// </summary>

// Start is called before the first frame update
void Start()
{
//キャラの各コンポーネント取得
mainCharaTran = mainCharacter.GetComponent<Transform>();
nameTx = nameTxObj.GetComponent<Text>();
//スコアtext取得
scoreTx = scoreTxObj.GetComponent<Text>();
//フィールドImage取得
fieldImage = fieldImageObj.GetComponent<Image>();
//ネーム入力text取得
inputNameTx = inputNameObj.GetComponent<Text>();

}

// Update is called once per frame
void Update()
{

}
}

こんな感じでスクリプトを書いていました。

当時は、GameObjectを取り込んで、
コンポーネントを取得する必要があると勘違いしており
正直、無駄なリソースを使い過ぎていました。(-_-;)

プレイ中のリソースもさることながら、
スクリプトを組む手間まで増やしておりました (..*) オハズカシイ・・

この問題点は、不必要なGetComponentを繰り返している事です。
修正すると

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

public class UI_Test : MonoBehaviour
{
/// <summary>
/// オブジェクト・コンポーネント
/// </summary>

///パブリック
[Header("キャラ関連")]
public GameObject mainCharacter; //キャラ本体
public Text nameTx; //キャラネームText

[Header("スコアtext")]
public Text scoreTx; //スコアText

[Header("フィールドImage")]
public Image fieldImage; //フィールドImage

[Header("ネーム入力")]
public InputField inputName; //ネーム入力InputField


/// <summary>
/// メソッド
/// </summary>

// Start is called before the first frame update
void Start()
{

}

// Update is called once per frame
void Update()
{

}
}

public変数をUIネームにする事で、uGUIを直接取得できるようになります。

UIネームで変数宣言をして、アタッチすれば
GetComponentをする必要がないんですよ~ (*○*;) ギョッ

using UnityEngine.UI;を宣言しないとUIを使えないのですが、
宣言する事で、同時にコンポーネントの取得まで行ってくれます。

なので、GetComponentを追加すると同じコンポーネントを再度
取得すると言う無駄な事をやっていました。(T-T) グスッ

更にTransformも、今では取得する必要がありません。

試しに何かメソッドを組んで動かしてみます。

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

public class UI_Test : MonoBehaviour
{
/// <summary>
/// オブジェクト・コンポーネント
/// </summary>

///パブリック
[Header("キャラ関連")]
public GameObject mainCharacter; //キャラ本体
public Text nameTx; //キャラネームText

[Header("スコアtext")]
public Text scoreTx; //スコアText

[Header("フィールドImage")]
public Image fieldImage; //フィールドImage

[Header("ネーム入力")]
public InputField inputName; //ネーム入力InputField


//メインキャラの移動変数
private bool dire = true;
private float speed = 200f;


//カラーコード
private Color32 blue = new Color32(80, 180, 215, 255);


/// <summary>
/// メソッド
/// </summary>

// Start is called before the first frame update
void Start()
{
//各メソッド呼び出し
ScoreUpdate();
FieldColorChange();
}

// Update is called once per frame
void Update()
{
if (mainCharacter.transform.localPosition.x >= 250f && dire) dire = false;
if (mainCharacter.transform.localPosition.x <= -250f && dire == false) dire = true;
MoveChara();
}



//スコアの更新
private void ScoreUpdate()
{
scoreTx.text = "Hi:10万点";
scoreTx.color = Color.red;
}

//フィールドの色を変える
private void FieldColorChange()
{
fieldImage.color = blue;
}

//キャラネーム入力
public void NameChange()
{
nameTx.text = inputName.text;
inputName.text = string.Empty;
}

//メインキャラのムーブメント
private void MoveChara()
{
float amount = dire ? Time.deltaTime * speed : Time.deltaTime * -speed;
float pos = mainCharacter.transform.localPosition.x + amount;
mainCharacter.transform.localPosition = new Vector3(pos, 0f, 0f);
}
}

各変数にアタッチして
UIテスト③.jpg
InputFieldの入力完了にNameChangeメソッドを割り当てたら
UIテスト④.jpg
PLAYしてみます。

動画が小さくて分かりにくいですが、
無事にUIの操作が出来ています。

拙い知識で記事を書いているので、参考にされた方には
本当に申し訳ないです。_(._.)_ ユルシテ

余りにも初歩的な間違いを放置していると、UnityできるよTシャツのネタに
なりそうなので、怖いのですが…

なにはともあれ拙い知識ですが、これからも発信していこうと思っています。
何かおかしいとか、ここはこう書けばいいとかあれば
コメント頂けるとうれしいでっす。


それでは、コロナに負けず、より良いUnityライフを送ってくださいませ。
今回は、このへんで( ^ 0 ^ )/~~~~see you again

この記事へのコメント