質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

3779閲覧

コルーチンが指定した秒数間隔で呼ばれない

okprogramming

総合スコア12

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2019/02/14 05:39

キャンバスとパネルを動的に生成し、
フェードイン、フェードアウトする機能を作ろうと持ったのですがうまくいきませんでした。

具体的には、フェードイン、アウトで指定した秒数と実際にフェードする秒数が微妙にずれてしまいます。

私の認識では、"コルーチンを利用すれば指定した秒数後に処理が行われる"と思っていたので驚きました。

コルーチンのような非同期処理にも呼び出す時間のずれというものは生じるのでしょうか、どなたかご教授ください。

以下コードになります。(QuolityでDon't Syncに設定変更し、Fpsを90近くキープした状態でも同様の現象が起きました)

using System.Collections; using UnityEngine; using UnityEngine.UI; public class FadeInOut : MonoBehaviour { Canvas faceCanvas; Image facePanel; Coroutine coroutine; [SerializeField] Color panelColor = new Color(0,0,0,0); [SerializeField] float fadeTime = 5; // Start is called before the first frame update void Start() { //キャンバス生成&設定 GameObject canvas_G = new GameObject("FaceCanvas"); faceCanvas = canvas_G.AddComponent<Canvas>(); canvas_G.AddComponent<CanvasScaler>(); canvas_G.AddComponent<GraphicRaycaster>(); //レンダリングをメインカメラに faceCanvas.renderMode = RenderMode.ScreenSpaceCamera; faceCanvas.worldCamera = FindObjectOfType<Camera>(); //パネル生成&設定 GameObject panel_G = new GameObject("FacePanel"); facePanel = panel_G.AddComponent<Image>(); Color tmpColor = facePanel.color; tmpColor.a = 0f; facePanel.color = tmpColor; //パネルをキャンバスの子に設定 panel_G.transform.parent = canvas_G.transform; //パネルのポジションを正面に調整 Vector3 panelPosition = panel_G.transform.localPosition; panelPosition.x = 0; panelPosition.y = 0; panel_G.transform.localPosition = panelPosition; } void Update() { //キー押してない間はreturn if (Input.anyKey == false) { return; } if (coroutine == null) { //テスト用 フェードアウト if (Input.GetKeyDown(KeyCode.O) && panelColor.a == 0) { FadeOut(); } //テスト用 フェードイン if (Input.GetKeyDown(KeyCode.I) && panelColor.a == 1) { FadeIn(); } } } public void FadeOut() { if (panelColor.a == 0) { coroutine = StartCoroutine(FadeOutCoroutine()); } } IEnumerator FadeOutCoroutine() { float alpha = 1; while (panelColor.a < 1) { yield return new WaitForSeconds(0.1f); panelColor.a += alpha / (fadeTime * 10); facePanel.color = panelColor; } panelColor.a = 1; StopCoroutine(coroutine); coroutine = null; } public void FadeIn() { if (panelColor.a == 1) { coroutine = StartCoroutine(FadeInCoroutine()); } } IEnumerator FadeInCoroutine() { float alpha = 1; while (panelColor.a > 0) { yield return new WaitForSeconds(0.1f); panelColor.a -= alpha / (fadeTime * 10); facePanel.color = panelColor; } panelColor.a = 0; StopCoroutine(coroutine); coroutine = null; } }

よりスムーズにフェードさせようと思い、
下記のように変更するとフェード時間を5秒にした場合、1秒近い誤差が生まれます。

while (panelColor.a < 1) { yield return new WaitForSeconds(0.05f); panelColor.a += alpha / (fadeTime * 20); facePanel.color = panelColor; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

FPSが90になっていると、Updateが1秒に90回呼ばれていると思います
で、これと同じ間隔でコルーチンも呼ばれています

WaitForSecondsを使うと、指定した秒数が経過してない場合は呼び出しをスキップし、
指定した秒数が経過したフレームで呼び出されます。
90fpsで0.05sを指定したなら、5フレーム後、0.055s時に呼び出されます

WaitForSecondsは指定した秒数以上を待つ関数と考えてください
できるだけ厳密な値がほしいなら、毎フレーム呼び出してTime.deltaTimeで計測する必要があります

投稿2019/02/14 06:39

izmktr

総合スコア2856

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

okprogramming

2019/02/14 08:00 編集

回答ありがとうございます。つまり90fpsの場合は1fps=1秒/90=0.011…となり、 4フレーム目までの0.044秒間はスキップされるということですね(間違ってたらすみません) 今後、シビアな再現性が求めらる処理はFixUpdateを使っていこうと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問