今回はUnityで「弓で矢を飛ばす」のを実装してみます。マウスで弓を引き、離した時に矢を撃つ感じです。Part1では弓の弦を引っ張るのを実装していきます。
はじめに
Unityのヴァージョンは2022.3.14f1です。下記、2つの画像を利用していきます。私がInkscapeで簡単に作成したものです。
実装開始
ここから実際に作成していきます。
弓の弦を作成
まずは、弓の弦を作成していきます。弓の画像を画面にセットします。
弓の配下に「空オブジェクト」を追加して名前をstring1とし、LineRendrerを追加します。
LineRendererは下記のようにサイズ、Width、色、マテリアルを変更します。
下記のようにLineRendererで弓の弦を作成することが出来ます。
弦をスクリプトで実装
弓の配下に「空オブジェクト」を2つ追加して、位置を弓の上下に配置します。
string1の座標をリセットしておきます。
下記スクリプトを作成します。
using UnityEngine; public class Bow : MonoBehaviour { [SerializeField] private GameObject Top; [SerializeField] private GameObject Bottom; [SerializeField] private LineRenderer String1; void Start() { Vector2 TopPos = Top.transform.position; Vector2 BottomPos = Bottom.transform.position; String1.SetPosition(0, TopPos); String1.SetPosition(1, BottomPos); } }
弓にスクリプトを追加して、パラメータをセットします。
実行して、弦が作成されたらOKです。
マウスで弓を引く
次にマウスで弓を引けるようにします。
まずは、string1をコピーしてstring2を作成、弦の真ん中の位置に空オブジェクトを追加します。
スクリプトを下記に変更します。
using UnityEngine; public class Bow : MonoBehaviour { [SerializeField] private GameObject Top; [SerializeField] private GameObject Bottom; [SerializeField] private LineRenderer String1; [SerializeField] private LineRenderer String2; [SerializeField] private GameObject Anchor; private Vector2 startPos; private bool isPull; void Start() { isPull = false; StringRender(Vector2.zero); } private void StringRender(Vector2 pos) { Vector2 TopPos = Top.transform.position; Vector2 BottomPos = Bottom.transform.position; if (isPull) { String2.gameObject.SetActive(true); String1.SetPosition(0, TopPos); String1.SetPosition(1, pos); String2.SetPosition(0, pos); String2.SetPosition(1, BottomPos); } else { String2.gameObject.SetActive(false); String1.SetPosition(0, TopPos); String1.SetPosition(1, BottomPos); } } void Update() { Vector2 mousePos = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition); if (Input.GetMouseButtonDown(0)) { startPos = mousePos; isPull = true; } else if (Input.GetMouseButton(0)) { Vector2 distance = mousePos - startPos; StringRender((Vector2)Anchor.transform.position + distance); } if (Input.GetMouseButtonUp(0)) { isPull = false; StringRender(Vector2.zero); } } }
スクリプトの簡単な説明
StringRenderで弦を表示しています。弓を引いてないときはstring1だけでまっすぐな状態、弓を引いてるときはstring1とstring2で「>」の形にしています。
Update内では、マウスを左クリック時に基準となるマウス位置を取得、マウスクリックしたまま動かすと弦の位置を変更、マウスクリックを離した時に初期状態に戻す処理を行っています。
それぞれのパラメータをセットします。
実行して、下記のようにマウスで弓を引けたらOKです。
弦がどこまでも引けてしまうので制限をかけるのを、弓の角度を変えていきます。スクリプトを下記に変更します。startとStringRendererは変更がないので省略してあります。
using UnityEngine; public class Bow : MonoBehaviour { [SerializeField] private GameObject Top; [SerializeField] private GameObject Bottom; [SerializeField] private LineRenderer String1; [SerializeField] private LineRenderer String2; [SerializeField] private GameObject Anchor; private Vector2 startPos; private bool isPull; private float maxString = 1.2f; void Update() { Vector2 mousePos = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition); if (Input.GetMouseButtonDown(0)) { startPos = mousePos; isPull = true; } else if (Input.GetMouseButton(0)) { Vector2 distance = Vector2.ClampMagnitude((mousePos - startPos), maxString); StringRender((Vector2)Anchor.transform.position + distance); float angle = Mathf.Atan2(mousePos.y - startPos.y, mousePos.x - startPos.x); transform.rotation = Quaternion.AngleAxis(angle * Mathf.Rad2Deg, Vector3.forward); } if (Input.GetMouseButtonUp(0)) { isPull = false; StringRender(Vector2.zero); } } }
実行してみて、下記のように引っ張る限界が出来て、弓の角度が変わればOKです。
Part1では弓の弦を引っ張るここまでとします。Part2では実際に矢を飛ばしていきます。