自定义第一人称控制器可适配PC端和移动端
实现功能:
可直接挂载给第一人称控制器,实现在PC端控制第一人称角色移动,摄像机旋转,以及移动端触摸实现摄像机旋转(后续还可以加上移动端点击导航功能)
构思过程:
因为之前经常用到第一人称控制器,刚好有朋友问过我移动端触摸屏怎么做,我就想能不能同时满足移动端和PC端的第一人称控制控制,这里只做了一根手指触摸滑动摄像机的功能,里面加了一个防止误触到UI的判断,移动端基本上是根据PC端的第三种情况改的(前两种情况可用在特殊情况下),基本没有太大变化,脚本粘在下面,都有详细的注释,可以参考一下
public class MoveCtrl : MonoBehaviour
{ //PC端控制摄像机的三种情况
public enum RotationAxes
{
MouseXandY = 0,
MouseX = 1,
MouseY = 2
}
public RotationAxes axes = RotationAxes.MouseXandY;
//初始化
public float sensitivityHor = 9.0f;
public float sensitivityVert = 9.0f;
//旋转灵敏度
public float minVert = -45.0f;
public float maxVert = 45.0f;
//旋转角度限制
private float _rotation;
//旋转角度
private CharacterController _characterController;
public float speed = 8f;
//移动速度
private Vector2 mouseLook;
//移动端点击
public float sensitivity = 0.1f;
//移动端灵敏度
private bool isUI;
private Camera camera;
void Start()
{
Rigidbody body = GetComponent<Rigidbody>();
if (body != null)
{
body.freezeRotation = true;
}
_characterController = GetComponent<CharacterController>();
camera = Camera.main;
}
void Update()
{ //是否点击到UI
if (Input.GetMouseButtonDown(0) || Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
if (EventSystem.current.IsPointerOverGameObject())
isUI = true;
else
isUI = false;
}
if (Input.touchCount <= 0)//判断有无触屏
{
if (Input.GetMouseButton(0))
{
//绕Y轴水平旋转
if (axes == RotationAxes.MouseX)
{
transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityHor, 0);
}
//绕X轴上下旋转,上下视角做限制
else if (axes == RotationAxes.MouseY)
{
_rotation -= Input.GetAxis("Mouse Y") * sensitivityVert;
_rotation = Mathf.Clamp(_rotation, minVert, maxVert);
float rotationY = transform.localEulerAngles.y;
//锁死水平轴旋转
transform.localEulerAngles = new Vector3(0, rotationY, 0);
//上下旋转
transform.GetChild(0).localEulerAngles = new Vector3(_rotation, 0, 0);
}
else//无限制第一人称视角旋转
{
_rotation -= Input.GetAxis("Mouse Y") * sensitivityVert;
_rotation = Mathf.Clamp(_rotation, minVert, maxVert);
float delta = Input.GetAxis("Mouse X") * sensitivityHor;
float rotationY = transform.localEulerAngles.y + delta;
transform.localEulerAngles = new Vector3(0, rotationY, 0);
transform.GetChild(0).localEulerAngles = new Vector3(_rotation, 0, 0);
}
}
float deltaX = Input.GetAxis("Horizontal") * speed;
float deltaZ = Input.GetAxis("Vertical") * speed;
Vector3 movement = new Vector3(deltaX, 0, deltaZ);
movement = Vector3.ClampMagnitude(movement, speed);//保持各方向的速度相同
movement = movement * Time.deltaTime;
movement = transform.TransformDirection(movement);//将本地坐标转换为世界坐标
_characterController.Move(movement);//通过CharacterController进行移动
}
else
{
if (isUI)
return;
Vector2 inputs = Vector2.zero;
if (Input.touchCount==1)
{
inputs = new Vector2(Input.GetTouch(0).deltaPosition.x,Input.GetTouch(0).deltaPosition.y);
}
mouseLook -= inputs * sensitivity;
mouseLook.y = Mathf.Clamp(mouseLook.y, minVert, maxVert);//上下角度加限制
transform.GetChild(0).localRotation = Quaternion.AngleAxis(mouseLook.y, Vector3.right);//绕x轴
transform.localRotation = Quaternion.AngleAxis(-mouseLook.x, Vector3.up);//绕y轴
}
}
功能测试
PC端功能正常,移动端可以使用 Device Simulator功能测试一下