当前位置:   article > 正文

Unity3D开发日志一:#1 3DRPG中的人物移动和相机跟随_unity3d人物移动代码

unity3d人物移动代码

 一、人物移动

        在大多数的游戏当中,不仅有玩家本身需要移动,游戏内的许多NPC也需要移动,因此我们可以将“人物移动”的代码拆分成“人物”代码和“移动”代码,这样一来,便可以方便我们后期的维护,并不需要分别为玩家和NPC都写下移动的代码。

1.关于角色移动

  1. [RequireComponent(typeof(Rigidbody))]
  2. public class CharacterMovement: MonoBehaviour
  3. {
  4. private Rigidbody _rigidbody;
  5. public Vector3 CurrentInput { get; private set; }
  6. public float MaxWalkSpeed = 5;
  7. private void Awake()
  8. {
  9. _rigidbody = GetComponent<Rigidbody>();
  10. }
  11. private void FixedUpdate()
  12. {
  13. _rigidbody.MovePosition(_rigidbody.position + CurrentInput * MaxWalkSpeed * Time.fixedDeltaTime);
  14. }
  15. public void SetMovementInput(Vector3 input)
  16. {
  17. CurrentInput = Vector3.ClampMagnitude(input, 1);
  18. }
  19. }

       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#的物体自带组件

2.关于玩家角色

  1. public class PlayerCharacter: MonoBehaviour
  2. {
  3. private CharacterMovement _characterMovement;
  4. [SerializeField]
  5. private Photographer _photographer;
  6. [SerializeField] private Transform _followingTarget;
  7. private void Awake()
  8. {
  9. _characterMovement = GetComponent<CharacterMovement>();
  10. _photographer.InitCamera(_followingTarget);
  11. }
  12. void Update()
  13. {
  14. UpdateMovementInput();
  15. }
  16. private void UpdateMovementInput()
  17. {
  18. Quaternion rot = Quaternion.Euler(0, _photographer.Yaw, 0);
  19. _characterMovement.SetMovementInput(rot * Vector3.forward * Input.GetAxis("Vertical") +
  20. rot * Vector3.right * Input.GetAxis("Horizontal"));
  21. }
  22. }

        [SerializeField]----将私有类型和保护类型可视化到面板上

二、相机跟随

        在写下相机跟随的代码前,我们需要先为摄像机创建一个坐标轴

        在大多数第三人称游戏中,摄像机并不会完完全全地跟随玩家角色,大多数游戏里当玩家向前移动时,操控者都可以移动视角达到看玩家的正面,以达到向前移动时仍可以观察四周

        在Unity中Project Settings自带的方法中,就存在自带的一个坐标轴:

                MouseX,MouseY给出是一个“距离”,即鼠标所移动的距离

                而Horizontal(水平的)与Vertical(竖直的)给出的则是一个比率

                即当其数值为0的时候,则静止;数值为1的时候,则移动;0.5则为半速移动

        因此,显然Horizontal相比于MouseX更适合做摄像机移动的坐标轴,我们便可

        复制Horizontal,改名为“CameraRateX”,并设定为第4坐标系

        复制Vertical,改名为“CameraRateY”,并设定为第5坐标系,将此作为摄像机坐标轴

  1. public class Photographer : MonoBehaviour
  2. {
  3. public float Pitch { get; private set; }
  4. public float Yaw { get; private set; }
  5. public float mouseSensitivity = 5;
  6. public float cameraRotatingSpeed = 80;
  7. public float cameraYSpeed = 5;
  8. private Transform _target;
  9. private Transform _camera;
  10. [SerializeField] private AnimationCurve _armLengthCurve;
  11. private void Awake()
  12. {
  13. _camera = transform.GetChild(0);
  14. }
  15. public void InitCamera(Transform target)
  16. {
  17. _target = target;
  18. transform.position = target.position;
  19. }
  20. void Update()
  21. {
  22. UpdateRotation();
  23. UpdatePosition();
  24. UpdateArmLength();
  25. }
  26. private void UpdateRotation()
  27. {
  28. Yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
  29. Yaw += Input.GetAxis("CameraRateX") * cameraRotatingSpeed * Time.deltaTime;
  30. Pitch += Input.GetAxis("Mouse Y") * mouseSensitivity;
  31. Pitch += Input.GetAxis("CameraRateY") * cameraRotatingSpeed * Time.deltaTime;
  32. Pitch = Mathf.Clamp(Pitch, -90, 90);
  33. transform.rotation = Quaternion.Euler(Pitch, Yaw, 0);
  34. }
  35. private void UpdatePosition()
  36. {
  37. Vector3 position = _target.position;
  38. float newY = Mathf.Lerp(transform.position.y, position.y, Time.deltaTime * cameraYSpeed);
  39. transform.position = new Vector3(position.x, newY, position.z);
  40. }
  41. private void UpdateArmLength()
  42. {
  43. _camera.localPosition = new Vector3(0, 0, _armLengthCurve.Evaluate(Pitch) * -1);
  44. }
  45. }

       其中Pitch为绕X轴旋转,Yaw为绕竖直方向的Y轴旋转

  1. Yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
  2. Yaw += Input.GetAxis("CameraRateX") * cameraRotatingSpeed * Time.deltaTime;
  3. Pitch += Input.GetAxis("Mouse Y") * mouseSensitivity;
  4. Pitch += Input.GetAxis("CameraRateY") * cameraRotatingSpeed * Time.deltaTime;

        mouseSensitivity为鼠标灵敏度

        其中“+=”:用于指定响应事件时要调用的方法,这类方法称为事件处理程序,叫注册/订阅事件,用在操作类名后

        

        在大多数第三人称游戏中,往上拖动视角可以看向天空,但若一直往上拉,则会导致像太空类游戏一样视角倒转,因此需要规定摄像机可旋转的最大范围

Pitch = Mathf.Clamp(Pitch, -90, 90);

        

        在大多数第三人称游戏中,当把视角往下拉,摄像机则会越来越靠近人物,这是为了防止摄像机看到地下,因此,我们需要一个添加一条曲线并设定摄像机臂长方法

        此外,我们可以创建一个空物体放置在玩家的头部,以确保相机一直跟随着玩家的头部

[SerializeField] private AnimationCurve _armLengthCurve;
  1. private void UpdateArmLength()
  2. {
  3. _camera.localPosition = new Vector3(0, 0, _armLengthCurve.Evaluate(Pitch) * -1);
  4. }

        将曲线的两点设为(-90,0.8)和(90,10)

        关于在摄像机旋转所用到的欧拉角相关知识,参考:

Unity之C#学习笔记(4):Unity中旋转的表示——四元数 Quaternion(上)_quaternion xyzw_Altair_Alpha_的博客-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/122971
推荐阅读
相关标签
  

闽ICP备14008679号