简介
Unity3d脚本知识已经入门了,然后从今天开始做黑魂复刻,教程取自傅老师的DarkSouls复刻经典教程,av21513489。因为一遍做到底容易忘,那样做完就没有意义了,所以我打算一边学着做一边写博客记录过程,这样以后有哪个unity操作步骤忘了也方便查找笔记。因为是笔记,所以不会写的太详细,步骤一步过,脚本会说的细一点,那么就开始吧。
制作流程
1.新建一个3d项目,把素材导入
2.创建一个名为Materials的文件夹,在里面创建一个Material,并把在textures上下的材质图贴上对应的位置
3.创建一个plane,并把Material贴上去,再创建一个capsule,命名为PlayerHandle,把模型yBot拖进PlayerHandle中,重命名为model
4.修改PlayerHandle的组件,并添加PlayerInput、ActorController两个脚本:
5.再添加一个动画控制器:创建一个文件夹名为animator,在里面创建一个animator Controller,名为Actor,双击打开
6.创建一个前进动画的混合树,名为forward。
7.把yBot的idle4和walk动画添加进混合树:
8.把Actor导入model的animator中
9.创建一个文件夹Scripts,把脚本拖进去
这时编写好脚本(见下)后就可以行走了,但是此时走的只是模型本身,而Playerhandle并没有移动,所以我们得换一种移动方式,让Rigidbody移动。所以需要加上rigidbody组件
10.给Playerhandle附上Rigidbody组件,并把constraints的rotation的xyz勾上
11.取消勾选animator的apply root Motion选项
脚本编写
当前有ActorController和PlayerInput两个脚本,其中PlayerInout用于做角色的控制器输入,PlayerInput中定义了四个方向键和dUp与dRight作为上和右的移动量,取值[0,1),因为如果直接用Input.GetKey判断是否按下而将值在0和1两数中变化就太生硬了,所以可以用Mathf.SmoothDamp来让dUp和dRight有一个过渡。
//注意,变量都为全局变量而不能在update中定义
targetUp = (Input.GetKey(upKey) ? 1.0f : 0) - (Input.GetKey(bottomKey) ? 1.0f : 0);
targetRight = (Input.GetKey(rightKey) ? 1.0f : 0) - (Input.GetKey(leftKey) ? 1.0f : 0);
dUp = Mathf.SmoothDamp(dUp, targetUp, ref velocityDUp, 0.1f);
dRight = Mathf.SmoothDamp(dRight, targetRight, ref velocityDRight, 0.1f);
移动量可以用勾股定理算出dUp和dRight的组合量作为移动量,代码为
dMag = Mathf.Sqrt(dUp * dUp + dRight * dRight);
不过这会有一个bug,当角色斜向走时,移动量为根号2,显然比1快,这个问题先放着以后再来解决。
而要求实际移动向量,可以用移动量dMag乘模型的前向量model.transform.forward,为了让移动速度和动画同步防止出现太空步的问题,还需要乘一个walkSpeed,值根据动画来设,这里我设为1.5f。
//movingVec为Vector3,walkSpeed为float
movingVec = pi.dMag * model.transform.forward * walkSpeed;
PlayerInput.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerInput : MonoBehaviour
{
public string upKey = "w";
public string bottomKey = "s";
public string leftKey = "a";
public string rightKey = "d";
public float dUp;
public float dRight;
[SerializeField]
private float targetUp;
private float targetRight;
private float velocityDUp;
private float velocityDRight;
public float dMag; //
public Vector3 dVec; //移动方向
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
targetUp = (Input.GetKey(upKey) ? 1.0f : 0) - (Input.GetKey(bottomKey) ? 1.0f : 0);
targetRight = (Input.GetKey(rightKey) ? 1.0f : 0) - (Input.GetKey(leftKey) ? 1.0f : 0);
dUp = Mathf.SmoothDamp(dUp, targetUp, ref velocityDUp, 0.1f);
dRight = Mathf.SmoothDamp(dRight, targetRight, ref velocityDRight, 0.1f);
dMag = Mathf.Sqrt(dUp * dUp + dRight * dRight) ;
dVec = transform.forward * dUp + transform.right * dRight;
}
}
ActorController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ActorController : MonoBehaviour
{
[SerializeField]
private Animator animr;
public PlayerInput pi;
public GameObject model;
private Rigidbody rigbody;
public Vector3 movingVec; //移动向量
public float walkSpeed = 1.4f;
// Start is called before the first frame update
void Awake()
{
animr = model.GetComponent<Animator>();
pi = GetComponent<PlayerInput>();
rigbody = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
animr.SetFloat("forward", pi.dMag);
if (pi.dMag > 0.1f)
model.transform.forward = pi.dVec;
movingVec = pi.dMag * model.transform.forward * walkSpeed;
}
private void FixedUpdate()
{
rigbody.position += movingVec * Time.fixedDeltaTime;
}
}