Last Updated on 2021-10-25 by Clay
差不多是在去年,我嘗試使用 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 嘗試執行遊戲
References
- http://www.theappguruz.com/blog/beginners-guide-learn-to-make-simple-virtual-joystick-in-unity
- https://assetstore.unity.com/packages/tools/input-management/joystick-pack-107631
- https://github.com/MarcoFazioRandom/Virtual-Joystick-Unity