一.首先点击UI创建两个Image,将Image的Source Image改成自己想要的Texture即可,然后在Canvas下创建一空物体,将两个Image放在空物体下作为他的子对象;

然后为可以拖动的Image编写脚本,脚本如下:(有注释,就不多说了)

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class JoyStick : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler//需要注意继承的接口,接口内的方法需要实现
{

    /// 
    /// 摇杆最大半径
    /// 以像素为单位
    /// 
    public float JoyStickRadius = 50;

    /// 
    /// 摇杆重置所诉
    /// 
    public float JoyStickResetSpeed = 5.0f;

    /// 
    /// 当前物体的Transform组件
    /// 
    private RectTransform selfTransform;

    /// 
    /// 是否触摸了虚拟摇杆
    /// 
    private bool isTouched = false;

    /// 
    /// 虚拟摇杆的默认位置
    /// 
    private Vector2 originPosition;

    /// 
    /// 虚拟摇杆的移动方向
    /// 
    private Vector2 touchedAxis;
    public Vector2 TouchedAxis
    {
        get
        {
            if (touchedAxis.magnitude < JoyStickRadius)
                return touchedAxis.normalized / JoyStickRadius;
            return touchedAxis.normalized;
        }
    }

    /// 
    /// 定义触摸开始事件委托 
    /// 
    public delegate void JoyStickTouchBegin(Vector2 vec);

    /// 
    /// 定义触摸过程事件委托 
    /// 
    /// 虚拟摇杆的移动方向
    public delegate void JoyStickTouchMove(Vector2 vec);

    /// 
    /// 定义触摸结束事件委托
    /// 
    public delegate void JoyStickTouchEnd();

    /// 
    /// 注册触摸开始事件
    /// 
    public event JoyStickTouchBegin OnJoyStickTouchBegin;

    /// 
    /// 注册触摸过程事件
    /// 
    public event JoyStickTouchMove OnJoyStickTouchMove;

    /// 
    /// 注册触摸结束事件
    /// 
    public event JoyStickTouchEnd OnJoyStickTouchEnd;

    void Start()
    {
        //初始化虚拟摇杆的默认方向
        selfTransform = this.GetComponent();
        originPosition = selfTransform.anchoredPosition;
    }


    public void OnPointerDown(PointerEventData eventData)
    {
        isTouched = true;
        touchedAxis = GetJoyStickAxis(eventData);
        if (this.OnJoyStickTouchBegin != null)
            this.OnJoyStickTouchBegin(TouchedAxis);
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        isTouched = false;
        selfTransform.anchoredPosition = originPosition;
        touchedAxis = Vector2.zero;
        if (this.OnJoyStickTouchEnd != null)
            this.OnJoyStickTouchEnd();
    }

    public void OnDrag(PointerEventData eventData)
    {
        touchedAxis = GetJoyStickAxis(eventData);
        if (this.OnJoyStickTouchMove != null)
            this.OnJoyStickTouchMove(TouchedAxis);
    }


    void Update()
    {
        //当虚拟摇杆移动到最大半径时摇杆无法拖动
        //为了确保被控制物体可以继续移动
        //在这里手动触发OnJoyStickTouchMove事件
        if (isTouched && touchedAxis.magnitude >= JoyStickRadius)
        {
            if (this.OnJoyStickTouchMove != null)
                this.OnJoyStickTouchMove(TouchedAxis);
        }

        //松开虚拟摇杆后让虚拟摇杆回到默认位置
        if (selfTransform.anchoredPosition.magnitude > originPosition.magnitude)
            selfTransform.anchoredPosition -= TouchedAxis * Time.deltaTime * JoyStickResetSpeed;
    }

    /// 
    /// 返回虚拟摇杆的偏移量
    /// 
    /// The joy stick axis.
    /// Event data.
    private Vector2 GetJoyStickAxis(PointerEventData eventData)
    {
        //获取手指位置的世界坐标
        Vector3 worldPosition;
        if (RectTransformUtility.ScreenPointToWorldPointInRectangle(selfTransform,
                 eventData.position, eventData.pressEventCamera, out worldPosition))
            selfTransform.position = worldPosition;
        //获取摇杆的偏移量
        Vector2 touchAxis = selfTransform.anchoredPosition - originPosition;
        //摇杆偏移量限制
        if (touchAxis.magnitude >= JoyStickRadius)
        {
            touchAxis = touchAxis.normalized * JoyStickRadius;
            selfTransform.anchoredPosition = touchAxis;
        }
        return touchAxis;
    }


}

二.接下来,就是拖拽p_w_picpath使物体能够移动了;

为该物体添加脚本:

using UnityEngine;
using System.Collections;

public class JoyStick3D : MonoBehaviour
{

    private JoyStick js;

    void Start()
    {
        js = GameObject.FindObjectOfType();
        js.OnJoyStickTouchBegin += OnJoyStickBegin;
        js.OnJoyStickTouchMove += OnJoyStickMove;
        js.OnJoyStickTouchEnd += OnJoyStickEnd;
    }


    void OnJoyStickBegin(Vector2 vec)
    {
        Debug.Log("开始触摸虚拟摇杆");
    }

    void OnJoyStickMove(Vector2 vec)
    {
        Debug.Log("正在移动虚拟摇杆");

        //设置角色朝向
        Quaternion q = Quaternion.LookRotation(new Vector3(vec.x, 0, vec.y));
        transform.rotation = q;

        //移动角色
        transform.Translate(Vector3.forward * 75f * Time.deltaTime);
    }

    void OnJoyStickEnd()
    {
        Debug.Log("触摸移动摇杆结束");

     
    }

    void OnGUI()
    {
        GUI.Label(new Rect(30, 30, 200, 30), "3D模式下的虚拟摇杆测试");
    }
}

三.接着可以试着运行,可以看到物体可以随着p_w_picpath的拖动而移动,但是有不好的地方,就是拖拽的p_w_picpath超过半径所设置的半径JoyStickRadius时,p_w_picpath的位置就会固定在一个位置不动,

而且当在半径范围内时,物体不会持续移动,这个就不好了,不知道有那位大神能够邦杰呢?