- 投稿日:2020-01-21T22:29:25+09:00
オブジェクトのサイズを等倍にしたい
- 投稿日:2020-01-21T22:09:42+09:00
【Unity/C#】コルーチンを自前で動かすためにIEnumeratorについて簡単に調べた
コルーチンを自前で動かしたい
コルーチンは
MonoBehaviour
を継承していればStartCoroutine
で動かすことができます。しかし、MonoBehaviour
を継承していなくても使いたい場面は割と多いです、多分。
MonoBehaviour
なしでコルーチンを動かす方法は調べるとそれなりに出てきますが、そもそもコルーチンで使われているIEnumerator
とはなんぞ?から始めたい所存です。IEnumeratorインターフェース?
MSDNを見てみるとシンプルに書かれています。
非ジェネリック コレクションに対する単純な反復処理をサポートします。
IEnumerator
インターフェースは反復処理を実現するためのインターフェースになります。
コルーチンはUnityが反復処理をいい感じに実行してくれてる仕組みというわけですね。反復処理を作って動かしてみる
とりあえず物は試しということでUnityで適当な反復処理を作ってみます。
わかりやすくデバッグログも出してこんな感じに。SampleCoroutine.cspublic IEnumerator Coroutine() { Debug.Log("Coroutine 1"); yield return 1; Debug.Log("Coroutine 2"); yield return 2; }こいつをこんな感じで動かしてみます
SampleCoroutine.cspublic void Sample() { var iEnumerator = Coroutine(); while (iEnumerator.MoveNext()) { Debug.Log($"Coroutine Return {iEnumerator.Current}"); } }ConsoleCoroutine 1 Coroutine Return 1 Coroutine 2 Coroutine Return 2おもったよりかんたん!
何をやっているの?
まずは反復処理についてです。何気なく使っている
yield
ですが、yield
を含むブロックのことをイテレータブロックと言います。
大雑把に説明すると「1回の処理でここまでやってね」というブロックになります。yield
には値を返すreturn
と処理を抜けるbreak
の2つのキーワードがあります。次に
MoveNext
です。これはイテレータを次に進ませます。イテレータが進んだ場合はtrue
を返すため、while
を使うとイテレータを全て進めることができます。
Current
は反復処理が返した値を保持しているプロパティです。yield return
で返した値がそのまま入ってくる感じですね。
object
型なので色んなものを返せます。SampleCoroutine.cspublic IEnumerator Coroutine() { yield return 1; yield return 9.6; yield return "ほげえ"; }ConsoleCoroutine Return 1 Coroutine Return 9.6 Coroutine Return ほげえまた、
Reset
に関してですが、こちらは自前で実装する必要があります(実装してないとNotSupportedException
がスローされます)。
単純にIEnumerator
インターフェースで実装した反復処理メソッドをやり直したい場合は対象のメソッドを再び取得して動かします。SampleCoroutine.cspublic void Sample() { var iEnumerator = Coroutine(); while (iEnumerator.MoveNext()) { Debug.Log($"Coroutine Return {iEnumerator.Current}"); } // iEnumerator.Reset(); <- NotSupportedExceptionがスローされる iEnumerator = Coroutine(); while (iEnumerator.MoveNext()) { Debug.Log($"Coroutine Return {iEnumerator.Current}"); } }思ったよりシンプル!これなら
StartCoroutine
なしでもなんとかなりそう・・・?WaitFor関係は更に自前で実装しないとダメ
注意点として
WaitForSecounds
等は単純にyield return
しただけではうまくいかないです。
よくあるのがyield return WaitForSeconds
でカウントをするコルーチンですが、単純にMoveNext
をしただけではできません。
MoveNext
は1フレーム毎にイテレータを進めるというイメージが良いと思います。この辺はStartCoroutine
がいい感じに処理してくれてる部分です。反復処理の入れ子をやりたい
反復処理から反復処理を実行するような形にすればできます。実は
IEnumerator
インターフェースを調べ始めたきっかけでもあります。SampleCoroutine.cspublic IEnumerator Coroutine() { Debug.Log("Coroutine Start"); var coroutine2 = Coroutine2(); while (coroutine2.MoveNext()) { yield return coroutine2.Current; } Debug.Log("Coroutine End"); } public IEnumerator Coroutine2() { Debug.Log("Coroutine2 1"); yield return 1; Debug.Log("Coroutine2 2"); yield return 2; } public void Sample() { var iEnumerator = Coroutine(); while (iEnumerator.MoveNext()) { Debug.Log($"Coroutine Return {iEnumerator.Current}"); } }ConsoleCoroutine Start Coroutine2 1 Coroutine Return 1 Coroutine2 2 Coroutine Return 2 Coroutine Endおしまい
何気なく使っていたコルーチンと
IEnumerator
インターフェースですが、思ったよりシンプルでした。
これでもまだ触りの部分だと思いますが、当初の目的を達成しつつある程度は分かった気がしたのでとりあえずOKとしましょう。何かあったらコメントください。
参考
++C++; // 未確認飛行 C イテレーター
WisdomSoft 処理の分割(コルーチン)
Qiita:[C#]IEnumeratorとIEnumerableを調べた
- 投稿日:2020-01-21T21:34:18+09:00
ひたすら回転するオブジェクトを数値入力で制御する
無理して外出しにしなくていいけれど、あとあと変えたいのであればぜひ。
public float Rot_x; public float Rot_y; public float Rot_z; void Update() { transform.Rotate(Rot_x,Rot_y,Rot_z); }
- 投稿日:2020-01-21T21:29:12+09:00
キー押下でScene再読み込みをする(リロード、リトライ的なもの)
実行ボタンのオンオフがめんどくなってきたら、
カメラなどオブジェクトの存在が一定の物に対して、スクリプトをアタッチしておくと楽チン実質3行の追加で実装完了
必要なのは下記のとおり
using UnityEngine.SceneManagement;
void Update() { if (Input.GetKey(KeyCode.Return)){ SceneManager.LoadScene(SceneManager.GetActiveScene().name); } }
- 投稿日:2020-01-21T21:25:05+09:00
爆速でunitychanを動かしたい時
- unityHubではなく、unity2018などを起動する
- プロジェクト新規作成の段階で、アセットのstandardAssetsとunitychanを指定してプロジェクト作成する
- 地面を作る
- unitychanをプレファブからぶっこむ
- アニメーターコントローラーをThirdPersonAnimatorControllerにする
- 関係ないやつをオフる
- カプセルコライダーをいい感じにする
- ThirdPersonCharacterをアタッチして、細かい挙動はあとからいい感じにする
カメラ設定はいろいろやり方があるけれど、とにかく時間短縮命!であれば、MultipurposeCameraRigを入れて、ターゲットをunitychanにすればオケ
- 投稿日:2020-01-21T21:09:35+09:00
unitychanでThirdPersonCharacterを入れて壁に埋まった時
- 投稿日:2020-01-21T21:05:55+09:00
Unityでオブジェクトを中心にカメラを移動させるスクリプト
スワイプでカメラ移動させたい!!頼む!!
最近Unityの楽しさを知ってからというものの、業務でPHPを使いつつ、家ではがっつりゲーム開発というワケワカメな状況を送っているBuzzです。
今回はそんな初心者ゲーム開発者(仮)の私がボードゲーム(仮)を作成する際、盤面状況の把握方法として盤面を中心としたカメラ移動を画面スワイプで実現したやり方を備忘録として投稿します。そしてあわよくば猛者様の意見を頂戴できればと。
どんなものができたのか
まずは完成形をお見せします。
今回はチェスや将棋、オセロなどの盤面を想定しているのでY方向の回転は無しにしています。(Y方向回転についても後述してます)
なぜ宇宙にタイルが浮いているかは置いといて、この処理をコーディングしていきます。
Let's コーディング
とりあえずこんなコードになりました。今回はカメラに関する処理なのでファイル名をCameraControllerとして、カメラオブジェクトにアタッチしています。
CameraController.csusing System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraController : MonoBehaviour { //① START GameObject mainCamera; //カメラ GameObject fieldObject; //フィールド(中心としたいオブジェクト、今回は盤面を中心とするためfield) public float rotateSpeed = 1.0f; //回転スピード //① END void Start() { //② START this.mainCamera = Camera.main.gameObject; //カメラオブジェクトを代入 this.fieldObject = GameObject.Find("Field"); //"Field"に中心としたいオブジェクトをHierarchyの名前から指定 //② END } void Update() { //③ START if(Input.GetMouseButton(0)) { rotateCamera(); } //③ END } //④ START private void rotateCamera() { Vector3 angle = new Vector3( Input.GetAxis("Mouse X") * this.rotateSpeed, 0, 0 ); this.mainCamera.transform.RotateAround(this.fieldObject.transform.position, Vector3.up, angle.x); } //④ END }①カメラ、中心としたいオブジェクト(以降「中心オブジェ」)、回転のスピードをそれぞれ定義し、この時点ではカメラと中心オブジェは空の状態です。
②Start()の中でカメラ(mainCamera)にカメラオブジェクト、中心オブジェ(fieldObject)にFieldオブジェクトを代入しています。
③Update()の中で「もし左クリックを押している間」という条件のもと、rotateCamera()を実行しています。実際これくらいの記述量であればこの中にrotateCameraの中身を書いてもいいかもしれません。
④rotateCamera()を定義しています。Vector3引数にGetAxis関数でX方向に生じた値を取って回転スピード(rotateSpeed)と掛けた値、YとZに関しては今回用はないので0を渡しています。最後にカメラオブジェクトのRotateAround関数でfieldObjectの中心、回転の軸(今回はY)、回転方向(今回はX)とすることで回転を実現しています。
実機で動かす
これで実際にビルドしてスマートフォンで確認してみました。
すこし見辛いですが、画面をタップするたびに別のアングルにワープするようになってしまいました。
これでは盤面状況の確認時にかなりストレスですよね。。
こんな時はGoogle先生の出番です(最初から出番しかありませんが)検索すると直前の回転を保持しておくことで解決できそうです。
自然にスクロール編
いろいろ調べた結果、以下に落ち着きました。
CameraController.csusing System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraController : MonoBehaviour { GameObject mainCamera; GameObject fieldObject; public float rotateSpeed = 1.0f; private Vector3 lastMousePosition; //①追記 private Vector3 newAngle = new Vector3(0, 0, 0); //②追記 void Start() { this.mainCamera = Camera.main.gameObject; this.fieldObject = GameObject.Find("Field"); } void Update() { //追記 START if(Input.GetMouseButtonDown(0)) //③ { newAngle = mainCamera.transform.localEulerAngles; //④ lastMousePosition = Input.mousePosition; //⑤ } //追記 END else if(Input.GetMouseButton(0)) { rotateCamera(); } } private void rotateCamera() { Vector3 angle = new Vector3( Input.GetAxis("Mouse X") * this.rotateSpeed, 0, 0 ); this.mainCamera.transform.RotateAround(this.fieldObject.transform.position, Vector3.up, angle.x); } }①直前の回転を保持しておくためのVector変数lastMousePositionを定義、最初の時点では空です。
②Vector型変数newAngleにX:0,Y:0,Z:0のVector3インスタンスを代入しています。
③左クリックが押下された際、一回だけ実行されます。
④newAngle変数に相対的な回転地を代入しています。
⑤lastMousePosition変数に左クリックされた際のマウス位置を代入しています。
今度こそ!
これで直前までの回転を保持してくれて、想定通りの動きをしてくれそうです!
ビルドしてみましたー
いい感じ・・・圧倒的いい感じ・・・っ!!!
そんなこんなで初心者が無事、カメラ回転を実装できました。
もっと簡単に実装できる方法などあればコメントお願いします。おまけ
最後にY方向の回転も追加して終わろうと思います。
これは今あるコードに以下を追加することでチョチョイのチョイのお茶の子さいさいのサイって感じで実装できました。CameraController.csusing System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraController : MonoBehaviour { GameObject mainCamera; GameObject fieldObject; public float rotateSpeed = 1.0f; private Vector3 lastMousePosition; private Vector3 newAngle = new Vector3(0, 0, 0); void Start() { this.mainCamera = Camera.main.gameObject; this.fieldObject = GameObject.Find("Field"); } void Update() { if(Input.GetMouseButtonDown(0)) { newAngle = mainCamera.transform.localEulerAngles; lastMousePosition = Input.mousePosition; } else if(Input.GetMouseButton(0)) { rotateCamera(); } } private void rotateCamera() { Vector3 angle = new Vector3( Input.GetAxis("Mouse X") * this.rotateSpeed, Input.GetAxis("Mouse Y") * this.rotateSpeed, //追記 0 ); this.mainCamera.transform.RotateAround(this.fieldObject.transform.position, Vector3.up, angle.x); this.mainCamera.transform.RotateAround(this.fieldObject.transform.position, transform.right, angle.y); //追記 } }盤面確認などで使うには裏面まで見る必要はないので、Y方向が一定値以下になったら固定させる処理などを追加する必要がありますね。ですが例えば入手したアイテムなどを眺めるシーンなんかにはそのまま使えそうです。まんもすうれぴー。
参考サイト
非常にお世話になりました。
① https://xr-hub.com/archives/6272
② https://tech.pjin.jp/blog/2018/09/05/unity_material_color-change/
③ https://mogi0506.com/uinty-camera-rotation/少しでもお役に立てればと思います。
- 投稿日:2020-01-21T19:41:45+09:00
回転させたオブジェクトを水平に動かす方法(ローカルとグローバル)
- 投稿日:2020-01-21T13:31:19+09:00
unitychanでいきなりエラーが出た(メモ)
using System.Security.Policy;
ここを削除する
- 投稿日:2020-01-21T13:04:02+09:00
SteamVR導入後に設定ポップアップがしつこく出るときの対処法メモ
(いつも調べなおすのが大変なのでメモ書き)
何度許してもでてくるこいつがうざい!
いろんな記事で「“Accept All”を押して進んでください。」ってあって、
その通りにするんだけど、事あるごとにこいつがでてきて正直うざい。ということで、このポップアップを消す方法のメモ書き。
①Asset⇒SteamVR⇒Editorの順に進み
SteamVR_UnitySettingsWindow.csを開く。②41行目の
const bool recommended_UnitySprashScreen = false;
falseをtrueに書き換える。
(参考スクリーンショット)これでもうしつこく許可を乞われることはなくなるはず。
参考ページ(英語):https://stackoverflow.com/questions/41418481/in-unity-how-to-stop-popup-for-show-unity-splashscreen
- 投稿日:2020-01-21T11:15:53+09:00
【Unity】個人用にメソッド拡張してみた(随時更新予定
初めに
プログラミングしていると「なんでこの機能ないんだろ?」とか「この機能が欲しい」ということが度々行ったりするようにいつもなっているのでそろそろ拡張していきたいと思いました。
ダウンロード先
内容説明
基本的にUnityを触っている時に使うことを想定して作っています。
使う場合はusing SKTool.Unityをお忘れなく。目次(クラス、メソッド名)
・ListExtension
・RemoveNull()
・Allocation(T _add,bool _addFlag=false)機能説明
ListExtension
RemoveNull()
Allocation(T _add,bool _addFlag=false)
List内にnullがある場合そのnullに割り当てる、nullがない場合なにもしない。_addFlagがtrueであれば要素内にnullがない場合Addします。
- 投稿日:2020-01-21T02:10:25+09:00
macOS Catalina + Unity 2019.3でAndroidビルド(IL2CPP)に失敗する場合の対処
概要
macOS Catalina + Unity 2019.3でAndroidビルド(IL2CPP)に失敗したので対処のメモを残しておく。
何が起きたか
IL2CPPでAndroid向けビルドをした時に、以下のエラーが発生。
Failed running /Applications/Unity/Hub/Editor/2019.3.0f5/Unity.app/Contents/il2cpp/build/deploy/il2cppcore/il2cppcore.dll (以下略)
原因(おそらく)
Android NDK を手動でインストールしたことにより、macOS Catalinaの強力すぎるセキュリティに引っかかってコマンドを実行できなかった。
対処方法
UnityHubからAndroid NDK をインストールする。(SDKも一緒にインストールされるが)
PreferenceからNDKのパスを設定することを忘れないこと。環境
Mac OS 10.15.2
Unity 2019.3.0f5