简介

Unity3d脚本知识已经入门了,然后从今天开始做黑魂复刻,教程取自傅老师的DarkSouls复刻经典教程,av21513489。因为一遍做到底容易忘,那样做完就没有意义了,所以我打算一边学着做一边写博客记录过程,这样以后有哪个unity操作步骤忘了也方便查找笔记。因为是笔记,所以不会写的太详细,步骤一步过,脚本会说的细一点,那么就开始吧。

制作流程

1.新建一个3d项目,把素材导入

1_导入素材.png

2.创建一个名为Materials的文件夹,在里面创建一个Material,并把在textures上下的材质图贴上对应的位置

2_添加Material.png

3.创建一个plane,并把Material贴上去,再创建一个capsule,命名为PlayerHandle,把模型yBot拖进PlayerHandle中,重命名为model

3_添加模型.png

4.修改PlayerHandle的组件,并添加PlayerInput、ActorController两个脚本:

4_PlayerHandle组件修改.png

5.再添加一个动画控制器:创建一个文件夹名为animator,在里面创建一个animator Controller,名为Actor,双击打开

5_Actor.png

6.创建一个前进动画的混合树,名为forward。

6_1_创建混合树.png
6_2_修改名字.png

7.把yBot的idle4和walk动画添加进混合树:

7_1_添加动画.png
7_2_导入动画.png
7_3_混合数动画设置信息.png

8.把Actor导入model的animator中

8_导入动画控制器.png

9.创建一个文件夹Scripts,把脚本拖进去

9_放入scripts中.png

这时编写好脚本(见下)后就可以行走了,但是此时走的只是模型本身,而Playerhandle并没有移动,所以我们得换一种移动方式,让Rigidbody移动。所以需要加上rigidbody组件
9_GIF.gif

10.给Playerhandle附上Rigidbody组件,并把constraints的rotation的xyz勾上

10_添加rigidbody组件.png

11.取消勾选animator的apply root Motion选项

11.取消勾选.png

脚本编写

当前有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;
    }
}

完成效果

控制器效果.gif

最后修改:2020 年 02 月 26 日
如果觉得我的文章对你有用,请随意赞赏