1,040
社区成员




目录
在介绍具体的方法前我们先来了解一下unity中的坐标,unity的坐标采用的是左手坐标轴而不是我们常见的右手坐标轴,
unity中的世界坐标系类比于地球的经纬度,可以确定一个物体在世界中的位置,而物体的自身坐标系则是以这个物体为原点建立的坐标系,在控制物体移动的过程中我们会更多的用到物体的自身坐标系
我们这次只考虑控制器为“键盘+鼠标”的组合,手柄等控制器不在考虑范围内,在撰写控制人物移动和视角控制的脚本前,我们通过对游戏玩法的设想,将人物的移动大致分为以下几种类型
虽然unity也提供2D游戏的开发工具和开发模板,但本次只涉及3D部分的内容,在整体游戏为3D的情况下采用2D视角的横向卷轴游戏做到了一种伪2D,自3D游戏诞生以来,采用此种方式开发的卷轴游戏不在少数,如《新超级马里奥兄弟》《星之卡比 Wii》等
同样的,在考虑人物移动与视角控制时我们仍按照开发2D游戏的思路即可,只获取X轴方向上的控制器信号,并为人物加上X轴方向的力
public Rigidbody rd;
void Start()
{
rd = GetComponent<Rigidbody>();
}
void Update()
{
float h = Input.GetAxis("Horizontal");//'A''D'控制水平方向移动
rd.AddForce(new Vector3(h, 0, 0));
}
撰写控制跳跃的代码
private bool grounded;//定义一个变量用于判定是否接地,毕竟我们不能让人物左脚踩右脚上天(
void Start()
{
grounded = true;//默认接地
}
void Update()
{
if (Input.GetButtonDown("Jump"))//对应键盘的空格
{
if (grounded == true)//接地判定
{
rd.velocity += new Vector3(0, 5, 0);
rd.AddForce(Vector3.up * 50);
grounded = false;//更改控制变量,如果希望角色能二段跳也可以通过此变量控制
}
}
}
void OnTriggerEnter(Collider other)
{
grounded = true;//接地后更改控制变量
}
视角控制脚本只需要摄像机固定跟随人物移动即可
public Transform playerTransform;
private Vector3 offset;
void Start()
{
offset = transform.position - playerTransform.position;//计算摄像机与人物位置的偏移
}
void Update()
{
transform.position = playerTransform.position + offset;//改变摄像机位置
}
第一人称与第三人称的区别取决于我们摄像机的摆放,与脚本无关,在撰写脚本时的关注点是视角旋转与视角跟随
第一种方法同上,只需要补上Z轴方向的控制即可,但要控制角色的转向(角色朝向)需要另外撰写脚本
void Update()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");//'W''S'控制垂直方向移动(前进后退)
rd.AddForce(new Vector3(h, 0, v));
}
第二种方法,我们让W、S控制角色前进后退,用A、D控制人物转向,这种控制逻辑在赛车游戏上较为常见
void Update()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
transform.Translate(Vector3.forward * Time.deltaTime * v, Space.Self);
transform.Rotate(Vector3.up * Time.deltaTime * h * 60, Space.Self);
}
再考虑回视角控制,如果我们不想使用固定视角,那么最好的办法是让视角随着鼠标移动
public enum RotationAxes
{
MouseXAndY = 0,
MouseX = 1,
MouseY = 2
}
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityY = 15F;
public float minimumX = -360F;
public float maximumX = 360F;//水平方向视角控制,数字是限制的角度
public float minimumY = -60F;
public float maximumY = 60F;//垂直方向视角控制,数字是限制的角度
float rotationY = 0F;
void Start()
{
if (GetComponent<Rigidbody>())
GetComponent<Rigidbody>().freezeRotation = true;//防止刚体影响镜头旋转
}
void Update()
{
if (axes == RotationAxes.MouseXAndY)
{
float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivityX;
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = Mathf.Clamp(rotationY, minimumY, maximumY);
transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
}
else if (axes == RotationAxes.MouseX)
{
transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX, 0);
}
else
{
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = Mathf.Clamp(rotationY, minimumY, maximumY);
transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0);
}
}
俯视角的游戏,如LOL,大都考虑让角色移动到鼠标点击位置的控制逻辑,要实现这一逻辑并不难,实际上unity为我们提供了一套导航系统,只需用导航系统烘焙出导航网格,再给人物加上NavMeshAgent组件就可以实现自动寻路
using UnityEngine.AI;//记得加上这个
public NavMeshAgent agent;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//在鼠标点击处发射一条由屏幕坐标发出的射线
RaycastHit hit;//记录下射线映射的位置
if(Physics.Raycast(ray, out hit))
{
agent.SetDestination(hit.point);//寻路
}
}
}