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

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

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

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

Unity

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

Q&A

解決済

2回答

2871閲覧

Unityでの線形補間について

sim123

総合スコア7

Unity3D

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

Unity

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

0グッド

0クリップ

投稿2017/05/19 08:32

編集2017/05/19 08:33

###前提・実現したいこと
Unity5.6でオブジェクトを持ち、
線形補間で一定間隔スライドさせようとしています。

プレイヤーがオブジェクトを持ち
スライドさせるところまではできましたが
位置が元の位置まで戻ってしまいます。

###発生している問題・エラーメッセージ
・スライド実行時に位置が元の位置まで戻ってしまう
・不自然なスライド
大きさを元にインターバルを取り、その分移動させていますが
移動量が一定なだけでオブジェクトの端を通りすぎてしまう。

###該当のソースコード

C#

1public class SlideObject : BaseObject 2{ 3 // 分割数 4 [SerializeField] 5 private int split_ = 1; 6 7 // インターバル 8 private float middlePoint_; 9 // 最初の位置からの差分 10 private float sub_; 11 // 大きさ 12 private float endPoint_; 13 // 移動時間 14 private float time_; 15 // 移動速度 16 [SerializeField] 17 private float speed_ = 0.5f; 18 19 // 補間用変数 20 Vector3 start_; 21 Vector3 movement_; 22 Vector3 result_; 23 24 // Use this for initialization 25 public void Awake() 26 { 27 base.Awake(); 28 // 大きさ 29 endPoint_ = transform.localScale.x; 30 // 分割数を求める 31 middlePoint_ = endPoint_ / split_; 32 // 補間用変数初期化 33 start_ = transform.position; 34 movement_ = transform.position; 35 time_ = 0; 36 } 37 38 // Update is called once per frame 39 public void Update() 40 { 41 base.Update(); 42 if (time_ < 1.0f) 43 time_ += Time.deltaTime * speed_; 44 else 45 { 46 time_ = 1.0f; 47 start_ = transform.position; 48 } 49 50 // プレイヤーの手持ちフラグがオンの時は線形補間 51 // オフの時はなにもしない。 52 var parent = transform.root.transform.GetComponent<Player>(); 53 if (!parent) return; 54 if (parent.GetHaveFlag()) 55 { 56 57 } 58 else 59 { 60 // 移動 61 if (Mathf.Abs(sub_) < endPoint_) 62 { 63 result_ = Vector3.Lerp(start_, movement_, time_); 64 transform.position = new Vector3(result_.x, transform.position.y, result_.z); 65 } 66 } 67 } 68 69 public override void Gimmick() 70 { 71 if (time_ < 1) return; 72 73 if (Input.GetKeyDown(KeyCode.D)) 74 { 75 Slide(middlePoint_); 76 } 77 if (Input.GetKeyDown(KeyCode.A)) 78 { 79 Slide(-middlePoint_); 80 } 81 } 82 /// <summary> 83 /// スライドさせる 84 /// </summary> 85 /// <param name="Slide"></param> 86 private void Slide(float middlepoint) 87 { 88 movement_ = new Vector3(transform.position.x + middlepoint, transform.position.y, transform.position.z); 89 sub_ += middlepoint; 90 time_ = 0; 91 } 92 93 94}

###補足情報(言語/FW/ツール等のバージョンなど)
C# Unity5.6
ヒントだけでも試しますのでよろしくお願いします
もしコード内の処理でわからないことがあれば返信します

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

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

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

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

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

guest

回答2

0

ベストアンサー

いまいち質問の意図がつかめておりませんが、とりあえず下記のようなコードにすることで位置がもとに戻ってしまう、という現象をなくすことが出来ます。ヒントになれば幸いです。

(私の環境でテストするためにメソッド名や継承クラスに手を加えております。ご注意下さい)

C#

1public class SlideObject : MonoBehaviour 2{ 3 [SerializeField] float speed_ = 0.5f; 4 5 Vector3 moveStart_; 6 Vector3 moveEnd_; 7 float time_; 8 9 Player player; 10 public void Awake() 11 { 12 player = FindObjectOfType<Player>(); 13 } 14 15 public void Update() 16 { 17 if (!player) return; 18 if (!player.GetHaveFlag()) return; 19 20 time_ += Time.deltaTime * speed_; 21 22 var tmp = Vector3.Lerp(moveStart_, moveEnd_, time_); 23 transform.position = new Vector3(tmp.x, transform.position.y, transform.position.z); 24 25 UpdateInput(); 26 } 27 28 public void UpdateInput() 29 { 30 if (time_ < 1) return; 31 32 if (Input.GetKeyDown(KeyCode.D)) 33 { 34 StartSlide(2); // 2右に移動する 35 } 36 if (Input.GetKeyDown(KeyCode.A)) 37 { 38 StartSlide(-2); // 2左に移動する 39 } 40 } 41 42 private void StartSlide(float moveLength) 43 { 44 time_ = 0; 45 moveStart_ = transform.position; // 移動開始時の座標を記憶しておく 46 moveEnd_ = moveStart_ + new Vector3(moveLength, 0, 0); // 移動終了の座標を計算する 47 } 48}

上記のコードがヒントにならない、解決しない場合は下記質問に返答していただけるとサポートしやすいです。

大きさを元にインターバルを取り、その分移動させていますが
移動量が一定なだけでオブジェクトの端を通りすぎてしまう。

全体として移動可能な範囲(例えば 2 ≦ x ≦ 10)があり、
さらにその中で移動可能なポイント(例えばx=2, 4, 6, 8, 10)がある、
ということでしょうか。

投稿2017/05/19 13:15

kokeiro001

総合スコア62

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

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

sim123

2017/05/21 11:15

回答ありがとうございます。 すみません、文章で伝えるのが得意ではなくて。。。 解決はまだしていません。。 zの値は戻らず解決しましたが、xの値だけは戻ってしまいます。 紹介してくださったコードとの違いは UpdateInput()を使う場所だけで、あとはほぼ同じように組みました ```C# public class Player : MonoBehaviour { void Update() { if (Input.GetMouseButtonDown(1)) { gimmickFlag_ = !gimmickFlag_; } if (gimmickFlag_) { UpdateGimmick(); // この中でUpdateInput()を呼んでいます } } private void UpdateGimmick() { if (!child_) { gimmickFlag_ = false; return; } else { haveFlag_ = false; // 動くオブジェクトの子供がいればUpdateGimmick() child_.GetComponent<BaseObject>().UpdateInput(); } } } ``` 大きさを元に... というのは 大きさ3の分割数3の設定とします そうすると移動量は 大きさ/分割数 = 1 1ずつずれていくようにします 右にずらす   □■□    □■□     □■□ 左にずらす   □■□  □■□ □■□ 移動可能な範囲は、上記の図のような感じです
kokeiro001

2017/05/21 11:42

移動範囲に関する図示、Playerクラスの中身の提示ありがとうございます、とてもわかり易いです。 > zの値は戻らず解決しましたが、xの値だけは戻ってしまいます。 原因の特定が難しいため「戻ってしまう」についての詳細を教えていただけますか。 - 戻るタイミングについて - 移動直後に戻ってしまいますか? - 2回目の移動タイミングで、1回目の移動開始の場所に戻ってしまう感じでしょうか? - 戻る場所について - もしも3回移動しようとした場合、戻ってしまう場所は何処になりますか? - 必ず1回前の移動開始の場所に戻る? - 毎回シーン開始時の初期地点にまで戻る? お手数おかけしますが、上記のヒント貰えると解決しやすそうです。
sim123

2017/05/21 13:12

答えやすいかたちで質問していただきありがとうございます ・戻るタイミングついて ①プレイヤーがオブジェクトを持つ ②右クリックでギミックフラグON ③DキーorAキーでスライド ④ギミックフラグをOFF ⑤再度プレイヤーがオブジェクトを移動させる ⑥ギミックフラグON ⑦スライドさせる この⑥の段階で、一回目に移動させた座標に戻ってしまいます。 ・戻る場所について そうですね、必ず一回前の移動地点に戻ります
guest

0

kokeiro001さん 回答ありがとうございました。
ギミックフラグがオフの時に
start と end をリセットすることで、戻る現象を抑えることができました

C#

1 2public class SlideObject : BaseObject 3{ 4 [SerializeField] 5 float speed_ = 0.5f; 6 7 Vector3 moveStart_; 8 Vector3 moveEnd_; 9 float time_; 10 11 Player player; 12 13 14 15 public void Awake() 16 { 17 base.Awake(); 18 moveStart_ = transform.position; 19 moveEnd_ = transform.position; 20 player = FindObjectOfType<Player>(); 21 } 22 23 public void Update() 24 { 25 base.Update(); 26 27 if (!transform.parent) return; 28 if (!player) return; 29 // 使用している関数名を変更しましたが、ほとんど内容は変わっていません 30 // ギミックがOnではないとき、自分の位置を代入し続ける 31 if (!player.GetGimmickFlag()) 32 { 33 // ギミックがOnではないとき、自分の位置を代入し続ける 34 moveStart_ = transform.position; 35 moveEnd_ = transform.position; 36 return; 37 } 38 39 time_ += Time.deltaTime * speed_; 40 var tmp = Vector3.Lerp(moveStart_, moveEnd_, time_); 41 transform.position = new Vector3(tmp.x, tmp.y, tmp.z); 42 } 43 44 public override void Gimmick() 45 { 46 if (time_ < 1) 47 { 48 return; 49 } 50 if (Input.GetKeyDown(KeyCode.D)) 51 { 52 StartSlide(1); // 2右に移動する 53 } 54 if (Input.GetKeyDown(KeyCode.A)) 55 { 56 StartSlide(-1); // 2左に移動する 57 } 58 } 59 60 private void StartSlide(float moveLength) 61 { 62 time_ = 0; 63 moveStart_ = transform.position; // 移動開始時の座標を記憶しておく 64 Vector3 d = transform.TransformDirection(moveLength, 0, 0); 65 moveEnd_ = moveStart_ + d; // 移動終了の座標を計算する 66 }

投稿2017/05/23 05:18

sim123

総合スコア7

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問