本章我们创建一个“RoleDemoProject”项目,然后导入我们之前在地形创建章节中创建的“TerrainDemo.unitypackage”资源包。 这个场景很大,需要调整场景视角才能看清楚。
接下来,我们通过将模型文件目录复制到“Assets”来添加角色模型
然后Unity会自动同步文件,我们查看Project面板
“Alita”目录中有两个文件:“Alita.fbx”和“alita_d.png”。 前者是模型文件,后者是纹理文件。 接下来我们要做的就是将“Alita.fbx”模型文件拖放到场景中。 由于我们的场景太大,模型可能不容易看到。 我们这样做,我们可以在Hierarchy面板中找到这个游戏对象(“Alita”),然后我们将鼠标“到(不要点击)”移动到场景视图中,然后按“F”键点击场景视图 该游戏对象显示在 中。
当然,我们最好再把这个模型调整一下,让它站在地面上。 移动模型时,一定要保持选择模型轴和局部坐标系。如下
当我们切换轴时,我们发现模型上的坐标系指示箭头移到了模型脚的底部。 一般情况下,角色模型的轴位于脚底(局部坐标系的原点)。 如果我们处于“中心”状态,坐标系指示箭头将位于模型的中心。
我们可以看到模型的下半部分位于地形下方,所以我们将其向上移动。
接下来我们要做的就是让相机随着模型一起移动和旋转。 如果使用代码完成,原则是调整相机移动和旋转的方式与模型移动和旋转的方式同时进行。 这里有一个更简单的方法,就是将相机设置为模型的子游戏对象。 操作非常简单,只需将“主相机”拖至“层次结构”面板中的“Alita”即可。
拖拽后的样子
这样做的目的是当“阿丽塔”移动和旋转时,子对象“主摄像机”自动移动和旋转。 当然,我们还需要进一步调整相机的位置,使其放置在“Alita”的上方和后方。首先,我们将相机的Position和Rotation值清零,如下图
请注意,相机现在位于模特的脚边。 在Unity中,子游戏对象的移动和旋转是相对于父对象的。 我们将相机的 Position 值重置为零,不是将相机放置到世界坐标系的原点,而是放置到父对象“Alita”的原点。 接下来我们调整相机的位置,
我们将相机放置在角色模型的上方和后方,类似于第三人称视角。
接下来unity 模型旋转,我们保持摄像机处于选中状态,点击菜单栏“GameObject”->“Align View to Selected”
在前面的移动和旋转示例中,我们忽略了一个重要特征:时间(Time.deltaTime)。 游戏物体的运动由三个因素决定,一是方向,一是速度,二是时间。 方向和速度可以用向量表示(向量的长度表示速度、方向或方向),时间为Time.deltaTime。 为什么时间是Time.deltaTime? 因为每次调用update方法时游戏对象都会移动,而两次移动之间的时间就是两次update方法调用的时间差,也就是我们的Time.deltaTime值。 因此,Translate方法中的第一个参数应该是方向*速度*时间。
接下来我们来控制角色的前后左右移动。 我们创建一个“RoleController.cs”脚本文件并将其附加到“Alita”。我们目前使用WASD键来控制角色的前、后、左、右移动。 代码如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RoleController : MonoBehaviour
{
// 移动速度
private float moveSpeed = 10.0f;
// Update is called once per frame
void Update()
{
// 向前移动
if (Input.GetKeyDown(KeyCode.W))
{
transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime, Space.Self);
}
// 向后移动
if (Input.GetKeyDown(KeyCode.S))
{
transform.Translate(Vector3.back * moveSpeed * Time.deltaTime, Space.Self);
}
// 向左移动
if (Input.GetKeyDown(KeyCode.A))
{
transform.Translate(Vector3.left * moveSpeed * Time.deltaTime, Space.Self);
}
// 向右移动
if (Input.GetKeyDown(KeyCode.D))
{
transform.Translate(Vector3.right * moveSpeed * Time.deltaTime, Space.Self);
}
}
}
这里我们使用局部坐标系进行运动3D植物,这在大多数游戏开发中也是这样做的。
接下来我们播放当前项目,查看运行后的Gif图
由于我们使用的是GetKeyDown方法,因此每次按下键盘时游戏图片素材,它都会移动一定的距离。 如果我们需要长按键盘来移动,我们可以改为GetKey方法。 当我们搬家的时候,我们发现了一个小问题,那就是我们没有考虑地形的高度。 换句话说,模型在移动过程中可能会在地形下方或上方移动。 我们稍后会解决这个问题。 接下来,我们添加旋转代码,如下所示。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RoleController : MonoBehaviour
{
// 旋转速度
private float rotationSpeed = 20.0f;
// Update is called once per frame
void Update()
{
// 向左旋转
if (Input.GetKeyDown(KeyCode.Q))
{
transform.Rotate(Vector3.down * rotationSpeed * Time.deltaTime, Space.Self);
}
// 向右旋转
if (Input.GetKeyDown(KeyCode.E))
{
transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime, Space.Self);
}
}
}
上面我们忽略了移动代码。 为什么我们使用Vector3.up和Vector3.down进行左右旋转? 它们不应该是 Vector3.left 和 Vector3.right 吗? 这很简单。 我们所说的左右旋转,类似于“左右扭转”。 它实际上是绕Y轴旋转的,所以它就是Vector3.up和Vector3.down上下方向的Y轴。接下来我们播放当前项目,查看运行的Gif效果图
接下来,让我们解决地形高度。 我们需要使用“角色控制器”组件。 我们选择“Alita”并单击检查器面板中的“添加组件”按钮。
在弹出的搜索框中输入“ch”,然后在下拉框中选择“Character Controller”字符控制器组件。
此时,场景中的“阿丽塔”将覆盖胶囊的线框。
这个胶囊的线框用于“碰撞检测”,所以最好“包裹”我们的角色模型。 当然unity 模型旋转,默认情况下,它基本上会自动“包装”我们的角色模型。 然而,需要注意的一个非常重要的一点是,胶囊的线框不能“沉入”地形之下。因此,我们需要编辑胶囊的线框。 我们直接提供其参数调整。 你可以自己修改一些值看看效果。
接下来我们还需要修改角色移动代码,如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RoleController : MonoBehaviour
{
// 移动速度
private float moveSpeed = 10.0f;
// 旋转速度
private float rotationSpeed = 100.0f;
// 角色控制器组件
private CharacterController cc;
// Start is called before the first frame update
void Start()
{
// 获取角色控制器组件
cc = GetComponent();
}
// Update is called once per frame
void Update()
{
// 前后左右方向
float v = Input.GetAxis("Vertical");
float h = Input.GetAxis("Horizontal");
Vector3 direction = new Vector3(h, 0, v);
// 前后左右移动
cc.SimpleMove(transform.TransformDirection(direction) * moveSpeed);
// 向前移动
if (Input.GetKeyDown(KeyCode.W))
{
//transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime, Space.Self);
}
// 向后移动
if (Input.GetKeyDown(KeyCode.S))
{
//transform.Translate(Vector3.back * moveSpeed * Time.deltaTime, Space.Self);
}
// 向左移动
if (Input.GetKeyDown(KeyCode.A))
{
//transform.Translate(Vector3.left * moveSpeed * Time.deltaTime, Space.Self);
}
// 向右移动
if (Input.GetKeyDown(KeyCode.D))
{
//transform.Translate(Vector3.right * moveSpeed * Time.deltaTime, Space.Self);
}
// 向左旋转,替换GetKey方法
if (Input.GetKey(KeyCode.Q))
{
transform.Rotate(Vector3.down * rotationSpeed * Time.deltaTime, Space.Self);
}
// 向右旋转,替换GetKey方法
if (Input.GetKey(KeyCode.E))
{
transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime, Space.Self);
}
}
}
上面获取键盘输入的代码是:Input.GetAxis("Vertical/Horizontal")。 该代码与WASD按键输入采集兼容。 然后使用CharacterController组件的SimpleMove方法来移动它。 上面的代码我们就不过多解释了,直接播放看看Gif渲染图即可。
文章来源:https://blog.csdn.net/konkon2012/article/details/130448320