DOTweenで、移動(move)してみる

今日は、DOTweenでimageを移動してみます
おすすめは、DOAnchorPosだそうです。

サンプル

  1. DOMove=ワールド座標で移動
  2. DOLocalMove=ローカル座標で移動
  3. DOAnchorPos=アンカーを意識してくれる(RectTransform)が必要
using DG.Tweening;  //DOTweenを使うときはこのusingを入れる

public class GameManager : MonoBehaviour
{
    public Transform ob1;

    IEnumerator Start()
    {
        ob1.gameObject.transform.localPosition = Vector3.zero;
        Debug.Log("DOMove:" + ob1.gameObject.transform.localPosition);
        ob1.gameObject.transform.DOMove(new Vector3(1000f, 0f, 0f), 3f);
        yield return new WaitForSeconds(3.0f);
        Debug.Log("DOMove:" + ob1.gameObject.transform.localPosition);

        ob1.gameObject.transform.localPosition = Vector3.zero;
        Debug.Log("DOLocalMove:" + ob1.gameObject.transform.localPosition);
        ob1.gameObject.transform.DOLocalMove(new Vector3(1000f, 0f, 0f), 3f);
        yield return new WaitForSeconds(3.0f);
        Debug.Log("DOLocalMove:" + ob1.gameObject.transform.localPosition);

        ob1.gameObject.transform.localPosition = Vector3.zero;
        Debug.Log("DOAnchorPos:" + ob1.gameObject.transform.localPosition);
        ob1.gameObject.GetComponent<RectTransform>().DOAnchorPos(new Vector3(1000f, 0f, 0f), 3f);
        yield return new WaitForSeconds(3.0f);
        Debug.Log("DOAnchorPos:" + ob1.gameObject.transform.localPosition);
    }

メモ

  • localPositionで位置をリセット
  • DOAnchorPosの利用には、 .GetComponent()を使う
  • DOAnchorPosは中央ぞろえの時には威力なし

参考

umistudioblog.com

qiita.com

今日は、localPositionで画像位置のセット(学習中)

今日のひとこと
座標の取得と、セットはよくわからなければlocalPosition」を使おう。

例:(100,100)の位置に移動して、10秒待機する

ポイント
①「localPosition」と「position」の位置が違う点。
 ※positionは画面左下
 ※localPositionは画面中央<こちらの方が作成者意図に近い
②「Vector3」の前に「new」を書く
③「Vector3」の座標は「x,y,z」=「横,高さ,奥行(2Dでは使わない)」
※3Dの学習はしていないので、zについては詳しく見ていない
④「.transform.localPosition = Vector3.zero」で元の位置(0,0,0)に戻す

    public Transform ob1, ob2;

    static bool flag = true;
    IEnumerator C_Color()
    {
        if (flag == true)
        {
            flag = false;

            ob1.gameObject.transform.position += new Vector3(100, 500, 0);
            Debug.Log("World:"+ob1.gameObject.transform.position);
            Debug.Log("Local:" + ob1.gameObject.transform.localPosition);
        
            yield return new WaitForSeconds(10.0f);

//            ob1.gameObject.transform.localPosition = Vector3.zero;
//            yield return new WaitForSeconds(10.0f);

            flag = true;
        }
    }
    void Update()
    {
        StartCoroutine(C_Color()); 
    }

updateでコルーチンを使う(学習中)

まずは成功例

成功

ob1が「赤」→「青」→「黄色」と変化して
ob2が「赤」「青」を繰り返す
※staticでスタートを始めたら、それ以外のスタートをブロックする
(並列実行しないようにする)

    public Transform ob1, ob2;

    static bool flag = true;
    IEnumerator C_Color()
    {
        if (flag == true)
        {
            flag = false;
            ob1.gameObject.GetComponent<Image>().color = Color.red;
            yield return new WaitForSeconds(1.5f);
            ob1.gameObject.GetComponent<Image>().color = Color.blue;
            yield return new WaitForSeconds(1.5f);
            ob1.gameObject.GetComponent<Image>().color = Color.yellow;
            yield return new WaitForSeconds(1.3f);

            if(ob2.gameObject.GetComponent<Image>().color == Color.red)
                ob2.gameObject.GetComponent<Image>().color = Color.blue;
            else 
                ob2.gameObject.GetComponent<Image>().color = Color.red;
            flag = true;
        }
    }

    void Update()
    {
        Debug.Log("st");
        StartCoroutine("C_Color"); 
        Debug.Log("ed");
    }

失敗1:

Updateの中で、コルーチンが並列実行されて、いつまでも始まらず、終わらない

    public Transform ob1, ob2;

    IEnumerator C_Color()
    {
            ob1.gameObject.GetComponent<Image>().color = Color.red;
            yield return new WaitForSeconds(1.5f);
            ob1.gameObject.GetComponent<Image>().color = Color.blue;
            yield return new WaitForSeconds(1.5f);
            ob1.gameObject.GetComponent<Image>().color = Color.yellow;
            yield return new WaitForSeconds(1.3f);
    }
    void Update()
    {
        Debug.Log("st");
        StartCoroutine("C_Color"); 
        Debug.Log("ed");
    }

失敗2:

staticの位置がエラー

    public Transform ob1, ob2;

    IEnumerator C_Color()
    {
        static bool flag = true;
        if (flag == true)
        {
            flag = false;
            ob1.gameObject.GetComponent<Image>().color = Color.red;
            yield return new WaitForSeconds(1.5f);
            ob1.gameObject.GetComponent<Image>().color = Color.blue;
            yield return new WaitForSeconds(1.5f);
            ob1.gameObject.GetComponent<Image>().color = Color.yellow;
            yield return new WaitForSeconds(1.3f);
            flag = true;
        }
    }
    void Update()
    {
        Debug.Log("st");
        StartCoroutine("C_Color"); 
        Debug.Log("ed");
    }

おまけ

    StartCoroutine("C_Color");  

は古い書き方で
StartCoroutine(C_Color());
が新しい書き方らしいです

本日はコルーチンを勉強する(学習中)

コルーチンが理解できていないので、調べてやってみる。

テスト1: 勉強した通りに書いてみた。
(startにIEnumeratorを直接書くのは新鮮だったので、載せてみた)

    public Transform ob1, ob2;
    public Text txt1, txt2;

    IEnumerator Start()
    {
        Debug.Log("st");
        ob1.gameObject.GetComponent<Image>().color = Color.red;
        yield return txt1_Count(10.0f);
        ob1.gameObject.GetComponent<Image>().color = Color.blue;
        yield return txt2_Count(10.0f);
        ob1.gameObject.GetComponent<Image>().color = Color.yellow;
        yield return txt1_Count(3.0f);
        ob2.gameObject.GetComponent<Image>().color = Color.red;
        Debug.Log("ed");
    }

    IEnumerator txt1_Count(float maxTime)
    {
        float xTime;
        xTime = 0;
        int c = 0;

        while (c < (int)maxTime)
        {
            xTime += Time.deltaTime;
            c++;
            txt1.text = c.ToString();
            Debug.Log("1:"+xTime);
            yield return new WaitForSeconds(1f);
        }
    }

    IEnumerator txt2_Count(float maxTime)
    {
        float xTime;
        xTime = maxTime;
        int c = (int)maxTime;

        while (c > 0)
        {
            c--;
            txt2.text = c.ToString();
            xTime = xTime - Time.deltaTime;
            Debug.Log("2:"+xTime);
            yield return new WaitForSeconds(1f);
        }
    }

スト2:実験(動く想定)
なんだ、こいつ動くぞ!! って、これは大丈夫。

    public Transform ob1, ob2;

    IEnumerator Start()
    {
        Debug.Log("st");
        ob1.gameObject.GetComponent<Image>().color = Color.red;
        yield return new WaitForSeconds(2f);
        ob1.gameObject.GetComponent<Image>().color = Color.blue;
        yield return new WaitForSeconds(2f);
        ob1.gameObject.GetComponent<Image>().color = Color.yellow;
        yield return new WaitForSeconds(3f);
        ob2.gameObject.GetComponent<Image>().color = Color.red;
        Debug.Log("ed");
    }

テスト3:やっぱり動きませんでした。

    IEnumerator Update()
    {
    }

参考

shibuya24.info

他のGameObjectを取得する(学習)

unityの基礎がわかったぞ!
と思い作り始めたが、基礎が記述できるだけで理解が低かったことに気づき、 前回から再度基礎の勉強。

今回は、
①GameObjectの名前を取得 ②GameObjectでローカル座標を取得する
③GameObjectでワールド座標を取得する
④自分の親GameObjectを取得する ⑤GameObjectでActiveのON/OFFで遊ぶ

①GameObjectの名前を取得

情報取得はpublicで行う。
他の方法もあるが、初心者なので欲張らない

    public Transform myTransform;

    void Start()
    {
        Debug.Log(
            myTransform.name
        );
    }

②GameObjectでローカル座標を取得する

    void Start()
    {
        Debug.Log(
            myTransform.name
            + ":" +
            myTransform.localPosition //ローカル
        );
    }

③GameObjectでワールド座標を取得する

    void Start()
    {
        Debug.Log(
            myTransform.name
            + ":" +
            myTransform.localPosition //ローカル
            + ":" +
            myTransform.position //ワールド
        );
    }

④自分の親GameObjectを取得する

    void Start()
    {
        Debug.Log(
            myTransform.parent.name
            + ":" +
            myTransform.parent.localPosition //ローカル
        );
    }

⑤GameObjectでActiveのON/OFFで遊ぶ

    void Start()
    {
        Debug.Log(
            myTransform.name
            + ":" +
            myTransform.localPosition //ローカル
            + ":" +
            myTransform.position //ワールド
        );

        myTransform.gameObject.SetActive(false);

        Debug.Log(
            myTransform.parent.name
            + ":" +
            myTransform.parent.localPosition //ローカル
        );

        myTransform.gameObject.SetActive(true); //これは動かない
    }

GameObject の外部呼出し4選(学習のみ)

次の方針で使うのが良さそう

分類 特性
Find 外部から少数のGameObjectを使う
FindWithTag 外部から複数のprefabを使う
public 自分より上位のGameObjectを使う
static 単一の共通のGameObjectを使う

1. Findを使う

GameObject.Find

メリット:
  • 事前作業不要
    デメリット:
  • 同名があった場合に識別できない(prefabなどには不向き)

GameObject gameManegerObj = GameObject.Find("GameManeger")

GameManeger gameManeger =  gameManegerObj.Find("GameManeger")//script

gameManeger.Sample();

2.FindWithTagを使う

GameObject.FindWithTag

メリット:
  • 複数あってもTagがあれば識別可能
  • unity推奨
    デメリット:
  • タグ付けるのが面倒
    • 非表示のときには、findできない

GameObject gameManegerObj = GameObject.FindWithTag("GameManeger")

GameManeger gameManeger =  gameManegerObj.Find("GameManeger")//script

gameManeger.Sample();

3.public+エディタで事前設定

public+エディタ

メリット:
  • よく使うCompornentのみを指定できる。(ソースコードが短くできる)
  • 自分の子供のGameObjectを指定するのが簡単
  • prefabで自分自身の参照に利用推奨?
    デメリット:
  • 事前登録が面倒

public GameManeger gameManeger; //hierarchyで事前設定 シリアライズフィールドでもOK

gameManeger.Sample();

4.staticでinstanceを持つ

メリット:
  • オブジェクトの共通化が簡単
  • 呼び出し側の設定が短い
    デメリット:
  • ゲーム内にオブジェクトが1つしかないこと
    • 目的のオブジェクトへ事前のソース記載が必要

public static GameManeger instance;
private void Awake()
{
    instance=this;
}
GameManeger.instance.Sample();

updateの中でStartCoroutineが正常動作しない件

いろいろやったけど、わからなくて聞いてみた

GPT

コードを見ると、Update()内でStartCoroutine()を使っていますが、これは注意が必要です¹。

Update()は毎フレームごとに処理される関数なので、スタートさせるコルーチンが1フレームで終了しない場合だと、毎フレームごとにどんどん増えていきます¹。

コルーチンの実行順番も、初回と2回目以降で異なります³。

初回は、StartCoroutine()よりも上の部分のUpdate()関数内の処理→コルーチン→StartCoroutine()よりも下の部分のUpdate()関数内の処理となります³。

2回目以降は、Update()関数内の処理全て→コルーチンの続きとなります³。

したがって、表示がでないのは、コルーチンが毎フレームごとにスタートしてしまい、終了しないからだと思われます¹。

解決策としては、コルーチンをStart()Awake()などの一度しか呼ばれない関数でスタートさせるか、フラグを使って一度しかスタートしないようにするか、コルーチンを使わずにタイマーを使うかなどが考えられます¹²。

詳細は、以下の記事をご覧ください。¹²³

unityに関する他の質問はありますか?🤔

ソース: Bing との会話 2023/8/16 (1) Unityにおけるコルーチンの性質まとめ - Qiita. https://qiita.com/kazz4423/items/73219068684e87adc87d. (2) Coroutine,Updateの実行順番 - Qiita. https://qiita.com/keito_takaishi/items/c0347d57b38dd28cf8e2. (3) MonoBehaviour-StartCoroutine - Unity スクリプトリファレンス. https://docs.unity3d.com/ja/current/ScriptReference/MonoBehaviour.StartCoroutine.html.