DOTweenで、移動(move)してみる
今日は、DOTweenでimageを移動してみます
おすすめは、DOAnchorPosだそうです。
サンプル
- DOMove=ワールド座標で移動
- DOLocalMove=ローカル座標で移動
- 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は中央ぞろえの時には威力なし
参考
今日は、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() { }
参考
他の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.