unity开发笔记#230821-手搓一个虚拟摇杆

做unity游戏时,如果是做手机端则需要加一个虚拟摇杆以便玩家控制角色移动(做pc端则直接获取键值即可较方便)。原理就是用Image制作一个大圆圈住一个Image小圆,玩家拖拽小圆控制角色移动。中心思想是,以小圆中心为(0,0),获取拖拽的偏移量即可。

首先将图片资源拉入项目
unity开发笔记#230821-手搓一个虚拟摇杆_第1张图片
在Hierarchy右键新建一个Canvas(UI → Canvas),并在其下新建一个Image作为摇杆背景(JoyStick-Backfround),在此摇杆背景下新建一Image作为摇杆(JoyStick)
unity开发笔记#230821-手搓一个虚拟摇杆_第2张图片
要注意的是,JoyStick-Background的RectTransform应设为左下,宽度和高度可按个人所需设定(我设了200*200)
unity开发笔记#230821-手搓一个虚拟摇杆_第3张图片
也可打开Scene手动调整虚拟摇杆在屏幕中的位置
unity开发笔记#230821-手搓一个虚拟摇杆_第4张图片
将背景和摇杆图片资源拉到JoyStick-Background和JoyStick的Image内
unity开发笔记#230821-手搓一个虚拟摇杆_第5张图片
新建一代码(VJHandler)并添加给JoyStick-Background
unity开发笔记#230821-手搓一个虚拟摇杆_第6张图片
unity开发笔记#230821-手搓一个虚拟摇杆_第7张图片
#VJHanlder

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

public class VJHandler : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler{

    private Image jsContainer;
    private Image joystick;

    public Vector3 InputDirection;

    void Start()
    {
        jsContainer = GetComponent<Image>();
        joystick = transform.GetChild(0).GetComponent<Image>();	//此处获取了子对象即摇杆的Image引用
        InputDirection = Vector3.zero;
    }

    public void OnDrag(PointerEventData ped)
    {
        Vector2 position = Vector2.zero;
        //获取输入方向(该函数返回joystick当前的坐标值)
        RectTransformUtility.ScreenPointToLocalPointInRectangle
            (jsContainer.rectTransform,
            ped.position,
            ped.pressEventCamera,
            out position);      //该函数out为返回值,此处打印可得position为(x, y)即摇杆相对于中心(0, 0)的坐标值   


        //限定JoyStick能移动的区域
        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)       //重置摇杆的方向和初始位置
    {
        InputDirection = Vector3.zero;
        joystick.rectTransform.anchoredPosition = Vector3.zero;
    }

}

其实写到屏幕坐标转成local坐标这里就已经实现了摇杆功能了,因为此处输出的坐标(代码中out position)就是摇杆的坐标

RectTransformUtility.ScreenPointToLocalPointInRectangle
            (jsContainer.rectTransform,
            ped.position,
            ped.pressEventCamera,
            out position); 
   print("out position:" + position);

加一行打印,然后运行游戏,拖动摇杆,能看到输出了每一帧摇杆的坐标值:
unity开发笔记#230821-手搓一个虚拟摇杆_第8张图片
之后再根据你的人物移动逻辑,根据已获取摇杆的坐标值,传给动画器即可实现人物移动。

如果你像我这样用(-1,0)…设置人物东南西北的移动动画
unity开发笔记#230821-手搓一个虚拟摇杆_第9张图片
则在VJHandler内加上坐标转换逻辑即可,先判断摇杆在哪一个象限,然后判断摇杆在x和y的方向上哪个偏移量更大。

if(position.x >= 0 && position.y >= 0)      //摇杆位于第一象限
        {
            if (position.x > position.y)
            {
                position.x = 1;
                position.y = 0;
            }
            else {
                position.x = 0;
                position.y = 1;
            }
        }
        else if (position.x <= 0 && position.y > 0)     //第二象限
        {
            if (Mathf.Abs(position.x) > position.y)
            {
                position.x = -1;
                position.y = 0;
            }
            else
            {
                position.x = 0;
                position.y = 1;
            }
        } else if(position.x <= 0 && position.y <= 0)   //第三象限
        {
            if(Mathf.Abs(position.x) > Mathf.Abs(position.y))
            {
                position.x = -1;
                position.y = 0;
            }
            else
            {
                position.x = 0;
                position.y = -1;
            }
        }
        else if (position.x >= 0 && position.y <= 0)      //第四象限
        {
            if (position.x > Mathf.Abs(position.y))
            {
                position.x = 1;
                position.y = 0;
            }
            else
            {
                position.x = 0;
                position.y = -1;
            }
        }

        InputDirection = new Vector3(position.x, position.y);

然后新建一个Script添加给PlayerObject,新建一个Vector3命名为movement接取VJHandler的InputDirection内的坐标值(即转换好的虚拟摇杆的坐标值),再用animator.SetFloat传给unity内的Animator即可(记得在unity内的Animator设好变量,此处变量是xDir, yDir)

using System.Collections;
using UnityEngine;

public class PlayerMovement : MonoBehaviour {

    public float moveSpeed = 0.5f;
    public VJHandler jsMovement;

    Vector3 movement = new Vector3();
    Animator animator;
    Rigidbody2D rb2D;

    private void Start()
    {
        animator = GetComponent<Animator>();
        rb2D = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        UpdateState();
    }

    void FixedUpdate()
    {
        MoveCharacter();
    }

    private void MoveCharacter()
    {
        movement.x = jsMovement.InputDirection.x;
        movement.y = jsMovement.InputDirection.y;
        movement.Normalize();       //向量归一化
        rb2D.velocity = movement * moveSpeed;	//rg2D实现移动

    }

    private void UpdateState()
    {
        if(Mathf.Approximately(movement.x, 0) && Mathf.Approximately(movement.y, 0))
        {
            animator.SetBool("isWalking", false);
        }
        else
        {
            animator.SetBool("isWalking", true);
        }
        animator.SetFloat("xDir", movement.x);
        animator.SetFloat("yDir", movement.y);

    }
}

参考:https://blog.csdn.net/JianZuoGuang/article/details/88944777

你可能感兴趣的:(unity与C#,unity,笔记,游戏引擎,C#,虚拟摇杆,安卓)