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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Q&A

解決済

3回答

1977閲覧

float型で0.01fずつ足す処理がうまくいかない、その回避方法(スクリプトの記載方法)がわからない

kudo201810

総合スコア30

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

0グッド

0クリップ

投稿2020/10/12 09:18

バージョン:Unity 2019.2.11f1 (64-bit)

float型で0.01fずつ足していく以下のようなスクリプトを作りました。(addの部分)

using System.Collections; using System.Collections.Generic; using UnityEngine; public class addforce_ctrl_src : MonoBehaviour { public float add = 0.01f; public float power = 10f; public Vector3 direction = new Vector3(1f, 1f, 1f); Rigidbody rb; bool stop_f = false; Vector3 start_pos; //初期位置 void Start() { start_pos = transform.position; rb = GetComponent<Rigidbody>(); rb.isKinematic = true; } private void Update() { if (Input.GetKeyDown("q")) { if (stop_f == false) { rb.isKinematic = false; rb.AddForce(direction * power, ForceMode.Impulse); stop_f = true; StartCoroutine("SampleCoroutine"); } else { Time.timeScale = 1f; stop_f = false; } } if (stop_f) { //一時停止中に上を押すと if (Input.GetKeyDown(KeyCode.UpArrow)) { rb.isKinematic = true; transform.position = start_pos;//初期位置に戻す direction.x += add; //X方向の力を+0.01する rb.isKinematic = false; rb.AddForce(direction * power, ForceMode.Impulse);//力を加える Time.timeScale = 1f; //再開させる StartCoroutine("SampleCoroutine"); } //一時停止中に下を押すと if (Input.GetKeyDown(KeyCode.DownArrow)) { rb.isKinematic = true; transform.position = start_pos;//初期位置に戻す direction.x -= add; //X方向の力を-0.01する rb.isKinematic = false; rb.AddForce(direction * power, ForceMode.Impulse);//力を加える Time.timeScale = 1f; //再開させる StartCoroutine("SampleCoroutine"); } } } IEnumerator SampleCoroutine() { yield return null; //1フレーム待機 これをしないと軌道の計算ができない Time.timeScale = 0f; //中断 yield break; //コルーチンを終了 } }

【問題1】
キーボードの上キーや下キーを繰り返し押していくと、
float型のため、誤差がでてしまい値が、おかしくなってしまいます。
(途中で 例 0.0199999 などと、ズレがでてきてしまう)

これを回避する書き方が、ネットで調べてみてもわからなかったため、
どういう記述をすれば、0.01ずつ値を変えることができますでしょうか。

【問題2】
transform.position = start_pos;//初期位置に戻す
上記の初期位置に戻す処理も、float型のため、繰り返していくと
最初の位置からずれてしまいます。これも、回避方法がありますでしょうか。

よろしくお願いたします。

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

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

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

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

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

guest

回答3

0

【問題2】
一部を抜粋します

//一時停止中に上を押すと if (Input.GetKeyDown(KeyCode.UpArrow)) { rb.isKinematic = true; transform.position = start_pos;//初期位置に戻す direction.x += add; //X方向の力を+0.01する rb.isKinematic = false; rb.AddForce(direction * power, ForceMode.Impulse);//力を加える Time.timeScale = 1f; //再開させる StartCoroutine("SampleCoroutine"); }

transform.position = start_pos;

で初期位置に戻した後に、

rb.isKinematic = false;
rb.AddForce(direction * power, ForceMode.Impulse);
Time.timeScale = 1f;

ここで一瞬移動する処理を行ってしまっているのでズレます
"下を押すと"の方も同じです

一時停止中に移動する必要があるなら仕方ないですが、ないなら下記の場所で移動させればいいと思います

if (Input.GetKeyDown("q")) { if (stop_f == false) { ~~略~~ } else { // ここで移動の処理を実行 } }

投稿2020/10/12 12:25

編集2020/10/12 12:27
lazh

総合スコア300

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

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

kudo201810

2020/10/12 19:57

問題2に関しては、上記指摘していただいたとおり、 自分で、あえて動かしていただけで問題なかったということで納得しました。 1フレーム分動かした結果、(しかも加える力も変えているので、その都度ずれる) 一時停止しているためずれるということでこれは問題ありません。 問題1が解決しておりません、問題1も回答いただけると助かります。
kudo201810

2020/10/12 20:35

問題1に関して、自己解決いたしました。ありがとうございました。
guest

0

floatなどの浮動小数点数は内部的に2進数で小数点以下も表現しているため、あなたの記述している0.001という10進数は表現できません(近似値でしか表現できない)

テとしては、数値を1000倍にして整数で保持しておいて、+1しながら処理時に1/1000 するということをすれば、処理回数としては辻褄は合います。
が、上記で言ってるように近似値でしかないので、それぞれの結果がどうなるかやってみないとわからないですね

【問題2】

transform.position = start_pos;//初期位置に戻す

これはありえません。
おそらく、何らかの10進数との演算を繰り返してるせいでずれていくのではないでしょうか

投稿2020/10/12 09:25

編集2020/10/12 09:27
y_waiwai

総合スコア87774

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

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

kudo201810

2020/10/12 20:04 編集

以下のように修正したのですが public float add = 0.01f; //0.01 int add_i; ーー省略ーー add_i++; direction.x += add_i / 100; //X方向の力を+0.01する 変化しませんでした。 具体的にどのように記載すればよいでしょうか。 1.01 1.02 1.03 : というふうに増加させたいのですが、やはり不可能でしょうか。 問題2については別の方から指摘があり回答がありました。
kudo201810

2020/10/12 20:04 編集

すみません、一行もれていました start()内に add_i = (int)(100 * add); //加算する場合 をいれています。
kudo201810

2020/10/12 20:35

自己解決いたしました。ありがとうございました。
guest

0

自己解決

以下で自己解決いたしました。ご回答ありがとうございました。

using System.Collections; using System.Collections.Generic; using UnityEngine; public class addforce_ctrl_src : MonoBehaviour { public float add = 0.01f; //0.01 public float power = 1f; public Vector3 direction = new Vector3(1f, 1f, 1f); Rigidbody rb; bool stop_f = false; Vector3 start_pos; //初期位置 void Start() { start_pos = transform.position; rb = GetComponent<Rigidbody>(); rb.isKinematic = true; } private void Update() { if (Input.GetKeyDown("q")) { if (stop_f == false) { rb.isKinematic = false; rb.AddForce(direction * power, ForceMode.Impulse); stop_f = true; StartCoroutine("SampleCoroutine"); } else { Time.timeScale = 1f; stop_f = false; } } if (stop_f) { //一時停止中に上を押すと if (Input.GetKeyDown(KeyCode.UpArrow)) { rb.isKinematic = true; transform.position = start_pos;//初期位置に戻す direction.x += float.Parse(add.ToString("f2")); //X方向の力を+0.01する(小数点第2以下をカットしたい例) direction.x = float.Parse(direction.x.ToString("f2")); rb.isKinematic = false; rb.AddForce(direction * power, ForceMode.Impulse);//力を加える Time.timeScale = 1f; //再開させる StartCoroutine("SampleCoroutine"); } //一時停止中に下を押すと if (Input.GetKeyDown(KeyCode.DownArrow)) { rb.isKinematic = true; transform.position = start_pos;//初期位置に戻す direction.x -= float.Parse(add.ToString("f2")); //X方向の力を-0.01する(小数点第2以下をカットしたい例) direction.x = float.Parse(direction.x.ToString("f2")); rb.isKinematic = false; rb.AddForce(direction * power, ForceMode.Impulse);//力を加える Time.timeScale = 1f; //再開させる StartCoroutine("SampleCoroutine"); } } } IEnumerator SampleCoroutine() { yield return null; //1フレーム待機 これをしないと軌道の計算ができない Time.timeScale = 0f; //中断 yield break; //コルーチンを終了 } }

以下のサイトが参考になりました。

[Unity5 C#] float型でハマった罠 その3 "途中で予期せぬ値に変わる時がある"
https://ameblo.jp/punini-p/entry-12244812908.html

投稿2020/10/12 20:34

kudo201810

総合スコア30

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問