谷城网站开发,优购物官方网站订单查询,买2g 空间做下载网站,营销型网站的作用是基础知识
鼠标输入
在Unity中#xff0c;开发者在“Edit” “Project Settings” “Input Manager”中设置输入#xff0c;如下图所示#xff1a;
在设置了Mouse X后#xff0c;Input.GetAxis(Mouse X)返回的是鼠标在X轴上的增量值。这意味着它会…基础知识
鼠标输入
在Unity中开发者在“Edit” “Project Settings” “Input Manager”中设置输入如下图所示
在设置了Mouse X后Input.GetAxis(Mouse X)返回的是鼠标在X轴上的增量值。这意味着它会返回鼠标在上一帧和当前帧之间的变化量。如果鼠标在X轴上向右移动返回值将是正数如果鼠标向左移动返回值将是负数。
根据Unity官方文档 - Input.GetAxis的说明这里要强调的是Input.GetAxis返回由axisName标识的虚拟轴的值没说是增量
对于键盘和操纵杆输入设备该值将在 [ − 1 , 1 ] [-1,1] [−1,1]的范围内。
如果将轴映射到鼠标则值会有所不同并且不会在 [ − 1 , 1 ] [-1,1] [−1,1]的范围内。相反它将是当前鼠标增量乘以轴灵敏度。通常正值表示鼠标向右/向下移动负值表示鼠标向左/向上移动。
这与帧速率无关使用此值时不需要担心帧速率的变化。
相机代码及解析
基本代码
using UnityEngine;public class CameraController: MonoBehaviour
{[Tooltip(the object that camera look at)]public Transform targetObject; // 指定的物体public float distance 5.0f; // 相机距离public float rotationSpeed 2.0f; // 旋转速度private float currentRotationX 0.0f;private float currentRotationY 0.0f;void Start(){if (targetObject null){Debug.LogError(Please assign a target object to the CameraManager script.);}}void Update(){// 获取鼠标输入float mouseX Input.GetAxis(Mouse X);float mouseY Input.GetAxis(Mouse Y);// 计算旋转角度单位是度currentRotationX - mouseY * rotationSpeed;currentRotationY mouseX * rotationSpeed;// 限制垂直旋转角度在-90到90度之间currentRotationX Mathf.Clamp(currentRotationX, -90.0f, 90.0f);// 计算相机位置Vector3 direction new Vector3(0, 0, -distance);Quaternion rotation Quaternion.Euler(currentRotationX, currentRotationY, 0);Vector3 cameraPosition targetObject.position rotation * direction;// 应用相机位置和旋转transform.position cameraPosition;transform.LookAt(targetObject.position);}
}主要先旋转相机再通过LookAt方法使之朝向人物就完事了。所以核心就是计算相机位置的三行代码如下。
// 计算相机位置
Vector3 direction new Vector3(0, 0, -distance);
Quaternion rotation Quaternion.Euler(currentRotationX, currentRotationY, 0);
Vector3 cameraPosition targetObject.position rotation * direction;Quaternion×Vector3的意义四元数×三维向量会得到一个新的Vector3表示旋转后的新方向。 首先定义了一个叫做direction的三维向量这里说实话我本身没想明白困扰了很久。 上图略去了y轴
但是我查了一下一个局部坐标系的Vector3变量乘以一个世界坐标系表示旋转操作的四元数其结果是世界坐标系的Vector3变量。
那这样就好理解了这个direction不是世界坐标系的不是图中红色箭头而是上图那个局部坐标系的它代表了一个从相机朝向目标物体的一个向量尽管相机是时刻移动的相应地这个局部坐标系在全局坐标系的位置和方向也在变但是乘完之后总是能得到一个全局的、经过旋转变换之后的量。 延伸1Unity默认局部坐标系的Z轴是对象的前方朝向X轴是右方Y轴是上方。 延伸2在Quaternion乘法中顺序很重要因为乘法是不符合交换律的。 相比之下一种看似正确实则错误的写法是如下这种显然是没理解direction到底是啥
// 计算相机位置
Vector3 direction new Vector3(0, 0, -distance);
Quaternion rotation Quaternion.Euler(currentRotationX, currentRotationY, 0);
Vector3 globalOffset camTransform.TransformPoint(rotation * direction);
Vector3 cameraPosition targetObject.position globalOffset;碰撞检测与SpringArm 碰撞检测和弹簧臂是相辅相成的。 如果游戏环境中有障碍物就得考虑实现碰撞检测以防止相机穿过物体。通常需要使用Raycast来检查相机和目标之间的障碍物。但是硬生生直接变化相机和人物的距离有些生硬所以还要实现弹簧臂。
弹簧臂的基本原理是将相机连接到一个虚拟的弹簧臂结构上这个结构允许相机在跟随目标的同时保持一定的弹性。弹簧臂可以有一定的长度角度和阻尼参数使相机能够在目标移动时更加平滑地跟随。
在Unity中可以使用SpringJoint或编写自定义的弹簧臂逻辑来实现这一点。弹簧臂常见的实现及其优缺点如下 Transform.Lerp: 优点 实现简单易于理解。不需要额外的组件或配置。 缺点 在快速移动的情况下可能会感觉到迟滞因为它只是简单地进行线性插值可能无法捕捉到加速和减速的变化。 SpringJoint组件: 优点 使用物理引擎可以产生更真实的弹簧效果。不需要手动编写平滑插值逻辑。 缺点 对性能的影响较大特别是在移动的物体较多的情况下。需要调整SpringJoint的参数来获取理想的效果这可能需要一些调试工作。 Vector3.SmoothDamp: 优点 提供更高级的平滑插值算法能够更好地处理加速和减速。相比Lerp更适合处理相机跟随玩家运动的场景。 缺点 可能需要调整参数以适应不同的场景。对于初学者来说可能需要一些时间来理解其工作原理。
有时候也可以结合多个方法根据不同的情况使用不同的技术。例如在高速移动时使用Vector3.SmoothDamp在需要物理效果时使用SpringJoint。
碰撞检测实现
using UnityEngine;public class CameraController: MonoBehaviour
{[Tooltip(the object that camera look at)]public Transform targetObject; // 指定的物体[Tooltip(the distance that from the camera to the target)]public float distance 5.0f; // 相机距离[Tooltip(碰撞检测平滑过渡的时间)]public float smoothTime 0.3f;[Tooltip(相机碰撞检测的层)]public LayerMask obstacleLayer;public float rotationSpeed 2.0f; // 旋转速度// camera rotateprivate float currentRotationX 0.0f;private float currentRotationY 0.0f;private Transform camTransform;// SpringArmprivate Vector3 velocity Vector3.zero;void Start(){if (targetObject null){Debug.LogError(Please assign a target object to the CameraManager script.);}camTransform GetComponentTransform();}void Update(){// 获取鼠标输入float mouseX Input.GetAxis(Mouse X);float mouseY Input.GetAxis(Mouse Y);// 计算旋转角度单位是度currentRotationX - mouseY * rotationSpeed;currentRotationY mouseX * rotationSpeed;// 限制垂直旋转角度在-85到85度之间currentRotationX Mathf.Clamp(currentRotationX, -85.0f, 85.0f);// 计算相机位置Vector3 direction new Vector3(0, 0, -distance);Quaternion rotation Quaternion.Euler(currentRotationX, currentRotationY, 0);Vector3 desiredCameraPosition targetObject.position rotation * direction;// 进行碰撞检测并调整相机位置RaycastHit hit;if (Physics.Raycast(targetObject.position, desiredCameraPosition - targetObject.position, out hit, distance, obstacleLayer)){// 如果碰撞到障碍物调整相机位置Vector3 adjustedCameraPosition hit.point;transform.position Vector3.SmoothDamp(transform.position, adjustedCameraPosition, ref velocity, smoothTime);}else{// 如果没有碰撞直接移动相机到目标位置// 这里也可以使用SmoothDamp但是效果有些怪transform.position desiredCameraPosition;}// 应用相机旋转transform.LookAt(targetObject.position);}
}主要就是在应用transform.position的时候前进行碰撞检测并查看其结果若有碰撞结果就把相机位置改到那里。 当然这样的话碰到障碍物变化起来也有些生硬可以再观察别的游戏细化加更多的逻辑。而且这里的碰撞点是很不合适的随着人物靠近障碍物相机总是靠近人物脚所以还得改y轴