Unity第一人称FPS:为带冲刺功能的角色添加左右相机晃动效果
FPS侧移相机左右晃动实现方案(保留自由环顾)
需求说明
完成Brackey的FPS移动教程并添加冲刺机制后,需要为相机添加左右侧移时的左右晃动效果(非常见的上下晃动),同时保留相机自由环顾的功能。玩家对象结构为:Player根对象下包含CharacterController、PlayerMovement脚本,以及CameraHolder子对象,相机挂载在CameraHolder下。
现有PlayerMovement代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerMovement : MonoBehaviour { public CharacterController controller; public float speed = 12f; public float gravity = -9.81f; public float jumpHeight = 3f; public Camera cam; public int MaxFOV = 90; public float timeFOV = 0.03f; public Transform groundCheck; public float groundDistance = 0.4f; public LayerMask groundMask; Vector3 velocity; bool isGrounded; // Update is called once per frame void Update() { isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask); if(isGrounded && velocity.y < 0) { velocity.y = -2f; } float x = Input.GetAxis("Horizontal"); float z = Input.GetAxis("Vertical"); float s = Input.GetAxis("Fire3") + 1; if(s == 2) { cam.fieldOfView = Mathf.Lerp(cam.fieldOfView, MaxFOV, timeFOV); } else { cam.fieldOfView = Mathf.Lerp(cam.fieldOfView, 60, timeFOV); } Vector3 move = transform.right * x + transform.forward * z * s; controller.Move(move * speed * Time.deltaTime); if(Input.GetButtonDown("Jump") && isGrounded) { velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); } velocity.y += gravity * Time.deltaTime; controller.Move(velocity * Time.deltaTime); } }
实现方法
核心思路
通过水平移动输入值(Horizontal轴)计算相机父物体(CameraHolder)的局部X轴偏移,用平滑插值实现自然的左右晃动,同时不干扰相机的旋转环顾功能。
修改后的完整代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerMovement : MonoBehaviour { public CharacterController controller; public float speed = 12f; public float gravity = -9.81f; public float jumpHeight = 3f; public Camera cam; public int MaxFOV = 90; public float timeFOV = 0.03f; public Transform groundCheck; public float groundDistance = 0.4f; public LayerMask groundMask; // 新增相机晃动控制参数 public Transform cameraHolder; // 拖入场景中的CameraHolder对象 public float sideWobbleAmount = 0.15f; // 晃动幅度,可按需调整 public float wobbleSmoothSpeed = 6f; // 晃动平滑速度,避免生硬抖动 private Vector3 originalCameraLocalPos; // 记录相机初始位置 Vector3 velocity; bool isGrounded; void Start() { // 初始化相机初始局部位置 originalCameraLocalPos = cameraHolder.localPosition; } // Update is called once per frame void Update() { isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask); if(isGrounded && velocity.y < 0) { velocity.y = -2f; } float x = Input.GetAxis("Horizontal"); float z = Input.GetAxis("Vertical"); float s = Input.GetAxis("Fire3") + 1; // 相机左右晃动逻辑 // 反向偏移:左移时相机右偏,右移时左偏,符合视觉惯性 float targetXOffset = -x * sideWobbleAmount; // 冲刺时可增大晃动幅度:targetXOffset = -x * sideWobbleAmount * s; Vector3 targetPos = originalCameraLocalPos + new Vector3(targetXOffset, 0, 0); // 平滑过渡到目标位置 cameraHolder.localPosition = Vector3.Lerp(cameraHolder.localPosition, targetPos, wobbleSmoothSpeed * Time.deltaTime); if(s == 2) { cam.fieldOfView = Mathf.Lerp(cam.fieldOfView, MaxFOV, timeFOV); } else { cam.fieldOfView = Mathf.Lerp(cam.fieldOfView, 60, timeFOV); } Vector3 move = transform.right * x + transform.forward * z * s; controller.Move(move * speed * Time.deltaTime); if(Input.GetButtonDown("Jump") && isGrounded) { velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); } velocity.y += gravity * Time.deltaTime; controller.Move(velocity * Time.deltaTime); } }
自定义调整建议
- 若想让冲刺时晃动更强烈,可将晃动幅度的计算改为:
float targetXOffset = -x * sideWobbleAmount * s; - 调整
sideWobbleAmount(幅度)和wobbleSmoothSpeed(平滑度)参数,匹配你的操作手感 - 若希望晃动带旋转效果而非纯位移,可替换位置偏移逻辑为旋转控制:
float targetRotationY = -x * 2f; // 旋转角度,按需调整 cameraHolder.localRotation = Quaternion.Lerp(cameraHolder.localRotation, Quaternion.Euler(0, targetRotationY, 0), wobbleSmoothSpeed * Time.deltaTime);
内容的提问来源于stack exchange,提问作者yesn't
相关产品推荐
相关产品推荐

