只需要把脚本交给画布下的空物体,自行自定义以下内容,运行即可生成虚拟摇杆。
提供了检测区域大小的自定义。
提供了摇杆检测区域的图片自定义。
提供了摇杆底盘以及摇杆的图片自定义。
提供了摇杆灵敏度的自定义。-----值越大 ----灵敏度越小
提供了摇杆移动百分比,以及移动方向信息,可直接用于接入移动模块。
生成的是仿照Moba类的虚拟摇杆,具体分析看对应的设计分析_【测试分析】手机游戏虚拟摇杆设计分析-By Terrell21
代码中某些数字部分没提供自定义,可根据个人需要修改或设置成自定义。
枚举为 虚拟摇杆的组成部分,摇杆盘底,摇杆。
主要功能:
不做出检测区域外的响应。
盘底位置根据在检测区域内的响应进行位置更新。松手后返回初始位置。
盘底不回超出检测区域,不会超出屏幕边缘。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
enum E_JoystickComponent
{
chassis,
joystick
}
public class VirtualJoyStick : MonoBehaviour {
//图片组件
private Image click_limit; //点击区域限制,,跟其RectTransform上的长宽 位置有关
private GameObject chassis; //操纵杆底盘
private GameObject joystick; //操纵杆
public Sprite chassis_sprite;
public Sprite joystick_sprite;
public Sprite limit_sprite;
//记录信息
private Vector2 prePos; //上一个点击位置
private Touch nowTouch; //当前触摸信息
private Vector2 iniPos; //初始位置
public float sensitivity = 2; //灵敏度 ---这里越大 灵敏度越小
private float m_radius; //盘子半径
public float moveInfo; //摇杆移动的百分比
public Vector2 moveDir; //摇杆移动的方向
public float trigger_width;
public float trigger_height;
// Use this for initialization
void Start () {
//图形部分
click_limit = gameObject.AddComponent(typeof(Image)) as Image;
click_limit.sprite = limit_sprite;
click_limit.color = new Color(0, 0, 0, 0.1f);
RectTransform triggerRect = GetComponent<RectTransform>();
triggerRect.anchorMax = Vector2.zero;
triggerRect.anchorMin = Vector2.zero;
triggerRect.pivot = Vector2.one;
triggerRect.anchoredPosition = new Vector2(trigger_width, trigger_height);
triggerRect.sizeDelta = new Vector2(trigger_width, trigger_height);
chassis = CreateChild("Chassis",this.transform,E_JoystickComponent.chassis);
joystick = CreateChild("Joystick", chassis.transform,E_JoystickComponent.joystick);
}
//1)触发区域
//2)触发情况
//3)放置摇杆
//4)摇杆拖动
//5)限制摇杆摆放位置
//6)边缘位置 直接拖动
public void Update()
{
if (Input.touches.Length > 0)
{
Touch touch = Input.GetTouch(0);
//检测上一次的触发是否结束
//结束->检验此次按压的位置是否处于检测区域->放置摇杆
//非结束->拖动给杆心
if (nowTouch.phase == TouchPhase.Ended)
{
Vector2 edge = transform.GetComponent<RectTransform>().anchoredPosition;
if (touch.position.x < edge.x && touch.position.y < edge.y)
{
nowTouch = touch;
chassis.transform.position = touch.position;
prePos = touch.position;
CheckIsEdge();
}
}
else
{
joystick.GetComponent<RectTransform>().anchoredPosition = (touch.position - prePos) / sensitivity;
if(joystick.GetComponent<RectTransform>().anchoredPosition.magnitude > m_radius)
{
joystick.GetComponent<RectTransform>().anchoredPosition = joystick.GetComponent<RectTransform>().anchoredPosition.normalized * m_radius;
}
}
//检测抬手
//摇杆杆心返回
//摇杆返回初始点
//将上一状态的触摸信息设置成触摸离开
if (touch.phase == TouchPhase.Ended)
{
nowTouch.phase = TouchPhase.Ended;
chassis.GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
joystick.GetComponent<RectTransform>().anchoredPosition = iniPos;
}
//刷新当前按压位置的信息
//s = touch.position.ToString();
}
if ((joystick.GetComponent<RectTransform>().anchoredPosition.normalized * m_radius).magnitude > 0)
moveInfo = joystick.GetComponent<RectTransform>().anchoredPosition.magnitude / (joystick.GetComponent<RectTransform>().anchoredPosition.normalized * m_radius).magnitude;
else
moveInfo = 0;
moveDir = joystick.GetComponent<RectTransform>().anchoredPosition.normalized;
}
//判断是否触碰触发区边缘,并作相应调整
private void CheckIsEdge()
{
float y = Mathf.Abs(transform.position.y - chassis.transform.position.y);
float x = Mathf.Abs(transform.position.x - chassis.transform.position.x);
//判断摇杆盘底是否触碰触发区上下边缘
if (y > transform.position.x - m_radius)
{
chassis.transform.position = new Vector3(chassis.transform.position.x, m_radius, chassis.transform.position.z);
}
else if (y < m_radius)
{
chassis.transform.position = new Vector3(chassis.transform.position.x, chassis.transform.position.y - m_radius, chassis.transform.position.z);
}
//判断摇杆底盘是否触碰触发区域左右边缘
if (x > transform.position.x - m_radius)
{
chassis.transform.position = new Vector3(m_radius, chassis.transform.position.y, chassis.transform.position.z);
}
else if (x < m_radius)
{
chassis.transform.position = new Vector3(chassis.transform.position.x - m_radius, chassis.transform.position.y, chassis.transform.position.z);
}
}
/// <summary>
/// 生成对象并建立关系
/// </summary>
/// <param name="name"></param>
/// <param name="parent"></param>
/// <returns></returns>
GameObject CreateChild(string name,Transform parent,E_JoystickComponent joystickComponent)
{
GameObject gameObject = new GameObject(name);
gameObject.transform.SetParent(parent);
Image image;
RectTransform rectTransform;
Vector2 triggerRect = this.GetComponent<RectTransform>().sizeDelta;
switch (joystickComponent)
{
case E_JoystickComponent.chassis:
image = gameObject.AddComponent(typeof(Image)) as Image;
image.sprite = chassis_sprite;
image.color = Color.black;
rectTransform = image.gameObject.GetComponent<RectTransform>();
rectTransform.anchoredPosition = Vector2.zero;
rectTransform.sizeDelta = new Vector2(triggerRect.x * 2 / 7, triggerRect.y * 2 / 7);
m_radius = triggerRect.x * 2 / 7 / 2;
prePos = rectTransform.position;
break;
case E_JoystickComponent.joystick:
image = gameObject.AddComponent(typeof(Image)) as Image;
image.sprite = joystick_sprite;
image.color = Color.red;
rectTransform = image.gameObject.GetComponent<RectTransform>();
rectTransform.anchoredPosition = Vector2.zero;
rectTransform.sizeDelta = new Vector2(triggerRect.x / 7, triggerRect.y / 7);
iniPos = rectTransform.anchoredPosition;
break;
}
return gameObject;
}
}
演示:
魅蓝 note5 Unity Remote 5 的录屏情况