赞
踩
在大多数的游戏当中,不仅有玩家本身需要移动,游戏内的许多NPC也需要移动,因此我们可以将“人物移动”的代码拆分成“人物”代码和“移动”代码,这样一来,便可以方便我们后期的维护,并不需要分别为玩家和NPC都写下移动的代码。
- [RequireComponent(typeof(Rigidbody))]
- public class CharacterMovement: MonoBehaviour
- {
- private Rigidbody _rigidbody;
-
- public Vector3 CurrentInput { get; private set; }
- public float MaxWalkSpeed = 5;
- private void Awake()
- {
- _rigidbody = GetComponent<Rigidbody>();
- }
-
-
- private void FixedUpdate()
- {
- _rigidbody.MovePosition(_rigidbody.position + CurrentInput * MaxWalkSpeed * Time.fixedDeltaTime);
- }
-
- public void SetMovementInput(Vector3 input)
- {
- CurrentInput = Vector3.ClampMagnitude(input, 1);
- }
- }
MovePosition意为“新的位置”,可为挂载Rigidbody组件的物体而用,是一个路程单位,而路程=速度*时间,因此可以写为“新的位置=当前的位置+移动速度*时间”,即
_rigidbody.MovePosition(_rigidbody.position + CurrentInput * MaxWalkSpeed * Time.fixedDeltaTime);
用以确保CurrentInput为模长为1的向量:
CurrentInput = Vector3.ClampMagnitude(input, 1);
可以通过以下写法做到一个属性对外只读,对类自身而言可以对其值进行修改
public Vector3 CurrentInput { get; private set; }
使用RequireComponent可以让挂载此C#的物体自带组件
- public class PlayerCharacter: MonoBehaviour
- {
- private CharacterMovement _characterMovement;
-
- [SerializeField]
- private Photographer _photographer;
-
- [SerializeField] private Transform _followingTarget;
-
- private void Awake()
- {
- _characterMovement = GetComponent<CharacterMovement>();
-
- _photographer.InitCamera(_followingTarget);
- }
-
- void Update()
- {
- UpdateMovementInput();
- }
-
- private void UpdateMovementInput()
- {
- Quaternion rot = Quaternion.Euler(0, _photographer.Yaw, 0);
-
- _characterMovement.SetMovementInput(rot * Vector3.forward * Input.GetAxis("Vertical") +
- rot * Vector3.right * Input.GetAxis("Horizontal"));
- }
- }
[SerializeField]----将私有类型和保护类型可视化到面板上
在写下相机跟随的代码前,我们需要先为摄像机创建一个坐标轴
在大多数第三人称游戏中,摄像机并不会完完全全地跟随玩家角色,大多数游戏里当玩家向前移动时,操控者都可以移动视角达到看玩家的正面,以达到向前移动时仍可以观察四周
在Unity中Project Settings自带的方法中,就存在自带的一个坐标轴:
MouseX,MouseY给出是一个“距离”,即鼠标所移动的距离
而Horizontal(水平的)与Vertical(竖直的)给出的则是一个比率
即当其数值为0的时候,则静止;数值为1的时候,则移动;0.5则为半速移动
因此,显然Horizontal相比于MouseX更适合做摄像机移动的坐标轴,我们便可
复制Horizontal,改名为“CameraRateX”,并设定为第4坐标系
复制Vertical,改名为“CameraRateY”,并设定为第5坐标系,将此作为摄像机坐标轴
- public class Photographer : MonoBehaviour
- {
- public float Pitch { get; private set; }
- public float Yaw { get; private set; }
-
- public float mouseSensitivity = 5;
-
- public float cameraRotatingSpeed = 80;
- public float cameraYSpeed = 5;
- private Transform _target;
- private Transform _camera;
- [SerializeField] private AnimationCurve _armLengthCurve;
-
- private void Awake()
- {
- _camera = transform.GetChild(0);
- }
-
- public void InitCamera(Transform target)
- {
- _target = target;
- transform.position = target.position;
- }
-
- void Update()
- {
- UpdateRotation();
- UpdatePosition();
- UpdateArmLength();
- }
-
-
- private void UpdateRotation()
- {
- Yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
- Yaw += Input.GetAxis("CameraRateX") * cameraRotatingSpeed * Time.deltaTime;
- Pitch += Input.GetAxis("Mouse Y") * mouseSensitivity;
- Pitch += Input.GetAxis("CameraRateY") * cameraRotatingSpeed * Time.deltaTime;
- Pitch = Mathf.Clamp(Pitch, -90, 90);
-
- transform.rotation = Quaternion.Euler(Pitch, Yaw, 0);
- }
-
- private void UpdatePosition()
- {
- Vector3 position = _target.position;
- float newY = Mathf.Lerp(transform.position.y, position.y, Time.deltaTime * cameraYSpeed);
- transform.position = new Vector3(position.x, newY, position.z);
- }
-
- private void UpdateArmLength()
- {
- _camera.localPosition = new Vector3(0, 0, _armLengthCurve.Evaluate(Pitch) * -1);
- }
- }
其中Pitch为绕X轴旋转,Yaw为绕竖直方向的Y轴旋转
- Yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
- Yaw += Input.GetAxis("CameraRateX") * cameraRotatingSpeed * Time.deltaTime;
- Pitch += Input.GetAxis("Mouse Y") * mouseSensitivity;
- Pitch += Input.GetAxis("CameraRateY") * cameraRotatingSpeed * Time.deltaTime;
mouseSensitivity为鼠标灵敏度
其中“+=”:用于指定响应事件时要调用的方法,这类方法称为事件处理程序,叫注册/订阅事件,用在操作类名后
在大多数第三人称游戏中,往上拖动视角可以看向天空,但若一直往上拉,则会导致像太空类游戏一样视角倒转,因此需要规定摄像机可旋转的最大范围
Pitch = Mathf.Clamp(Pitch, -90, 90);
在大多数第三人称游戏中,当把视角往下拉,摄像机则会越来越靠近人物,这是为了防止摄像机看到地下,因此,我们需要一个添加一条曲线并设定摄像机臂长方法
此外,我们可以创建一个空物体放置在玩家的头部,以确保相机一直跟随着玩家的头部
[SerializeField] private AnimationCurve _armLengthCurve;
- private void UpdateArmLength()
- {
- _camera.localPosition = new Vector3(0, 0, _armLengthCurve.Evaluate(Pitch) * -1);
- }
将曲线的两点设为(-90,0.8)和(90,10)
关于在摄像机旋转所用到的欧拉角相关知识,参考:
Unity之C#学习笔记(4):Unity中旋转的表示——四元数 Quaternion(上)_quaternion xyzw_Altair_Alpha_的博客-CSDN博客
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。