1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Unity简单第一人称移动和摄像机旋转

Unity简单第一人称移动和摄像机旋转

时间:2021-10-17 02:51:40

相关推荐

Unity简单第一人称移动和摄像机旋转

美女镇文

图片没找到,请重新加载

两个对象,一个当前需要移动的物体,一个摄像机物体,摄像机物体放到移动物体子物体下,然后两个脚本分别挂在到对应物体上,组件对象见图:

之后在玩家身上挂载刚体(rigidbody)和碰撞体,刚体上必须锁住玩家的X/Y/Z三个轴,防止玩家任意旋转,这个很关键,不然角色会在地图上到处滚动,无法正常行走,见下图:

角色移动脚本:

using System.Collections.Generic;using UnityEngine;[RequireComponent(typeof(Rigidbody))][RequireComponent(typeof(CapsuleCollider))]public class FirstPersonMovement : MonoBehaviour{public float moveSpeed = 5;[Header("Running")]public bool canRun = true;[Tooltip("奔跑速度")]public float runSpeed = 9;[Header("奔跑按键")]public KeyCode runningKey = KeyCode.LeftShift;//检测是否离地高度float groundCheck = 1f;[Tooltip("跳跃高度")]public float jumpStrength = 2;//跳跃事件public event System.Action Jumped;/// <summary>/// 重写移动速度,根据最后添加速度为移动速度/// </summary>public List<System.Func<float>> speedOverrides = new List<System.Func<float>>();/// <summary>/// 当再次接触地面调用当前事件/// </summary>public event System.Action Grounded;public bool IsRunning { get; private set; }//是否在地面bool isGrounded = true;Rigidbody playerRigidbody;const float OriginOffset = .001f;Vector3 RaycastOrigin => transform.position + Vector3.up * OriginOffset;void Awake(){playerRigidbody = GetComponent<Rigidbody>();}void FixedUpdate(){PlayerMove();}private void LateUpdate(){GroundCheck();if (Input.GetButtonDown("Jump") && isGrounded){Jump();}}void PlayerMove(){IsRunning = canRun && Input.GetKey(runningKey);// 判断是否奔跑更改玩家移动速度float targetMovingSpeed = IsRunning ? runSpeed : moveSpeed;if (speedOverrides.Count > 0){targetMovingSpeed = speedOverrides[speedOverrides.Count - 1]();}//得到最终期望数据Vector2 targetVelocity = new Vector2(Input.GetAxis("Horizontal") * targetMovingSpeed, Input.GetAxis("Vertical") * targetMovingSpeed);//更新刚体速度playerRigidbody.velocity = transform.rotation * new Vector3(targetVelocity.x, playerRigidbody.velocity.y, targetVelocity.y);}/// <summary>/// 检测是否离地/// </summary>void GroundCheck(){CapsuleCollider capsuleCollider = GetComponent<CapsuleCollider>();Ray ra = new Ray(RaycastOrigin, Vector3.down);//从当前角色位置发射球形检测,方向向下,距离为groundCheck设置的值bool isGroundedNow = Physics.SphereCast(ra, capsuleCollider.radius, groundCheck);if (isGroundedNow && !isGrounded){Grounded?.Invoke();}//更新是否离地isGrounded = isGroundedNow;}void Jump(){playerRigidbody.AddForce(Vector3.up * 100 * jumpStrength);Jumped?.Invoke();}}

摄像机旋转脚本:

通过Tab键控制鼠标锁定与解锁

using UnityEngine;public class FirstPersonLook : MonoBehaviour{[SerializeField][Tooltip("玩家对象")]Transform character;[Tooltip("鼠标移动灵敏度")]public float sensitivity = 2;[Tooltip("移动中平滑")]public float smoothing = 1.5f;Vector2 velocity;Vector2 frameVelocity;void Reset(){//从父对象中找到玩家对象初始化character = GetComponentInParent<FirstPersonMovement>().transform;}bool isLock = true;void Start(){// 进入游戏时锁定鼠标Cursor.lockState = CursorLockMode.Locked;}void Update(){if (Input.GetKeyDown(KeyCode.Tab)){isLock = !isLock;Cursor.lockState = isLock?CursorLockMode.Locked:CursorLockMode.None;Cursor.visible= !isLock;}if (!isLock){return;}MouseRotate();}void MouseRotate(){Vector2 mouseDelta = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));//根据灵敏度修改输入数据Vector2 rawFrameVelocity = Vector2.Scale(mouseDelta, Vector2.one * sensitivity);//在目标速度和当前速度之间进行线性插值,使旋转平滑frameVelocity = Vector2.Lerp(frameVelocity, rawFrameVelocity, 1 / smoothing);velocity += frameVelocity;//对摄像机上下旋转角度进行限制,不超出(-60,60)度velocity.y = Mathf.Clamp(velocity.y, -60, 60);// 旋转摄像机的上下,旋转角色的左右transform.localRotation = Quaternion.AngleAxis(-velocity.y, Vector3.right);character.localRotation = Quaternion.AngleAxis(velocity.x, Vector3.up);}}

好了,以上就是一个简单的移动脚本,附带地面检测,代码中的地面检测是基于Unity中胶囊体进行检测的,胶囊体的坐标为中心点坐标,但是有的人物角色坐标是从脚底下发出的,所以代码中地面检测的部分代码需要修改,具体如何修改可以根据自己的项目中进行动态调整,这里指出调整方法:

Ray ra = new Ray(RaycastOrigin, Vector3.down);//从当前角色位置发射球形检测,方向向下,距离为groundCheck设置的值bool isGroundedNow = Physics.SphereCast(ra, capsuleCollider.radius, groundCheck);

这两句代码的意思是从玩家中心点位置发射一个半径为胶囊体半径的(capsuleCollider.radius)球形检测射线,方向向下,最大检测距离为groundCheck的值。大家可以根据自己玩家的位置计算新的检测位置和检测距离。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。