PS:本系列笔记将会记录我此次在北京学习Unity开发的总体过程,方便后期写总结,笔记为日更。
笔记内容均为 自己理解,不保证每个都对
实现 简易模拟摇杆控制物体旋转,移动,小地图光标的同步移动与旋转
使用UI接口时,要引用 EventSystems的库文件
using UnityEngine.EventSystems;
该博客举例部分接口为:
IPointerClickHandler, IPointerDownHandler, IPointerEnterHandler, IPointerExitHandler, IPointerUpHandler,
IDragHandler,IBeginDragHandler
使用方法:
public class UIInterfaceTest : MonoBehaviour,
IPointerClickHandler, IPointerDownHandler, IPointerEnterHandler, IPointerExitHandler, IPointerUpHandler,
IDragHandler,IBeginDragHandler
{
public void OnBeginDrag(PointerEventData eventData) //鼠标按下开始拖动
{
Debug.Log("OnBeginDrag !!!");
}
public void OnDrag(PointerEventData eventData) //正在拖动
{
transform.position = eventData.position; //拖动图片
Debug.Log("OnDrag !!!");
}
public void OnEndDrag(PointerEventData eventData) //结束拖动
{
Debug.Log("OnEndDrag !!!");
}
public void OnPointerClick(PointerEventData eventData) //鼠标按下松开
{
Debug.Log("OnPointerClick !!!");
}
public void OnPointerDown(PointerEventData eventData) //鼠标按下不松开
{
Debug.Log("OnPointerDown !!!");
}
public void OnPointerEnter(PointerEventData eventData) //鼠标进入
{
Debug.Log("OnPointerEnter !!!");
}
public void OnPointerExit(PointerEventData eventData) //鼠标离开
{
Debug.Log("OnPointerExit !!!");
}
public void OnPointerUp(PointerEventData eventData) //鼠标松开
{
Debug.Log("OnPointerUp !!!");
}
显示输出结果为:
可完成鼠标拖动物体DEMO: 脚本挂在物体上
public void OnDrag(PointerEventData eventData) //正在拖动
{
transform.position = eventData.position; //拖动图片
Debug.Log("OnDrag !!!");
}
利用Sin三角函数进行模拟:实现血条减少的时候会在 减少值区间小幅度震荡
public class DeHp : MonoBehaviour
{
Image tmpImg;
float orinHp, changeHp, angle;
//orinHp 初始值
//changeHp 震荡范围
//angle 震荡角度
// Start is called before the first frame update
void Start()
{
tmpImg = gameObject.GetComponent(); //获得Image组件
orinHp = tmpImg.fillAmount; //获得血量图片的初始值
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)) //空格键按下时触发
{
Debug.Log("KeyCode.Space !!!");
orinHp = tmpImg.fillAmount - 0.05f; //血量减少的0.05f
angle = 0;
changeHp = 0.3f;
}
if(changeHp >= 0)
{
angle += Time.deltaTime * 30; //修改震荡角度,趋于90°
changeHp -= Time.deltaTime; //修改震荡幅度, 震荡角和震荡幅度逐渐趋于平缓
tmpImg.fillAmount = orinHp + tmpImg.fillAmount * Time.deltaTime * Mathf.Sin(angle);
}
}
}
主要实现:
1、在摇杆圆内任意移动
2、超过摇杆圆的半径时,操作盘位于圆的交点
3、鼠标按下时,操作盘放大
4、鼠标松开时,操作盘归位
5、物体随着摇杆移动旋转方向
5、控制物体移动
代码实现:
1、2、3、4 操作盘 代码实现:
public Transform target; //获得摇杆位置
public Transform player; //获得玩家位置
public Transform playerArrow; //记录玩家光标的位置
public Transform terrian; //获得Terrian信息
public Transform Map; //获得MiniMap信息
float Radius = 0; //获得底部半径
Vector2 center; //记录圆心坐标
bool isHold = false; //记录是否在拖拽
public void OnBeginDrag(PointerEventData eventData) //鼠标按下,操作盘放大
{
target.localScale = new Vector3(1.1f, 1.1f, 1.1f); //选中时放大
}
public void OnDrag(PointerEventData eventData) //拖拽时跟随鼠标移动
{
isHold = true; //拖拽标记 记为true
float tmpDistance = Vector3.Distance(transform.position, eventData.position); //计算圆心到鼠标位置的距离
Vector2 tmpVector = eventData.position - center; //获得圆心到鼠标点的向量
if(tmpDistance <= Radius) //距离小于等于底部圆的半径
{
target.position = eventData.position;
}
else
{
target.position = center + tmpVector.normalized * Radius; //圆心加上 单位向量 * 半径 即为圆心到鼠标点 连线与圆的交点,即为摇杆的位置
}
}
public void OnEndDrag(PointerEventData eventData) //鼠标松开,操作盘归位
{
isHold = false; //拖拽标记记为false
target.localScale = new Vector3(1, 1, 1); //松开时恢复原大小
target.position = transform.position;
}
void Start()
{
Debug.Log("transform.position == " + transform.position);
center = transform.position; //获得圆心坐标
Debug.Log("center == " + center);
RectTransform tmpRect = transform.GetComponent(); //获得 Rect Transform组件
Radius = tmpRect.sizeDelta.x / 2; //因为底部是圆形,所以半径是 x 轴的一半
}
5 控制旋转:
添加在 public void OnDrag(PointerEventData eventData)方法中
float rad = Mathf.Atan2(tmpVector.y, tmpVector.x); //反三角求出夹角
float angle = Mathf.Rad2Deg * rad; //求夹角
Vector3 tmpEuler = player.localEulerAngles; //获得原物体的欧拉角
tmpEuler.y = 90 - angle; //绕着Y轴旋转
player.transform.localEulerAngles = tmpEuler; //将修改后的欧拉 赋给物体
6控制移动:
添加在Update方法中, isHold就是用来标记摇杆是否正在拖动
if(isHold == true) //拖拽中
{
player.transform.Translate(Vector3.forward, Space.Self); //向自身坐标的Y轴移动一个单位
}
主要实现:
1、小地图光标随着物体移动而移动
2、物体旋转时,光标也发生相应的旋转
主要方式思路:
1、光标移动,利用 原物体在大地图中的 坐标比例 可求小地图坐标
2、光标旋转,与摇杆控制物体旋转一样
光标移动:
void Update()
{
if(isHold == true) //拖拽中
{
player.transform.Translate(Vector3.forward, Space.Self); //向自身坐标的Y轴移动一个单位
Vector3 TerrianSize = terrian.GetComponent().terrainData.size; //获得terrian的 大小信息
Vector3 tmpDis = player.position - terrian.position;
float rateX = tmpDis.x / TerrianSize.x - 0.5f; //计算X轴比例
float rateZ = tmpDis.z / TerrianSize.z - 0.5f; //计算Y轴比例
RectTransform MapSize = Map.GetComponent(); //获得RectTransform组件
float newX = MapSize.sizeDelta.x * rateX; //根据比例计算箭头在小地图中的X轴坐标
float newY = MapSize.sizeDelta.y * rateZ; //根据比例计算箭头在小地图中的Y轴坐标
playerArrow.position = new Vector3(MapSize.position.x + newX, MapSize.position.y + newY);
//Debug.Log("playerArrow.position == " + playerArrow.position);
}
}
光标旋转:
添加在public void OnDrag(PointerEventData eventData)方法中
tmpEuler = playerArrow.localEulerAngles; //获得原箭头的欧拉
tmpEuler.z = angle; //绕着Z轴旋转
playerArrow.transform.localEulerAngles = tmpEuler; //将修改后的欧拉赋给物体
总体代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class JoyMove : MonoBehaviour, IDragHandler, IEndDragHandler, IBeginDragHandler
{
public Transform target; //获得摇杆位置
public Transform player; //获得玩家位置
public Transform playerArrow; //记录玩家光标的位置
public Transform terrian; //获得Terrian信息
public Transform Map; //获得MiniMap信息
float Radius = 0; //获得底部半径
Vector2 center; //记录圆心坐标
bool isHold = false; //记录是否在拖拽
public void OnBeginDrag(PointerEventData eventData)
{
target.localScale = new Vector3(1.1f, 1.1f, 1.1f); //选中时放大
}
public void OnDrag(PointerEventData eventData) //拖拽时跟随鼠标移动
{
isHold = true; //拖拽标记 记为true
float tmpDistance = Vector3.Distance(transform.position, eventData.position); //计算圆心到鼠标位置的距离
Vector2 tmpVector = eventData.position - center; //获得圆心到鼠标点的向量
if(tmpDistance <= Radius) //距离小于等于底部圆的半径
{
target.position = eventData.position;
}
else
{
target.position = center + tmpVector.normalized * Radius; //圆心加上 单位向量 * 半径 即为圆心到鼠标点 连线与圆的交点,即为摇杆的位置
}
float rad = Mathf.Atan2(tmpVector.y, tmpVector.x); //反三角求出夹角
float angle = Mathf.Rad2Deg * rad; //求夹角
Vector3 tmpEuler = player.localEulerAngles; //获得原物体的欧拉角
tmpEuler.y = 90 - angle; //绕着Y轴旋转
player.transform.localEulerAngles = tmpEuler; //将修改后的欧拉 赋给物体
tmpEuler = playerArrow.localEulerAngles; //获得原箭头的欧拉
tmpEuler.z = angle; //绕着Z轴旋转
playerArrow.transform.localEulerAngles = tmpEuler; //将修改后的欧拉赋给物体
}
public void OnEndDrag(PointerEventData eventData)
{
isHold = false; //拖拽标记记为false
target.localScale = new Vector3(1, 1, 1); //松开时恢复原大小
target.position = transform.position;
}
// Start is called before the first frame update
void Start()
{
Debug.Log("transform.position == " + transform.position);
center = transform.position; //获得圆心坐标
Debug.Log("center == " + center);
RectTransform tmpRect = transform.GetComponent(); //获得 Rect Transform组件
Radius = tmpRect.sizeDelta.x / 2; //因为底部是圆形,所以半径是 x 轴的一半
}
// Update is called once per frame
void Update()
{
if(isHold == true) //拖拽中
{
player.transform.Translate(Vector3.forward, Space.Self); //向自身坐标的Y轴移动一个单位
Vector3 TerrianSize = terrian.GetComponent().terrainData.size; //获得terrian的 大小信息
Vector3 tmpDis = player.position - terrian.position;
float rateX = tmpDis.x / TerrianSize.x - 0.5f; //计算X轴比例
float rateZ = tmpDis.z / TerrianSize.z - 0.5f; //计算Y轴比例
RectTransform MapSize = Map.GetComponent(); //获得RectTransform组件
float newX = MapSize.sizeDelta.x * rateX; //根据比例计算箭头在小地图中的X轴坐标
float newY = MapSize.sizeDelta.y * rateZ; //根据比例计算箭头在小地图中的Y轴坐标
playerArrow.position = new Vector3(MapSize.position.x + newX, MapSize.position.y + newY);
//Debug.Log("playerArrow.position == " + playerArrow.position);
}
}
}