今回は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では実際に矢を飛ばしていきます。
