黑魂向project制作学习一:movement(开展的原因和客户端学习的安排)

一、最近的感想

最近有点疑惑,想做好个mmorpg的服务器程序员,至少得会点客户端的东西,所以想参考下油管上制作黑魂向的指导视频学习下,小哥叫做SebastianGraves,传送门,另外在docker学习结束后,还会进行nginx搭建和对原理的简单了解博客撰写。

二、Movement

sebastian小哥的视频传送门

1)创建平面去移动

在这里插入图片描述
但是这样没地板图纹很硬核,所以得先该变下纹理

在这里插入图片描述
改名为Floor_MAT,并选择纹理
在这里插入图片描述
并选择格子的大小为5x5
在这里插入图片描述

2)导入人物模型

  • 加载人物模型,因为是收费的,所以这里没链接下载,但是网上都有这个,只需要上网购买就行,需要配套对应人物移动动画
    在这里插入图片描述
  • 创建场景obj并命名为Player
    在这里插入图片描述
  • 把人物模型导入这个obj里面
    在这里插入图片描述
    现在导入后就有个人物obj
    在这里插入图片描述
  • 现在需要编辑C#脚本来让人物移动
    在这里插入图片描述
  • 名词解释
    locomotion 移动
  • 这里让人物移动就需要两个东西
    ①InputHandler 玩家输入识别系统
    ②player_locomotion 玩家移动系统

3)安装unity的输入安装包

  • 安装移动识别输入的安装包
    在这里插入图片描述
    在这里插入图片描述

  • 如果找不到这个Input System,那么就点击Adcanced,选择
    在这里插入图片描述

  • 注意点
    安装完后重启unity重载项目

  • 新建Input Actions
    在这里插入图片描述

  • 脚本生成C#类,然后apply
    在这里插入图片描述

4)设置unity的输入 系统(涉及到三个脚本)

(1)涉及到的脚本

①InputHandler 输入
②PlayerControls 控制输入
③PlayerLocomotion 人物移动
在这里插入图片描述

(2)设定PlayerControl是的监听哪些键盘按键(InputHandler.cs)

①双击PlayerControls,引出一个窗口,新建action
在这里插入图片描述
②改名为Player Movement,actions改名为Movement,actions type改为 Pass Through,control Type改为Vector
在这里插入图片描述
③并删除默认的No Bingdings ,增加 2D Vector Composite,并改名为WASD
在这里插入图片描述
④修改对应Composite为2D Vector,Mode为Analog
在这里插入图片描述
⑤让wasd绑定对应键盘设定
在这里插入图片描述
⑥新增Camera监听,让摄像机右边跟随,增加StickDeazone
在这里插入图片描述
⑦新增Binding(Delta(Mouse))
在这里插入图片描述
Processors选择Normalize Vector2
在这里插入图片描述
⑧设置项目配置(这个能修改一些输入设定)
在这里插入图片描述
在这里插入图片描述
change Default Hold Time to 0,如果不设置为0,那么人物移动的时候会有延迟
在这里插入图片描述

5)人物碰撞和刚体

unity刚体文档
①点击人物Player 的GameObject增加胶囊碰撞体
在这里插入图片描述
修改一些参数
在这里插入图片描述
②增加RighidBody,然后设置Constraints,设置Freeze Rotation(因为我们要自己控制旋转)
在这里插入图片描述
③修改InputHandler这个C#脚本()

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SG
{
    
    
    public class InputHandler : MonoBehaviour
    {
    
    
        public float horizontal;
        public float vertical;
        public float moveAmount;
        public float mouseX;
        public float mouseY;

        //人物移动键盘监听的管理器
        PlayerControls inputActions;
        CameraHandler cameraHandler;

        //移动输入
        Vector2 movementInput;
        //摄像头输入
        Vector2 cameraInput;
         
        private void Awake()
        {
    
    
            cameraHandler = CameraHandler.singleton;
        }

        private void FixedUpdate()
        {
    
    
            float delta = Time.fixedDeltaTime;

            if (cameraHandler != null)
            {
    
    
                cameraHandler.FollowTarget(delta);
                cameraHandler.HandlerCameraRotation(delta,mouseX,mouseY);
            }
        }

        public void OnEnable()
        {
    
    
            //①初始化单例和单例对应的回调函数
            //获取键盘的输入数据,从2D坐标数据读进来
            if (inputActions == null)
            {
    
    
                inputActions = new PlayerControls();
                inputActions.PlayerMovement.Movement.performed += inputActions => movementInput = inputActions.ReadValue<Vector2>();
                inputActions.PlayerMovement.Camera.performed += i => cameraInput = i.ReadValue<Vector2>();
            }

            //②初始化这个输入资源库
            inputActions.Enable();
        }

        private void OnDisable()
        {
    
    
            //回收输入资源库对应数据 
            inputActions.Disable();
        }

        //这里应该是每帧去调用,转进来应该是时间?
        public void TickInput(float delta)
        {
    
    
            MoveInput(delta);
        }

        //这里应该是每帧去调用,转进来应该是时间?
        private void MoveInput(float delta)
        {
    
    
            //记录水平垂直移动值,并计算移动值
            horizontal = movementInput.x;
            vertical = movementInput.y;
            moveAmount = Mathf.Clamp01(Mathf.Abs(horizontal) + Mathf.Abs(vertical));
            mouseX = cameraInput.x;
            mouseY = cameraInput.y;
        }
    }
}

6)人物移动模块和输入脚本(player_locomotion)

①代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SG
{
    
    
    public class PlayerLocomotion : MonoBehaviour
    {
    
    
        //主摄像机的坐标
        Transform cameraObject;
        InputHandler inputHandler;
        Vector3 moveDirection;

        [HideInInspector]
        public Transform myTransform;
        [HideInInspector]
        public AnimatorHandler animatorHandler;

        public new Rigidbody rigidbody;
        //后面会有个lock Camera
        public GameObject normalCamera;  

        [Header("Stats")]
        [SerializeField]
        float movementSpeed = 5;
        [SerializeField]
        float rotationSpeed = 1;

        void Start()
        {
    
    
            //初始化单例
            rigidbody = GetComponent<Rigidbody>();
            inputHandler = GetComponent<InputHandler>();
            animatorHandler = GetComponentInChildren<AnimatorHandler>();
            cameraObject = Camera.main.transform;
            //这个的transform是默认的哪个?
            myTransform = transform;
            animatorHandler.Initialize();

        }

        public void Update()
        {
    
    
            //获得距离上一帧的间隔时间
            float delta = Time.deltaTime;

            inputHandler.TickInput(delta);

            //移动主摄像头坐标位置
            moveDirection = cameraObject.forward * inputHandler.vertical;
            moveDirection += cameraObject.right * inputHandler.horizontal;
            moveDirection.Normalize();
            moveDirection.y = 0;

            float speed = movementSpeed;
            moveDirection *= speed;

            Vector3 projectedVelocity = Vector3.ProjectOnPlane(moveDirection, normalVector);
            rigidbody.velocity = projectedVelocity;

            animatorHandler.UpdateAnimatorValues(inputHandler.moveAmount, 0);

            if (animatorHandler.canRotate)
            {
    
    
                HandleRotation(delta);
            }


        }

        #region Movement
        Vector3 normalVector;  //后面会用到
        Vector3 targetPosition;

        //调整玩家的旋转
        private void HandleRotation(float delta)
        {
    
    
            Vector3 targetDir = Vector3.zero;
            float moveOverride = inputHandler.moveAmount;

            targetDir = cameraObject.forward * inputHandler.vertical;
            targetDir += cameraObject.right * inputHandler.horizontal;

            //向量单位化,a vector keeps the same direction but its length is 1.0 
            targetDir.Normalize();
            targetDir.y = 0;

            if (targetDir == Vector3.zero)
                targetDir = myTransform.forward;

            float rs = rotationSpeed;

            Quaternion tr = Quaternion.LookRotation(targetDir);
            Quaternion targetRotation = Quaternion.Slerp(myTransform.rotation, tr, rs * delta);

            myTransform.rotation = targetRotation;
        }

        #endregion
    }
}


②点击player这个obj,挂载C#脚本到人物下面
在这里插入图片描述
③再挂载locomotion
在这里插入图片描述

  • 总结
    这样人物就能再这个平面上移动了
    在这里插入图片描述

7)动画脚本控制

①新建动画管理脚本Animations.cs
②代码展示

using System.Collections.Generic;
using UnityEngine;

namespace SG
{
    
    
    public class AnimatorHandler : MonoBehaviour
    {
    
    
        public Animator anim;
        int vertical;
        int horizontal;
        public bool canRotate;

        //相当于C++类自定义个init函数
        public void Initialize()
        {
    
    
            anim = GetComponent<Animator>();
            vertical = Animator.StringToHash("Vertical");
            horizontal = Animator.StringToHash("Horizontal");
        }

        //用移动值选择更新不同移动值,来选择不同动画
        public void UpdateAnimatorValues(float verticalMovement, float horizontalMovement)
        {
    
    
            #region Vertical
            float v = 0;

            if (verticalMovement > 0 && verticalMovement < 0.55f)
            {
    
    
                v = 0.5f;
            }
            else if (verticalMovement > 0.55f)
            {
    
    
                v = 1;
            }
            else if (verticalMovement < 0 && verticalMovement > -0.55f)
            {
    
    
                v = -0.5f;
            }
            else if (verticalMovement < -0.55f)
            {
    
    
                v = -1;
            }
            else
            {
    
    
                v = 0;
            }
            #endregion

            #region Horizontal
            float h = 0;

            if (horizontalMovement > 0 && horizontalMovement < 0.55f)
            {
    
    
                h = 0.5f;
            }
            else if (horizontalMovement > 0.55f)
            {
    
    
                h = 1;
            }
            else if (horizontalMovement < 0 && horizontalMovement > -0.55f)
            {
    
    
                h = -0.5f;
            }
            else if (horizontalMovement < -0.55f)
            {
    
    
                h = -1;
            }
            else
            {
    
    
                h = 0;
            }
            #endregion

            anim.SetFloat(vertical, v, 0.1f, Time.deltaTime);
            anim.SetFloat(horizontal, h, 0.1f, Time.deltaTime);
        }

        public void CanRotate()
        {
    
    
            canRotate = true;
        }

        public void StopRotation()
        {
    
    
            canRotate = false;
        }

    }
}

③点击Player下面的小player,添加动画组件
在这里插入图片描述

  • 总结
    现在就可以旋转人物了

8)动画控制和人物执行动画帧控制

①增加动画控制组件,改名为humanoid
在这里插入图片描述
②把humanoid放到Controller对应组件位置
在这里插入图片描述
③打开动画组件页面
在这里插入图片描述
④增加两个参数
在这里插入图片描述
⑤点击图层Layers创建xin的Blend Tree
在这里插入图片描述
⑥双击点开这个新加的BlendTree,修改Blend Type为2D Freeform Cartesian,参数修改为刚刚新增的两个参数
在这里插入图片描述

⑦新增三个奔跑、行走等动画,重置参数为0
在这里插入图片描述

三、一些名词解释

1)velocity 速度
2)InputSystem 输入系统

playeControl  负责处理存储键鼠、手柄的输入。
InputHandle   处理PlayerControl里的数据,把InputSystem里的数据类型转化为float、Vector2这种常用、直接的数据类型。
AnimatorHandle   负责给animator传入数值,改变动画状态
PlayerLocomotion  负责Player的rigidbody.velocity,以及transform.rotation
CameraHandle 负责控制相机的跟随,旋转。  

补充说明:
InputHandle处理完输入数据后,其他脚本进行计算和封装。Player的相关函数在PlayerLocomotion的Update中统一执行,CameraHandle则在InputSystem中执行。

3)animation 动画
4)resemble 看起来像
5)locomotion 移动运动
6) encapsulating
v. 简述; 概括; 压缩;
7)magnitude
n. 巨大; 重大; 重要性; 星等; 星的亮度; 震级;
8)animation
n. 动画; 动画片; 生气; 活力; 富有生命力; (指电影、录像、电脑游戏的)动画制作;

猜你喜欢

转载自blog.csdn.net/weixin_43679037/article/details/126798861
今日推荐