简单记录一下之前做的人物移动,包括摇杆和键盘的切换
首先是摇杆的代码,单例类代码就不贴了,随便写个单例就行,界面长这样,注意JoyStickerBG的设置一定要和图片上一样,如果出问题的话大概就是布局和锚点(pivot)的问题,JoySticker脚本挂在sticker上就行,设置一下limit的长度,一般是父物体长宽的一半
using UnityEngine;
using UnityEngine.EventSystems;
public class JoySticker : MonoSingleton<JoySticker>, IDragHandler, IBeginDragHandler, IEndDragHandler
{
/// <summary>
/// 限制摇杆的移动范围
/// </summary>
public float limit;
/// <summary>
/// 摇杆所在位置的向量
/// </summary>
public Vector2 dir;
/// <summary>
/// 摇杆向量的模
/// </summary>
public float mo;
public RectTransform rect;
public RectTransform parentRect;
protected override void Awake()
{
base.Awake();
rect = transform.GetComponent<RectTransform>();
parentRect = transform.parent.GetComponent<RectTransform>();
}
public void OnBeginDrag(PointerEventData eventData)
{
LimitSticker(eventData);
}
public void OnDrag(PointerEventData eventData)
{
LimitSticker(eventData);
}
public void OnEndDrag(PointerEventData eventData)
{
//松开摇杆时重置摇杆的位置
rect.anchoredPosition = Vector3.zero;
Debug.Log("OnEndDrag " + rect.anchoredPosition);
dir = Vector2.zero;
mo = 0;
}
public void LimitSticker(PointerEventData eventData)
{
//鼠标位置减去摇杆父物体的位置,这里一定要用RectTransform的anchoredPosition,不然canvas的renderMode会影响效果
//得到摇杆相对于自身anchoredPosition的零点的位置(这一步是最重要的也是最坑的)
//eventData.position - parentRect.anchoredPosition 这两个相减就是摇杆的位置,如果点到摇杆的中心的话这个值应该接近0
Vector3 offset = eventData.position - parentRect.anchoredPosition;
Debug.Log(parentRect.anchoredPosition);
//对摇杆的localPosition进行限制,限制摇杆的位置向量长度
rect.anchoredPosition = Vector3.ClampMagnitude(offset, limit);
//设置摇杆的向量
dir = transform.localPosition / limit;
mo = dir.magnitude;
}
}
然后是人物移动的代码
using UnityEngine;
public class PlayerController : MonoBehaviour
{
/// <summary>
/// 移动速度
/// </summary>
public float moveSpeed = 1;
/// <summary>
/// 摇杆移动死区
/// </summary>
public float moveDeathAre = 0.2f;
/// <summary>
/// 旋转速度
/// </summary>
public float rotateSpeed = 5;
/// <summary>
/// 动画组件
/// </summary>
Animator ani;
/// <summary>
/// 是否为摇杆移动
/// </summary>
public bool isJoySticker;
/// <summary>
/// 移动的方向
/// </summary>
Vector3 dir;
/// <summary>
/// 摄像机自身的方向
/// </summary>
Vector3 cameraRealDir;
/// <summary>
/// 真实的摄像机方向(去除角度影响)
/// </summary>
Vector3 realDir;
public CharacterController cc;
void Start()
{
ani = GetComponent<Animator>();
cc = GetComponent<CharacterController>();
}
void Update()
{
MoveType();
}
/// <summary>
/// 选择操作类型进行移动
/// </summary>
public void MoveType()
{
//如果不是摇杆移动,则通过键盘输入的值移动
if (!isJoySticker)
{
dir = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
Move(dir.x, dir.z, dir.magnitude);
}
else
{
Move(JoySticker.Instance.dir.x, JoySticker.Instance.dir.y, JoySticker.Instance.mo);
}
if (dir.x != 0 || dir.z != 0)
{
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(realDir), Time.deltaTime * rotateSpeed);
}
}
/// <summary>
/// 控制移动的方法
/// </summary>
/// <param name="dirX"></param>
/// <param name="dirY"></param>
/// <param name="mo"></param>
public void Move(float dirX, float dirY, float mo)
{
dir = new Vector3(dirX, 0, dirY);
cameraRealDir = Camera.main.transform.TransformDirection(dir);
realDir = new Vector3(cameraRealDir.x, 0, cameraRealDir.z).normalized;
if (mo >= moveDeathAre)
{
cc.SimpleMove(realDir * moveSpeed * Time.deltaTime * mo);
ani.SetFloat("isWalk", mo);
}
else
{
ani.SetFloat("isWalk", 0);
}
}
}