teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

値の連動機構について案を追記

2019/01/26 09:56

投稿

Bongo
Bongo

スコア10816

answer CHANGED
@@ -25,4 +25,76 @@
25
25
  }
26
26
  ```
27
27
 
28
- ![スライダー](e383d8c878302959b2cba40ed0fcd64b.gif)
28
+ ![スライダー](e383d8c878302959b2cba40ed0fcd64b.gif)
29
+
30
+ #追記
31
+ [UniRx](https://assetstore.unity.com/packages/tools/integration/unirx-reactive-extensions-for-unity-17276)を使っても構わなければ、連動機構のごちゃごちゃ感を軽減できるかもしれませんね。
32
+
33
+ ```C#
34
+ using UniRx;
35
+ using UnityEngine;
36
+ using UnityEngine.UI;
37
+
38
+ public class SliderTextController : MonoBehaviour
39
+ {
40
+ // 外部スクリプトから値を操作する場合、こちらのプロパティ経由で行う
41
+ public ReactiveProperty<float> Value1 => this.value1;
42
+ public ReactiveProperty<float> Value2 => this.value2;
43
+
44
+ [SerializeField] private FloatReactiveProperty value1 = new FloatReactiveProperty();
45
+ [SerializeField] private FloatReactiveProperty value2 = new FloatReactiveProperty();
46
+ [SerializeField] private Vector2 range1 = new Vector2(0.1f, 1.0f);
47
+ [SerializeField] private Vector2 range2 = new Vector2(300.0f, 22000.0f);
48
+ [SerializeField] private Slider value1Slider;
49
+ [SerializeField] private Slider value2Slider;
50
+ [SerializeField] private Text value1Text;
51
+ [SerializeField] private Text value2Text;
52
+
53
+ private void Awake()
54
+ {
55
+ // スライダー1の範囲を設定
56
+ this.value1Slider.minValue = this.range1.x;
57
+ this.value1Slider.maxValue = this.range1.y;
58
+ this.value1Slider.value = this.range1.x;
59
+
60
+ // スライダー1の値が操作されたらvalue1をその値に書き換える
61
+ this.value1Slider.OnValueChangedAsObservable().Subscribe(value => this.value1.Value = value);
62
+
63
+ // value1に変更があったらテキスト1を書き換えて...
64
+ this.value1.SubscribeToText(this.value1Text, value => value.ToString("F6"));
65
+ // スライダー1を更新する必要があれば更新し...
66
+ this.value1.Where(value => value != this.value1Slider.value)
67
+ .Subscribe(value => this.value1Slider.value = value);
68
+ // value2を更新する必要があれば更新する
69
+ this.value1.Select(value => MapValue(value, this.range1.x, this.range1.y, this.range2.x, this.range2.y))
70
+ .Where(value => value != this.value2.Value).Subscribe(value => this.value2.Value = value);
71
+
72
+ // スライダー2の範囲を設定
73
+ this.value2Slider.minValue = this.range2.x;
74
+ this.value2Slider.maxValue = this.range2.y;
75
+ this.value2Slider.value = this.range2.x;
76
+
77
+ // スライダー2の値が操作されたらvalue2をその値に書き換える
78
+ this.value2Slider.OnValueChangedAsObservable().Subscribe(value => this.value2.Value = value);
79
+
80
+ // value2に変更があったらテキスト2を書き換えて...
81
+ this.value2.SubscribeToText(this.value2Text, value => value.ToString("F0"));
82
+ // スライダー2を更新する必要があれば更新し...
83
+ this.value2.Where(value => value != this.value2Slider.value)
84
+ .Subscribe(value => this.value2Slider.value = value);
85
+ // value1を更新する必要があれば更新する
86
+ this.value2.Select(value => MapValue(value, this.range2.x, this.range2.y, this.range1.x, this.range1.y))
87
+ .Where(value => value != this.value1.Value).Subscribe(value => this.value1.Value = value);
88
+ }
89
+
90
+ private static float MapValue(float value, float fromMin, float fromMax, float toMin, float toMax)
91
+ {
92
+ return Mathf.Lerp(toMin, toMax, Mathf.InverseLerp(fromMin, fromMax, value));
93
+ }
94
+ }
95
+ ```
96
+
97
+ ![スライダー](6fe9c9546a20fabf7450b1dc104f022f.gif)
98
+
99
+ len_soukoさんがおっしゃるように、私も何かとpublicなフィールドを使いたがる悪癖があって耳が痛いところですが、外部に何を見せて何を隠すか十分検討しておくとプログラムの規模が大きくなっても混乱しにくいかと思います。
100
+ プロパティは優れた機能だと思いますが、確かにWeb上で見かけるコードでは本家.NETほど広まってはいない印象です。インスペクタとの連携を考えると、Unity側のサポートがまだ弱いような気がしますね...今後のバージョンアップで改善されるでしょうか?