摇杆2

此博客主要围绕摇杆控制物体在平面上移动展开。定义了控制人物行走方向的枚举类型 RockerMoveType 以及朝向的枚举类型 Orientation,还创建了 Rocker 类来处理相关操作,使用了 Unity 相关技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*--------------------------------------------------------------------

  • Author Name: DXL
  • Creation Time: 2018.9.28
  • File Describe: 摇杆,控制物体在平面上移动
  • ------------------------------------------------------------------*/

using UnityEngine;
using UnityEngine.EventSystems;

//控制人物行走的方向
public enum RockerMoveType
{
[EnumNameAttribute(“上下左右四方向角度不旋转移动”)]
Horizontal4, //水平面(x,y)4方向

[EnumNameAttribute("360度不旋转移动")]
Horizontal360,      //水平面(x,y)360度方向,不转向

[EnumNameAttribute("360度旋转朝向角度再旋转移动")]
TurnHead360,        //水平面(x,y)360度,转移前,先旋转头部位置,朝向移动的方向后再移动位置    

}

//朝向
public enum Orientation
{
Up,
Down,
Left,
Right,
}

public class Rocker : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
#region 变量

[InspectorShow("拖动的摇杆")]
public GameObject rockerIcon;      //当前摇杆使用的图片      

[InspectorShow("控制的物体")]
public GameObject role;            //当前摇杆控制的人物

[EnumNameAttribute("物体的移动方向")]
public RockerMoveType moveType;    //当前摇杆行走方向  

[InspectorShow("摇杆移动半径")]
public float maxRadius = 200;      //摇杆拖动的最大距离 

[InspectorShow("移动速度")]
public float roleMoveSpeed = 0.5f; //控制人物的移动速度  

[InspectorShow("减速倍率(Horizontal360)")]
public float slowSpeed = 100f;     //只有 Horizontal360 方式才生效,此时实际速度是 roleMoveSpeed / slowSpeed


Vector2 firstTouchPoint;           //首次触摸点(拖动摇杆起始点)
float hor;                         //摇杆 x坐标
float ver;                         //摇杆 y坐标

Orientation currentOri = Orientation.Up;            //当前移动物体的朝向,(只有4方向),默认朝上
int lastOri = -1;                  //上次朝向,默认没有朝向
private bool isMove = true;        //当前是否可以移动物体



//暂时只支持上下4方向移动------------------map move-----------------------------
[InspectorShow("是否地图反向移动")]
public bool isMoveMap = false;     //专门为了解决在多屏的UIRoot界面下的Image地图移动
[InspectorShow("反向移动的地图")]
public GameObject map;             //当前的地图
public bool lockMapX = false;      //锁定后只能在Y上移动
public bool lockMapY = true;       //锁定后只能在X上移动
public float mapLeftLine;          //地图最左边边界
public float mapRightLine;         //地图最右边边界
public float mapUpLine;            //地图最上边边界
public float mapDownLine;          //地图最下边边界    


public GameObject uicamera;         //UI摄像机
//暂时只支持上下4方向移动------------------camera move-----------------------------
[InspectorShow("摄像机是否移动")]
public bool isMoveCamera = false;
public bool lockCameraX = false;    //锁定后只能Y轴上移动
public bool lockCameraY = false;    //锁定后只能X轴上移动
public float cameraLeftLine;        //摄像机最左边边界
public float cameraRightLine;       //摄像机最右边边界
public float cameraUpLine;          //摄像机最上边边界
public float cameraDownLine;        //摄像机最下边边界

//支持全方位移动------------------camera move--------未完成---------------------
[InspectorShow("摄像机是否跟随人物移动")]
public bool isCameraFlollowRole = false;
public bool lockFlollowX = false;           //是否锁定X
public bool lockFlollowY = false;           //是否锁定Y      
Vector3 offsetCamera = Vector3.zero;        //摄像机与人物的初始偏差

#endregion

#region 物体移动

void Start()
{
    //如果摄像机开始跟随一定,则自动关闭摄像机定向移动
    if (isCameraFlollowRole && uicamera != null)
    {
        isMoveCamera = false;

        offsetCamera = role.transform.position - uicamera.transform.position;
    }
}

void Update()
{

    if (rockerIcon == null || rockerIcon == null || isMove == false)
    {
        return;
    }

    #region  普通移动

    hor = rockerIcon.transform.localPosition.x;
    ver = rockerIcon.transform.localPosition.y;

    Vector3 direction = new Vector3(hor, ver, 0);
    //以12点方向为起始点进行计算角度,最大为180度,不区分方向
    float angle = Vector3.Angle(direction, Vector3.up);
    //区分方向,变成360度方向     
    angle = CalculateAngle(angle);

    if (direction != Vector3.zero)
    {
        if (moveType == RockerMoveType.TurnHead360)
        {
            role.transform.rotation = Quaternion.Euler(new Vector3(0, 0, angle));
            role.transform.Translate(Vector3.up * Time.deltaTime * roleMoveSpeed);
        }

        else if (moveType == RockerMoveType.Horizontal4)
        {
            if (angle <= 45 || angle >= 315)
            {
                //上
                if (currentOri != Orientation.Up || lastOri == -1)  //默认第一次执行1次
                {
                    currentOri = Orientation.Up;
                    lastOri = (int)Orientation.Up;

                    //回调 todo 这里仅仅只执行一次
                    if (BeginMoveEventUp != null)
                    {
                        this.BeginMoveEventUp();
                    }

                }

                //role.transform.Translate(Vector3.up * Time.deltaTime * roleMoveSpeed);

                //map 下
                if (!lockMapY && isMoveMap && map != null)
                {
                    if (map.transform.localPosition.y > mapDownLine)
                    {
                        map.transform.Translate(Vector3.down * Time.deltaTime * roleMoveSpeed);
                    }

                }

                //摄像机 向上移动
                else if (!lockCameraY && isMoveCamera && uicamera != null)
                {
                    if (uicamera.transform.localPosition.y > cameraUpLine)
                    {
                        uicamera.transform.Translate(Vector3.up * Time.deltaTime * roleMoveSpeed);
                    }
                }
                else
                {
                    //地图和人,摄像机,3者只能移动1个
                    role.transform.Translate(Vector3.up * Time.deltaTime * roleMoveSpeed);
                }

            }
            else if (angle > 45 && angle < 135)
            {
                //左
                if (currentOri != Orientation.Left)
                {
                    currentOri = Orientation.Left;
                    lastOri = (int)Orientation.Left;

                    //回调 todo 这里仅仅只执行一次
                    if (BeginMoveEventLeft != null)
                    {
                        this.BeginMoveEventLeft();
                    }

                }
                //role.transform.Translate(Vector3.left * Time.deltaTime * roleMoveSpeed);

                //map 右移动
                if (!lockMapX && isMoveMap && map != null)
                {
                    if (map.transform.localPosition.x < mapRightLine)
                    {
                        map.transform.Translate(Vector3.right * Time.deltaTime * roleMoveSpeed);
                    }
                }
                //摄像机 向左移动
                else if (!lockCameraX && isMoveCamera && uicamera != null)
                {
                    if (uicamera.transform.localPosition.x > cameraLeftLine)
                    {
                        uicamera.transform.Translate(Vector3.left * Time.deltaTime * roleMoveSpeed);
                    }
                }
                else
                {
                    role.transform.Translate(Vector3.left * Time.deltaTime * roleMoveSpeed);
                }
            }
            else if (angle >= 135 && angle < 225)
            {
                //下
                if (currentOri != Orientation.Down)
                {
                    currentOri = Orientation.Down;
                    lastOri = (int)Orientation.Down;

                    //回调 todo 这里仅仅只执行一次
                    if (BeginMoveEventDown != null)
                    {
                        this.BeginMoveEventDown();
                    }

                }
                //role.transform.Translate(Vector3.down * Time.deltaTime * roleMoveSpeed);

                //map 向上
                if (!lockMapY && isMoveMap && map != null)
                {
                    if (map.transform.localPosition.y < mapUpLine)
                    {
                        map.transform.Translate(Vector3.up * Time.deltaTime * roleMoveSpeed);
                    }
                }
                //摄像机 向下移动
                else if (!lockCameraY && isMoveCamera && uicamera != null)
                {
                    if (uicamera.transform.localPosition.y > cameraDownLine)
                    {
                        uicamera.transform.Translate(Vector3.down * Time.deltaTime * roleMoveSpeed);
                    }
                }
                else
                {
                    role.transform.Translate(Vector3.down * Time.deltaTime * roleMoveSpeed);
                }
            }
            else if (angle >= 225 && angle < 315)
            {
                //右
                if (currentOri != Orientation.Right)
                {
                    currentOri = Orientation.Right;
                    lastOri = (int)Orientation.Right;

                    //回调 todo 这里仅仅只执行一次
                    if (BeginMoveEventRight != null)
                    {
                        this.BeginMoveEventRight();
                    }
                }
                //role.transform.Translate(Vector3.right * Time.deltaTime * roleMoveSpeed);

                //map 向左
                if (!lockMapX && isMoveMap && map != null)
                {
                    if (map.transform.localPosition.x > mapLeftLine)
                    {
                        map.transform.Translate(Vector3.left * Time.deltaTime * roleMoveSpeed);
                    }
                }
                //摄像机 向右移动
                else if (!lockCameraX && isMoveCamera && uicamera != null)
                {
                    if (uicamera.transform.localPosition.x < cameraRightLine)
                    {
                        uicamera.transform.Translate(Vector3.right * Time.deltaTime * roleMoveSpeed);
                    }

                }
                else
                {
                    role.transform.Translate(Vector3.right * Time.deltaTime * roleMoveSpeed);
                }
            }
        }

        else if (moveType == RockerMoveType.Horizontal360)
        {
            role.transform.Translate(new Vector3(hor, ver, 0) * Time.deltaTime * roleMoveSpeed / slowSpeed);

            //上
            if (angle <= 45 || angle >= 315)
            {
                if (currentOri != Orientation.Up || lastOri == -1)  //默认第一次执行1次
                {
                    currentOri = Orientation.Up;
                    lastOri = (int)Orientation.Up;

                    //回调 todo 这里仅仅只执行一次
                    if (BeginMoveEventUp != null)
                    {
                        this.BeginMoveEventUp();
                    }
                }
            }

            //左
            else if (angle > 45 && angle < 135)
            {
                if (currentOri != Orientation.Left)
                {
                    currentOri = Orientation.Left;
                    lastOri = (int)Orientation.Left;

                    //回调 todo 这里仅仅只执行一次
                    if (BeginMoveEventLeft != null)
                    {
                        this.BeginMoveEventLeft();
                    }

                }
            }

            //下
            else if (angle >= 135 && angle < 225)
            {
                if (currentOri != Orientation.Down)
                {
                    currentOri = Orientation.Down;
                    lastOri = (int)Orientation.Down;


                    if (BeginMoveEventDown != null)
                    {
                        this.BeginMoveEventDown();
                    }
                }
            }

            //右
            else if (angle >= 225 && angle < 315)
            {
                if (currentOri != Orientation.Right)
                {
                    currentOri = Orientation.Right;
                    lastOri = (int)Orientation.Right;

                    if (BeginMoveEventRight != null)
                    {
                        this.BeginMoveEventRight();
                    }
                }
            }
        }
    }

    #endregion



    #region 摄像机跟随人物移动,包含检测条件,必须放在最后检测

    if (!isCameraFlollowRole || uicamera == null || role == null)
    {
        return;
    }
    Vector3 rc = role.transform.position - offsetCamera;
    float x = rc.x;
    float y = rc.y;

    if (lockFlollowX)
    {
        x = uicamera.transform.position.x;
    }
    if (lockFlollowY)
    {
        y = uicamera.transform.position.y;
    }

    uicamera.transform.position = Vector3.Lerp(uicamera.transform.position,
        new Vector3(x, y, 0), Time.deltaTime * roleMoveSpeed);

    #endregion
}


//转换角度 ang 从 0 - 180,要变成 0 - 360
float CalculateAngle(float ang)
{
    if (hor >= 0 && ver > 0)
    {
        //第一象限            
        ang = 360 - ang;
    }
    else if (hor <= 0 && ver > 0)
    {
        //第二象限            
    }
    else if (hor < 0 && ver <= 0)
    {
        //第三象限           
    }
    else if (hor > 0 && ver <= 0)
    {
        //第四象限            
        ang = 360 - ang;
    }

    return ang;
}

#endregion

#region 摇杆

//开始移动
public void OnBeginDrag(PointerEventData eventData)
{
    firstTouchPoint = eventData.position;
}

//移动中
void IDragHandler.OnDrag(PointerEventData eventData)
{
    //得到触摸点与原始点角度        
    Vector2 vec = eventData.position - firstTouchPoint;
    //获取向量长度
    float distance = Vector3.Magnitude(vec);
    float radius = Mathf.Clamp(distance, 0, maxRadius);
    rockerIcon.transform.localPosition = vec.normalized * radius;

}

//移动结束
void IEndDragHandler.OnEndDrag(PointerEventData eventData)
{
    //移动结束后,让摇杆归位        
    rockerIcon.transform.localPosition = Vector3.zero;
}

#endregion

#region 对外接口 -- 仅仅是RockerMoveType 为上下4方向Horizontal4

//注册一些回到方法即可
//例如在 Ontart()方法中 这样写即可
//rocker = this.transform.GetComponent<Rocker>();
//rocker.BeginMoveUP(UPStrt);
//rocker.BeginMoveDown(DownStrt);
//rocker.BeginMoveLeft(LeftStrt);
//rocker.BeginMoveRight(RightStrt);
//


//方法回调
public delegate void BeginMove();

//传递进来的要执行的方法
BeginMove BeginMoveEventUp;
BeginMove BeginMoveEventLeft;
BeginMove BeginMoveEventDown;
BeginMove BeginMoveEventRight;


//当物体开始超上移动时,执行1次,如果和上次移动的方向一致,则不调用
public void BeginMoveUP(BeginMove handler)
{
    this.BeginMoveEventUp = handler;
}

public void BeginMoveDown(BeginMove handler)
{
    this.BeginMoveEventDown = handler;

}

public void BeginMoveLeft(BeginMove handler)
{
    this.BeginMoveEventLeft = handler;
}

public void BeginMoveRight(BeginMove handler)
{
    this.BeginMoveEventRight = handler;
}

//停止物体的移动
public void StopMove()
{
    isMove = false;
}

//恢复移动
public void Restore()
{
    isMove = true;
}

//停止地图的移动
public void StopMapMove()
{
    isMoveMap = false;
}

//恢复地图的移动
public void RestoreMap()
{
    if (map == null)
    {
        return;
    }
    isMoveMap = true;
}

/// <summary>
/// 设置摇杆信息
/// </summary>
/// <param name="rockerIcon">摇杆icon</param>
/// <param name="role">被控制的物体</param>
/// <param name="type">移动方式</param>
/// <param name="radiu">摇杆移动半径</param>
/// <param name="speed">物体移动速度</param>
/// <param name="slow">减速倍率</param>
public void SetRockerInfo(GameObject rockerIcon, GameObject role, RockerMoveType type = RockerMoveType.Horizontal4, float radiu = 200, float speed = 0.5f, float slow = 100)
{
    this.rockerIcon = rockerIcon;
    this.role = role;
    this.moveType = type;
    this.maxRadius = radiu;
    this.roleMoveSpeed = speed;
    this.slowSpeed = slow;
}

/// <summary>
/// 设置摄像机跟随人物设置
/// </summary>
/// <param name="uiCamera"></param>
/// <param name="isCameraMove"></param>
/// <param name="localX"></param>
/// <param name="localY"></param>
public void SetCamerFlollowInfo(GameObject uiCamera, bool isCameraMove = true, bool lockX = false, bool lockY = true)
{
    this.uicamera = uiCamera;
    this.isCameraFlollowRole = isCameraMove;
    this.lockFlollowX = lockX;
    this.lockFlollowY = lockY;
}

#endregion

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值