Zephus 发表于 2022-12-5 13:41

unity 摄像机跟随与切换代码怎么写?

unity 摄像机跟随与切换代码怎么写?

mastertravels77 发表于 2022-12-5 13:47

由于在游戏行业从业多年,很多同学也是从这里起步的,看着很基础,但是要写得非常简单易懂,了解整个框架,还是需要些许实践的,这个大概聊下。
当然越是基础的逻辑,网上实例代码就会越多,如RTS相机,FPS/TPP等,都是3C(Camera,Character,Controller)体验的核心内容,待会举个具体的RTS例子。
在游戏开发中,相机的控制的划分方法比较多,可以根据用途用法,功能来区分,比如过场,转场,剧情,等等,在电影中也有很多专业的镜头用语和镜头语言,表现方法,算是易学难精吧。好了回到题主的问题,主要是镜头的跟随和切换。这个主要的应用场景应该是FPP/TPP,即第一人称镜头和三人称镜头。咱们重点说下这两种情况的实现和用法。
Unity属于左手系(假定目光平视所及方向为+Z轴,头顶朝向为+Y轴,右手沿肩方向为+X,轴可以理解为不动的,固定的事物),对应于航空和机器人等行业,用于控制镜头的专业术语,像Roll(翻滚Z,可以理解为绕Z轴旋转),Pitch(俯仰X,理解为绕X旋转),Yaw(偏航Y,同理),主要通过一人称的视角来形象描述相对旋转坐标系,参考系是本身的局部坐标系,咱们再在这个基础上进一步抽象一下这个问题,相机的控制无非是绕着某个具体的点(将跟随目标抽象)旋转,或者平移(这里不考虑缩放),这个过程是相对于跟随目标对象的世界坐标系而言的,当然相机本身相对于局部坐标系也有对应旋转和平移(特殊转场,过渡的镜头特写等都会有)因此只要知道了相机如何围绕着某个点旋转,或者相机跟目标如何保持同一个朝向移动相同的位移,就能解决题主的问题了,切换只是换个目标或者旋转平移到某个位置罢了,另外FPP和TPP本质上只是相机的朝向不一样,位置不一样罢了。
为什么要这么来说明呢?因为咱们的相机在Unity引擎中进行具体的控制,需要用到这些概念,只有关联起来,代码的含义才会变得清晰起来,需要注意的是,引擎提供给咱们的是怎样的一个接口和机制,这个可能是新同学遇到的困惑,如mono behavior 脚本类似于一个状态机,每帧执行一次Update函数,输入也是类似的机制,一帧获取一次用户的输入(delta)。
接下来给点提示代码(理解背后的逻辑了,思路,细节可以各取所需,只是形式差异)
第一步,加上一个名字叫做Camera的mono behavior 脚本(自己创建一个空的也行)。


第二步,在脚本中写入
float Speed = 8.0f;
float ZoomSpeed = 200.0f;
float RotateSpeed = 20.0f;
//该函数只会在脚本构造完成后执行一遍,记录自身起始位置
void Start()
{
      Vector3 rot = transform.eulerAngles;
      rotationX = rot.x;
      rotationY = rot.y;
}


//需要先定义好输入轴,名字没有报错的话需要加一下
//该函数每帧调用一次
void Update()
{
//获取水平和垂直方向的输入(delta)水平轴名字属于自定义的,没有这个名字绑定的可能会报错,需要在输入设置中设置
float horizontalInput = transform.position.y * Input.GetAxis("Horizontal");
float verticalInput = transform.position.y * Input.GetAxis("Vertical");
float scrollInput = -Mathf.Log(transform.position.y) * Input.GetAxis("Mouse ScrollWheel");
//获取相机的朝向 按时间片来做插值
Vector3 forwardMove = transform.forward;
      forwardMove.y = 0;
      forwardMove.Normalize();
      forwardMove *= verticalInput * Speed * Time.deltaTime;
      Vector3 verticalMove = new Vector3(0, scrollInput * ZoomSpeed * Time.deltaTime, 0);
      Vector3 rightMove = transform.right * horizontalInput * Speed * Time.deltaTime;

//初级用法,用相机当前视角FPP下的三个输入意向矢量叠加成一个具体的位移矢量
Vector3 Move = verticalMove + forwardMove + rightMove;
//每帧设置一个根据输入叠加得到的位置坐标
transform.position += Move;
//2表示鼠标的右键,意为按下右键旋转视角
if (Input.GetMouseButton(2))
{
            float mouseX = Input.GetAxis("Mouse X");
            float mouseY = -Input.GetAxis("Mouse Y");
            RotateCamera(mouseX, mouseY);
}


void RotateCamera(float mouseX, float mouseY)
    {
      rotationY += mouseX * RotateSpeed * 0.02f;
      rotationX += mouseY * RotateSpeed * 0.02f;
//四元数可以非常方便得表示绕某个坐标轴的旋转,其实可以写成一个很简单的公式,目标位置=朝向+单位向量*间隔距离,这种实现方便控制跟随距离和切换目标,注意当前脚本的transform 表示当前挂在哪个对象上,这个对象的位置信息表示,如果切换目标可以把目标抽象成“点”,然后用该点算出相机位置,在当前transform 位置处和目标位置处进行按时间每帧插值计算即可
//代码形式为Vector TargetPos = 下一步你想要到达的目标点
      transform.rotation = Quaternion.Euler(rotationX, rotationY, 0.0f);
//transform.position = vector.Lerp(transform.position,TargetPos,Time.deltaTime*Speed)
//插值方式可以任意设定
}
页: [1]
查看完整版本: unity 摄像机跟随与切换代码怎么写?