创建场景及物体
可以使用Unity Asset Store中的免费Propotyping Pack,其中有一些已经做好的形状,我们不需要自己从头开始做模型。
玩家需要使用一把枪作为武器,同样使用免费的模型,链接为Guns。
这是搭建好的场景,玩家先使用一个球体代替。
因为地图场景可以当成一个整体来看待,我们可以先创建一个Empty Object,将其命名为Environment,然后将地图中的场景拖拽进Environment中。
玩家模型也是同样的道理,因为游戏是第一人称视角,所以我们要将Camera放在玩家的内部。
Unity3D中的面是单向面,也就是说这个面从一个方向可以看到,但是从另一个方向就看不见,所以我们将Camera放在Sphere内部是可以从里面看到外面的,就像人的眼睛。
我们可以将玩家模型命名为Player,将Player模型的默认自带的Mesh Render、Sphere组件删除,此时Player模型会变成透明的,我们在其内部创建一个Sphere 3D对象,这样Player就又有形状和颜色了。
为Player模型添加RigidBody组件,这个组件时Unity3D自带的。我们先不使用它的Gravity(重力)属性,这样我们的Player就可以浮在空中,要不然Camera中的视角就太矮了。
RigidBody(刚体)可以用于模拟物体在物理世界中的运动和碰撞。
编写控制玩家移动的脚本
为Player模型创建PlayerController和PlayerInput两个脚本,分别用于读取玩家的输入和处理玩家的移动、转向。
键盘控制水平方向移动
我们可以将读取玩家输入的逻辑编写在PlayerInput文件的Update()函数中。
//水平方向的移动
float xMov = Input.GetAxisRaw("Horizontal");
float yMov = Input.GetAxisRaw("Vertical");
//normalized是单位化,保证速度不会因为斜向移动而变快
Vector3 velocity = (transform.right * xMov + transform.forward * yMov).normalized * speed;
在Unity3D中,速度是一个向量,我们将transform.right
和transform.forward
表示相对于物体本地坐标系的右方向和前方向。
transform.right
: 这表示物体本地坐标系中的右方向。在Unity中,右方向是物体向右的本地坐标轴。当你使用transform.right
时,你获取的是物体在其本地坐标系中沿着右侧轴的向量。transform.forward
: 这表示物体本地坐标系中的前方向。在Unity中,前方向是物体朝向的本地坐标轴。使用transform.forward
时,你获取的是物体在其本地坐标系中沿着前方轴的向量。
用他们分别乘以x轴和y轴的移动量,再进行标准化,最后再乘以速度。速度是我们自定义的一个变量。
[SerializeField]
private float speed = 5f;
在PlayerController中,我们要编写控制玩家移动的代码了。
玩家是一个刚体,我们要控制一个刚体做物理运动时,最好使用FixedUpdate()函数,它和Update()函数的区别是,FixedUpdate在一秒内会均匀的执行50次,而Update的执行可能是不均匀的。
核心代码
public class PlayerController : MonoBehaviour
{
[SerializeField]
private Rigidbody rb;
private Vector3 velocity;
public void Move(Vector3 _velocity)
{
velocity = _velocity;
}
private void PerformMovement()
{
if (velocity != Vector3.zero)
{
rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);
}
}
}
记得要在Unity编辑器中将RigidBody对象拖到rb属性上。
玩家的运动公式是,下一秒的位置=上一秒的运动位置 + 速度 * 时间,也就是xt=xt-1 + v * t
鼠标控制玩家旋转
同样,Input类中的静态方法GetAxisRaw也可以获取鼠标X轴和Y轴的移动,取值为0~1的浮点数,X轴正方向为正值,负方向为负值。
我们可以发现鼠标水平方向移动,移动的是物体的Y轴,而鼠标垂直方向移动,移动的是X轴。
lookSensitivity是用于控制镜头转动的灵敏度的
float xMouse = Input.GetAxisRaw("Mouse X");
float yMouse = Input.GetAxisRaw("Mouse Y");
Vector3 xRot = new Vector3(yMouse, 0f, 0f) * lookSensitivity;
Vector3 yRot = new Vector3(0f, xMouse, 0f) * lookSensitivity;
核心代码
public class PlayerController : MonoBehaviour
{
private Vector3 xRot;
private Vector3 yRot;
[SerializeField]
private Camera cam;
public void Rotate(Vector3 _xRot, Vector3 _yRot)
{
xRot = _xRot;
yRot = _yRot;
}
private void PerformRotation()
{
if (xRot != Vector3.zero)
{
cam.transform.Rotate(-xRot);
}
if (yRot != Vector3.zero)
{
rb.transform.Rotate(yRot);
}
}
}
同样要记得在Unity编辑器中将Camera对象拖进cam属性。
在Unity中控制物体旋转有很多方法,一种是使用四元数(比较复杂),另一种是使用欧拉角。这里使用第二种。
使用欧拉角是一种表示旋转的方式,但它有一些限制和问题,尤其是在进行多次旋转时可能出现万向锁(Gimbal Lock)的问题,导致旋转不稳定。
评论区