/*--------------------------------------------------------------------
- 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
}