文章目录
- 一、最近的感想
- 二、Movement
- 1)创建平面去移动
- 2)导入人物模型
- 3)安装unity的输入安装包
- 4)设置unity的输入 系统(涉及到三个脚本)
- (1)涉及到的脚本
- (2)设定PlayerControl是的监听哪些键盘按键(InputHandler.cs)
- 5)人物碰撞和刚体
- 6)人物移动模块和输入脚本(player_locomotion)
- 7)动画脚本控制
- 8)动画控制和人物执行动画帧控制
- 三、一些名词解释
一、最近的感想
最近有点疑惑,想做好个mmorpg的服务器程序员,至少得会点客户端的东西,所以想参考下油管上制作黑魂向的指导视频学习下,小哥叫做SebastianGraves,传送门,另外在docker学习结束后,还会进行nginx搭建和对原理的简单了解博客撰写。
二、Movement
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. 动画; 动画片; 生气; 活力; 富有生命力; (指电影、录像、电脑游戏的)动画制作;