Skip to content

[Unity] 簡易虛擬搖桿的設置、與移動物件

差不多是在去年,我嘗試使用 Unity 製作一款 2D 俯瞰視角的射擊遊戲,當時嘗試使用 Unity 商店內可下載的虛擬搖桿,然而效果不盡人意。最近研究起手機遊戲的製作,又再次找了不少虛擬搖桿相關的教學,發覺製作虛擬搖桿出乎意料的容易。

本篇文章便將我覺得相當容易的這個作法紀錄下來。主要的作法是參考自 Beginner’s Guide: Learn to Make Simple Virtual Joystick in Unity 這篇文章。

本篇的虛擬搖桿為求方便示範,並未使用任何圖像素材,直接使用 Unity 內建的元件,故可能會有些簡陋。


製作方法步驟

Step 1 新建 Canvas 以及 Image 物件

點擊右鍵添加,可以在 UI 選項中找到 Canvas 以及 Image 物件。


最後應該要有以下的結構:


再將 JoyStckContainer 的錨點設置在左下角,這步驟相當重要,否則會讓之後的搖桿操作失靈。如果你想知道,這個物件的 Pivot 是 x=0.5、y=0.5。



Step 2 (Optional)將物件添加顏色、放置到你希望的擺放位置

這步驟如果不想做的話可以跳過,我只是想讓大家清楚哪邊是搖桿、哪邊是玩家的物件。我擺放的方式如下:



Step 3 製作腳本

Joystick.cs (掛載在 Image-JoystickContainer 上)

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;


public class Joystick : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler
{
    // Init
    private Image jsContainer;
    private Image joystick;
    public Vector3 InputDirection = Vector3.zero;

    void Start()
    {
        // Get the Component we attach this script (JoystickContainer)
        jsContainer = GetComponent<Image>();

        // Get the only one child component (Joystick)
        joystick = transform.GetChild(0).GetComponent<Image>();
    }

    public void OnDrag(PointerEventData ped)
    {
        Vector2 position = Vector2.zero;

        // Get InputDirection
        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            jsContainer.rectTransform,
            ped.position,
            ped.pressEventCamera,
            out position
        );

        float x = (position.x / jsContainer.rectTransform.sizeDelta.x);
        float y = (position.y / jsContainer.rectTransform.sizeDelta.y);

        InputDirection = new Vector3(x, y, 0);
        InputDirection = (InputDirection.magnitude > 1) ? InputDirection.normalized : InputDirection;

        // Define the area in which joystick can move around
        joystick.rectTransform.anchoredPosition = new Vector3(
            InputDirection.x * jsContainer.rectTransform.sizeDelta.x / 3,
            InputDirection.y * jsContainer.rectTransform.sizeDelta.y / 3
        );
    }

    public void OnPointerDown(PointerEventData ped)
    {
        OnDrag(ped);
    }

    public void OnPointerUp(PointerEventData ped)
    {
        // If mouse release, the InputDirection variable have to return to Vector3(0.0, 0.0, 0.0);
        InputDirection = Vector3.zero;
        joystick.rectTransform.anchoredPosition = Vector3.zero;
    }
}



Player.cs (掛載在 Image-Player 上)

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;

public class Player : MonoBehaviour
{
    // Init
    public float moveSpeed = 1f;
    public Joystick jsMovement;
    public Vector3 direction;

    private float xMin, xMax, yMin, yMax;
    

    void Update()
    {
        // InputDirection can be used as per the need of your project
        direction = jsMovement.InputDirection;

        // If we drag the Joystick
        if (direction.magnitude != 0)
        {
            transform.position += direction * moveSpeed;
            transform.position = new Vector3(
                Mathf.Clamp(transform.position.x, xMin, xMax),
                Mathf.Clamp(transform.position.y, yMin, yMax),
                0f
            );
        }
    }

    void Start()
    {
        // Initialization of boundaries
        xMax = Screen.width - 50;
        xMin = 50;
        yMax = Screen.height - 50;
        yMin = 50;
    }
}






Step 4 將 Image-Player 物件的 jsMovement 欄位掛上 Image-JoystickContainer 物件



Step 5 嘗試執行遊戲

https://clay-atlas.com/wp-content/uploads/2021/06/any_test-SampleScene-PC-Mac-Linux-Standalone-Unity-2019.4.27f1-Personal_-_DX11_-2021-06-06-12-48-03.mp4

References


Read More

Tags:

Leave a Reply取消回覆

Click to Copy
Exit mobile version