弓をマウスで引っ張って矢を飛ばす。Part2.矢を飛ばす|Unityゲーム制作

今回はUnityで「弓で矢を飛ばす」のを実装してみます。マウスで弓を引き、離した時に矢を撃つ感じです。Part2では矢を飛ばすのを実装していきます。

はじめに

Unityのヴァージョンは2022.3.14f1です。Part1は下記です。

実装開始

Part1の続きから作成していきます。

矢を飛ばす

矢の画像を画面にセットして、「Rigidbody2D」を追加、Arrowという名前でスクリプトを作成して追加します。

作成した矢はプレハブ化しておきます。

Instantiateで矢を生成すると下記のように生成されます。

矢の生成位置を「矢の後ろの位置」と「弦の真ん中」に合わせたいので、矢の画像を「SpriteEditor」で編集してPivotの位置を変更します。

Bowスクリプトを下記のように変更します。変更のない箇所は省略してあります。

using UnityEngine;

public class Bow : MonoBehaviour
{

    [SerializeField] private Arrow ArrowPrefab;

    private Arrow Arrow;

    void Update()
    {
        Vector2 mousePos = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);

        if (Input.GetMouseButtonDown(0))
        {
            startPos = mousePos;
            isPull = true;

            Arrow = Instantiate(ArrowPrefab);
            SetArrowPos(Anchor.transform.position);
        }
        else if (Input.GetMouseButton(0))
        {
            Vector2 distance = Vector2.ClampMagnitude((mousePos - startPos), maxString);
            Vector2 pos = (Vector2)Anchor.transform.position + distance;
            StringRender(pos);

            float angle = Mathf.Atan2(mousePos.y - startPos.y, mousePos.x - startPos.x);
            transform.rotation = Quaternion.AngleAxis(angle * Mathf.Rad2Deg, Vector3.forward);

            SetArrowPos(pos);
        }
        if (Input.GetMouseButtonUp(0))
        {
            isPull = false;
            StringRender(Vector2.zero);
        }
    }
    private void SetArrowPos(Vector2 pos)
    {
        Arrow.transform.position = pos;
        Arrow.transform.rotation = this.transform.rotation;
    }
}

パラメータにプレハブをセットします。実行して下記のように矢の位置が意図した場所に生成されたらOKです。

次にArrowスクリプトの中身を下記に変更します。

using UnityEngine;

public class Arrow : MonoBehaviour
{
    private Rigidbody2D rb;

    private void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    public void ArrowShot(Vector2 force)
    {
        rb.AddForce(force, ForceMode2D.Impulse);
    }
}

Bowスクリプトの最終形は下記になります。

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;
    [SerializeField] private Arrow ArrowPrefab;

    private Vector2 startPos;
    private bool isPull;
    private float maxString = 1.2f;
    private float power = 8.0f;
    private Arrow Arrow;

    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;

            Arrow = Instantiate(ArrowPrefab);
            SetArrowPos(Anchor.transform.position);

        }
        else if (Input.GetMouseButton(0))
        {
            Vector2 distance = Vector2.ClampMagnitude((mousePos - startPos), maxString);
            Vector2 pos = (Vector2)Anchor.transform.position + distance;
            StringRender(pos);

            float angle = Mathf.Atan2(mousePos.y - startPos.y, mousePos.x - startPos.x);
            transform.rotation = Quaternion.AngleAxis(angle * Mathf.Rad2Deg, Vector3.forward);

            SetArrowPos(pos);

        }
        if (Input.GetMouseButtonUp(0))
        {
            Vector2 force = Vector2.ClampMagnitude((startPos - mousePos), maxString);
            Arrow.ArrowShot(force * power);

            isPull = false;
            StringRender(Vector2.zero);
        }
    }
    private void SetArrowPos(Vector2 pos)
    {
        Arrow.transform.position = pos;
        Arrow.transform.rotation = this.transform.rotation;
    }
}

引いた長さによって矢の速さが変わります。実行して下記のように矢を飛ばすことが出来ればOKです。

タイトルとURLをコピーしました