Coroutineの使用方法と動作について
Coroutine使用法
コルーチンはコルーチンとして開始した関数内で処理を一旦停止、フレーム単位で停止後(または指定時間後)処理を再開できる機能。
別スレッドので処理を走らせられる(かのような)感。(実際にはマルチスレッドな訳ではない)
関数内で
- 処理A
- 指定時間待機
- 処理B
- 指定時間待機
- 処理C
と言った一連の処理を記述できる。
処理間で待機が入っても、同一関数の処理なので、別途メンバ変数等によるState管理をしなくても、スタック変数で状態を保持できる。
また、時間のかかる処理を行う場合に「関数A->関数B->関数C->関数A」といった形で疑似的に並列処理を行える(懐かしのTSS)。
private IEnumerator _honyaHonyaCoroutine = default; void Start() { _honyaHonyaCoroutine = CoHonyaHonya(); StartCoroutine(_honyaHonyaCoroutine); } private IEnumerator CoHonyaHonya() { // 処理A yield return null; // 処理B yield return new WaitForSconds(3.0f); // 処理C yield return null; // 処理D }
上記のようにIEnumerator型の関数を定義し、StartCoroutineの引数として渡してやることでコルーチンがスタートする。
コルーチンでは、
処理A->1frame待機->処理B->3秒待機->処理C->1frame待機->処理D->終了
という動作を行う。
StopCoroutine等についてはまた別途追記予定。
TextMeshProでのフォントインストール方法
TextMesh Proでttfファイルのフォントをインストールする方法
まず、使用するフォントファイル(ここではttfファイル)をダウンロードしててから、
Assets -> Import New Assetsで該当のファイルをUnityに取り込みます。
Window -> TextMeshPro -> Font Assets Creatorを開きます。
開いたFont Assets Creatorのウィンドウで、Source Font Fileにインポートしたttfを指定して、Generate Font Atlasをクリック!
出来たアセットファイルを適当なフォルダにセーブして(TextMesh Pro/Resources/Font & Materials辺りが妥当か)、インポートしたttfファイルを削除して完成。
以上で、Text Mesh Pro UGUIのコンポーネントでFont Assetとして使用できるようになります。
こんな感じ(HAMMER OF GODの部分)
Unityの処理停止について
Time.timeScale について止まるもの止まらないもの
Unityで停止処理を行う際に使えるのが、Time.timeScaleですが、止まる処理と止まらない処理がある。
Time.timeScaleは基本的に1で通常時間、0に近づくにつれて時間の経過をスローにしていくことができる。
0にすると、時間関連を停止することができ、FixedUpdateが呼ばれなくなる。また、Time.deltaTimeによる時間経過も進まなくなる。
ただし、Updateは変わらず呼ばれるため、Update内の処理でTime.deltaTimeを加味していない場合止まらない。
止まる処理
void Update() { transform.Translate(2.0f * Time.deltaTime, 0, 0); } }
止まらない処理
void Update() { transform.Translate(2.0f , 0, 0); } }
Rigidbodyへの操作は内部的に経過時間が加味されているため、重ねてTime.deltaTimeを加味していなくても止まる。最も、本来Rigidbody操作はFixedUpdateでやるべきなのでどちらにせよFixedUpdateは呼ばれないけれども。
追記
パーティクルシステムも止まってしまうので使いづらい……メニュー開いたときとかに止める用かな。
Mathf.Round 備忘録
Mathf.Roundすぐ忘れるんで。
Mathf.Round(float f)
偶数丸め。
一番近い整数に数値を丸めるが、小数点以下が ~.5で終わる場合は最も近い上下の整数のうち偶数側に丸める。
よって
using System.Collections; using System.Collections.Generic; using UnityEngine; public class test1 : MonoBehaviour { // Start is called before the first frame update void Start() { Debug.Log(Mathf.Round(10.49f)); Debug.Log(Mathf.Round(10.5f)); Debug.Log(Mathf.Round(10.51f)); Debug.Log(Mathf.Round(11.49f)); Debug.Log(Mathf.Round(11.5f)); Debug.Log(Mathf.Round(11.51f)); } }
10.5は10.5の上下の整数が10と11なので偶数である10に丸める。
11.5は11.5の上下の整数が11と12なので偶数である12に丸める。
それ以外は普通に四捨五入な感じに丸める。
~.5の場合のみ単純な四捨五入にはならないので注意。
お・ま・け
Mathf.Floor(float f) 小数点以下切り捨て。
Mathf.Ceil(float f) 小数点以下切り上げ。
オブジェクトの動的生成 Scriptから
Resources.Load
前準備
- 動的生成を行いたいオブジェクトのプレハブを作成。
- Assets直下にResourcesフォルダを作成
- 1で作成したプレハブを2に配置
ここからScriptでの動的なオブジェクト生成処理。
using System.Collections; using System.Collections.Generic; using UnityEngine; using PlayerControl; namespace PlayerControl { public class BulletController : MonoBehaviour { private void DeactivateSelf() { // 爆発エフェクトオブジェクトを表示 GameObject explosiveCircleObj = (GameObject)Resources.Load("ExplosiveCircle"); Instantiate(explosiveCircleObj, transform.position, Quaternion.identity); }
上記のScriptでResouces配下においたプレハブ"ExplosiveCircle"のオブジェクトを取得し、そのオブジェクトをtransform.positionで指定した位置に生成できます。 上記は、オブジェクトの取得からScriptで行っているが、Unityの方でプレハブのオブジェクトを設定しておきそれをInstantinateするという方法でも実行可能。(この辺どっちが良いのか場合によるのだろう) 以下のような感じ。
using System.Collections; using System.Collections.Generic; using UnityEngine; using PlayerControl; namespace PlayerControl { public class BulletController : MonoBehaviour { // 爆発エフェクトのオブジェクト [SerializeField] private GameObject ExplosiveObj; private void DeactivateSelf() { Instantiate(explosiveCircleObj, transform.position, Quaternion.identity);
取りうる値の制限(オブジェクトの移動範囲の制限など)
Mathf.Clamp intまたはfloatの値の範囲を制限する
使用法はIntもFloatも同様。第一引数で与えられるValueを第二引数(最小値)、第三引数(最大値)の間に制限する。 この場合表示される値は3となる(最大値より大きい10であるため)。
using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { // Use this for initialization void Start() { // Clamps the value 10 to be between 1 and 3. // prints 3 to the console Debug.Log(Mathf.Clamp(10, 1, 3)); } }
これを利用してオブジェクトの移動などに制限を加える。 Mathf.Clampでオブジェクトが取りうるtransform.positionの値を-8~8に制限し、その範囲を超えてオブジェクトが移動することを防ぐ。
void Update() { // X方向に入力*速度*時間分移動させる this.transform.Translate(Input.GetAxisRaw("Horizontal") * MoveSpeed * Time.deltaTime, 0, 0); // X方向の移動範囲を制限する this.transform.position = new Vector2(Mathf.Clamp(this.transform.position.x, -8.0f, 8.0f), transform.position.y); }
衝突時のTrigger処理
OnTriggerEnter系とCompareTag
ColliderのコンポーネントでIs Triggerのチェックを入れていた場合、以下は2Dの場合。 引数のcollisionに衝突したオブジェクトの情報がある。CompareTagでオブジェクトにTagが設定されているかどうかチェックできる。
private void OnTriggerEnter2D(Collider2D collision) { // 隕石またはターゲットマーカのオブジェクトと接触した場合、爆発処理 if (collision.gameObject.CompareTag("Meteor") || collision.gameObject.CompareTag("TargetMarker")) { DeactivateSelf(); } } }
同系列でOnTriggerExitとOnTriggerStayがあり、Exitはオブジェクトの衝突が終わった(離れた)時、Stayはオブジェクトが重なっている間中コールされる。 また、それぞれ2Dの場合は末尾に2Dが付く。 これはまた後日。