| Unity の物理演算やら、ハイクォリティなグラフィックを一切役立てない簡素なアプリ
上の図は、小学4年生ぐらいで習う面積を求める問題。
緑の部分を求めなくてはならないのだ。
考え方は基本、自由なのだが、もっとも分かりやすく少ない計算量で、回答したいところだ。
しかし、計算量を減らそうとすると、アイデアが、必要になる。
また、計算量は増えるが、見たままの感じで、4つの緑の部分をそれぞれ計算する方が、考え方は単純である。
どちらにせよ、うちの子供はつまずいていた。
全体の面積から、白い部分を引き算すればいいのだが、その考え方が理解できなかったらしい。
となれば、いろんなパターンを見せて、理解してもらおうとある程度、変動可能な図解を作ってみた。
間に合わせなので、デザインの方はご容赦願いたいのだが、色々、作っていくうちに Unity の勉強にもなったので、以下、コードを載せさせていただく。
何しろ、初めて完成物を作ったので大目に見ていただきたい。
| 解説
まずは、はじめに、適当な四角を用意する。
そして、UI のスライダーを使って、四角形の縦と横の長さを変更できるようにした。
以下のスクリプトが、この四角形オブジェクトにアタッチしたもの。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class SquareScale : MonoBehaviour { public GameObject sliderV; public GameObject sliderH; public float verticalValue; public float horizontalValue; // Use this for initialization void Start() { sliderV = GameObject.Find("Slider"); sliderH = GameObject.Find("SliderHorizontal"); } // Update is called once per frame void Update() { SliderScript sliderValueV = sliderV.GetComponent<SliderScript>(); SliderScriptH sliderValueH = sliderH.GetComponent<SliderScriptH>(); verticalValue = sliderValueV.value1; horizontalValue = sliderValueH.value2; //transform.localScale = new Vector2(horizontalValue, verticalValue); iTween.ScaleTo(gameObject, iTween.Hash("x", horizontalValue, "y", verticalValue)); } }
本当は、Update 関数の中には、あまり、多くの処理を書きたくなかったのだけど、とりあえず、挙動は安定していたので、これで、良しとした。
(7年落ちのノートPCはうなりを上げていたが・・・。)
iTween を使って、滑らかな動きも入れてみた。(iTween イイ。)
何より、時間が掛ったのが、白いクロスしたものの挙動。
緑の四角形と連動して、長さを変えなくてはならないし、移動範囲もあわせて変動させなくてはならない。
もっと、簡単でPCへの負荷も少なくする方法もあるのだろうが、初心者の自分には、まだ、これが、精一杯。
以下、白い部分のスクリプト。
縦棒の方。(動きが、平行移動になるので、こちらを MoveBoarderH ( Horizonntal ) としている。)
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MoveBoaderH : MonoBehaviour { public GameObject sliderV; public GameObject sliderH; public GameObject sliderS; public float VerticalValue; public float HorizontalValue; public float scaleValue; void Start() { sliderV = GameObject.Find("Slider"); sliderH = GameObject.Find("SliderHorizontal"); sliderS = GameObject.Find("scaleSlider"); } void Update() { SliderScript sliderValueV = sliderV.GetComponent<SliderScript>(); VerticalValue = sliderValueV.value1; SliderScriptS slidervalueS = sliderS.GetComponent<SliderScriptS>(); scaleValue = slidervalueS.valueScale; iTween.ScaleTo(gameObject, iTween.Hash("x", scaleValue, "y", VerticalValue)); } void OnMouseDrag() { Vector3 objectPointInScreen = Camera.main.WorldToScreenPoint(this.transform.position); // objectの空間座標をスクリーン座標に変換している。 Vector3 mousePointInScreen = new Vector3(Input.mousePosition.x, objectPointInScreen.y, // マウスのスクリーン座標を変数に格納している。 objectPointInScreen.z); Vector3 mousePointInWorld = Camera.main.ScreenToWorldPoint(mousePointInScreen); // マウスのスクリーン座標を空間座標に変換している。 mousePointInWorld.z = this.transform.position.z; // objectの空間座標のz軸をマウスの空間座標のz軸に代入している。つまり、z軸は、移動させていない。 int m = Mathf.FloorToInt(mousePointInWorld.x); SliderScriptH sliderValueH = sliderH.GetComponent<SliderScriptH>(); HorizontalValue = sliderValueH.value2; SliderScriptS slidervalueS = sliderS.GetComponent<SliderScriptS>(); scaleValue = slidervalueS.valueScale; if (scaleValue == 1.0f) { float m1 = Mathf.Clamp(m, -1.0f * HorizontalValue / 2.0f + 0.5f, HorizontalValue / 2.0f - 0.5f); this.transform.position = new Vector3(m1, mousePointInWorld.y, mousePointInWorld.z); } else if (scaleValue == 2.0f) { float m1 = Mathf.Clamp(m, -1.0f * HorizontalValue / 2.0f + 1.0f, HorizontalValue / 2.0f - 1.0f); this.transform.position = new Vector3(m1, mousePointInWorld.y, mousePointInWorld.z); } else if (scaleValue == 3.0f) { float m1 = Mathf.Clamp(m, -1.0f * HorizontalValue / 2.0f + 1.5f, HorizontalValue / 2.0f - 1.5f); this.transform.position = new Vector3(m1, mousePointInWorld.y, mousePointInWorld.z); } } }
同じく、横棒の方。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MoveBoaderV : MonoBehaviour { public GameObject sliderH; public GameObject sliderV; public GameObject sliderS; public float horizontalValue; public float VerticalValue; public float scaleValue; void Start() { sliderH = GameObject.Find("SliderHorizontal"); sliderV = GameObject.Find("Slider"); sliderS = GameObject.Find("scaleSlider"); } void Update() { SliderScriptH sliderValueH = sliderH.GetComponent<SliderScriptH>(); horizontalValue = sliderValueH.value2; SliderScriptS slidervalueS = sliderS.GetComponent<SliderScriptS>(); scaleValue = slidervalueS.valueScale; iTween.ScaleTo(gameObject, iTween.Hash("x", horizontalValue, "y", scaleValue)); } void OnMouseDrag() { Vector3 objectPointInScreen = Camera.main.WorldToScreenPoint(this.transform.position); Vector3 mousePointInScreen = new Vector3(objectPointInScreen.x, Input.mousePosition.y, objectPointInScreen.z); Vector3 mousePointInWorld = Camera.main.ScreenToWorldPoint(mousePointInScreen); mousePointInWorld.z = this.transform.position.z; int m = Mathf.FloorToInt(mousePointInWorld.y); SliderScript sliderValueV = sliderV.GetComponent<SliderScript>(); VerticalValue = sliderValueV.value1; SliderScriptS slidervalueS = sliderS.GetComponent<SliderScriptS>(); scaleValue = slidervalueS.valueScale; if (scaleValue == 1.0f) { float m1 = Mathf.Clamp(m, -1.0f * VerticalValue / 2.0f + 2.0f, VerticalValue / 2.0f + 1.0f); this.transform.position = new Vector3(mousePointInWorld.x, m1 + 0.5f, mousePointInWorld.z); } else if (scaleValue == 2.0f) { float m1 = Mathf.Clamp(m, -1.0f * VerticalValue / 2.0f + 2.0f + 0.5f, VerticalValue / 2.0f + 1.0f - 0.5f); this.transform.position = new Vector3(mousePointInWorld.x, m1 + 0.5f, mousePointInWorld.z); } else if (scaleValue == 3.0f) { float m1 = Mathf.Clamp(m, -1.0f * VerticalValue / 2.0f + 2.0f + 1.0f, VerticalValue / 2.0f + 1.0f - 1.0f); this.transform.position = new Vector3(mousePointInWorld.x, m1 + 0.5f, mousePointInWorld.z); } } }
白い部分の棒を、ドラッグで移動できるようにした処理は、定型文みたいのを、拾ってきて、それぞれの動きに、制限をかけている。
そして、今回、新たな発見というか、とても便利だったのが、Mathf.Clamp(m, -1.0f * VerticalValue / 2.0f + 2.0f + 0.5f, VerticalValue / 2.0f + 1.0f – 0.5f); で、利用している、Math.Clamp 関数なるモノだった。
変数そのものに、変化の範囲を指定できるので、かなり、コードを簡略化出来た。
後は、適当に、式や値を、テキストで表示すれば、完成。
良かったら、お子様の算数の勉強にお役立てください。
コメント