在设计FPS(第一人称射击)游戏的摄像机系统代码逻辑架构时,需要考虑多个方面,包括摄像机的移动、旋转、视角切换、平滑过渡等。以下是一个基本的代码逻辑架构设计,使用Unity引擎作为示例:
1. 摄像机控制器基类
首先,定义一个摄像机控制器的基类,用于统一管理摄像机的基本行为。
using UnityEngine;
public abstract class CameraController : MonoBehaviour
{
public Transform playerTransform; // 玩家角色的Transform
protected virtual void Update()
{
// 子类可以重写此方法来实现具体的摄像机行为
UpdateCamera();
}
protected abstract void UpdateCamera();
}
2. 第一人称摄像机控制器
继承自基类,实现第一人称摄像机的具体行为。
using UnityEngine;
public class FirstPersonCameraController : CameraController
{
public float mouseSensitivity = 2.5f; // 鼠标灵敏度
public float smoothing = 2.0f; // 平滑过渡系数
private Vector2 currentLookingPos; // 当前摄像机视角位置
private Vector2 smoothV; // 平滑过渡向量
protected override void UpdateCamera()
{
// 获取鼠标输入
Vector2 mouseInput = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
// 计算新的视角位置
currentLookingPos += mouseInput * mouseSensitivity;
// 平滑过渡
currentLookingPos.x = Mathf.SmoothDampAngle(currentLooking + .Position.x, currentLookingPos.x, ref smoothV.x, smoothing);
currentLookingPos.y = Mathf.SmoothDampAngle(currentLookingPos.y, currentLookingPos.y, ref smoothV.y, smoothing);
// 限制垂直视角范围
currentLookingPos.y = Mathf.Clamp(currentLookingPos.y, -89f, 89f);
// 计算摄像机的旋转角度
Quaternion targetRotation = Quaternion.Euler(currentLookingPos.y, currentLookingPos.x, 0);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, smoothing * Time.deltaTime);
// 摄像机跟随玩家移动
transform.position = playerTransform.position - transform.forward * 0.18f; // 调整摄像机与玩家的距离
}
}
3. 摄像机切换逻辑
如果游戏中需要支持多种摄像机视角(如第一人称和第三人称),可以设计一个摄像机管理器来处理视角切换。
using UnityEngine;
public class CameraManager : MonoBehaviour
{
public CameraController firstPersonCamera;
public CameraController thirdPersonCamera;
private CameraController currentCamera;
void Start()
{
// 默认使用第一人称摄像机
SwitchCamera(firstPersonCamera);
}
public void SwitchCamera(CameraController newCamera)
{
if (currentCamera != null)
{
currentCamera.enabled = false;
}
currentCamera = newCamera;
currentCamera.enabled = true;
}
}
4. 输入处理
确保输入处理逻辑与摄像机控制器分离,以便于管理和扩展。
using UnityEngine;
public class InputHandler : MonoBehaviour
{
public CameraManager cameraManager;
void Update()
{
if (Input.GetKeyDown(KeyCode.C))
{
// 切换摄像机视角
if (cameraManager.currentCamera == cameraManager.firstPersonCamera)
{
cameraManager.SwitchCamera(cameraManager.thirdPersonCamera);
}
else
{
cameraManager.SaintCamera(cameraManager.firstPersonCamera);
}
}
}
}
总结
以上代码逻辑架构设计了一个基本的FPS游戏摄像机系统,包括摄像机控制器基类、第一人称摄像机控制器、摄像机切换逻辑和输入处理。通过这种方式,可以方便地扩展和维护摄像机系统,同时保持代码的清晰和可读性。根据具体需求,可以进一步添加更多的功能,如摄像机震动效果、视角切换动画等。
5. 第三人称摄像机控制器
为了完整性,我们还需要实现一个第三人称摄像机控制器。这个控制器将允许摄像机从玩家角色的后方跟随,并提供一定程度的自由度。
using UnityEngine;
public class ThirdPersonCameraController : CameraController
{
public float distance = 3.0f; // 摄像机与玩家的距离
public float height = 1.5f; // 摄像机的高度
public float smoothSpeed = 0.3f; // 平滑过渡速度
private Vector3 desiredPosition; // 摄像机期望的位置
protected override void UpdateCamera()
{
// 计算摄像机的期望位置
desiredPosition = playerTransform.position + playerTransform.up * height - playerTransform.forward * distance;
// 平滑过渡到期望位置
transform.position = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
// 摄像机朝向玩家
transform.LookAt(playerTransform);
}
}
6. 摄像机震动效果
为了增强游戏的沉浸感,可以添加摄像机震动效果。这个效果可以在特定事件(如爆炸、受伤)发生时触发。
using UnityEngine;
public class CameraShake : MonoBehaviour
{
public void Shake(float duration, float magnitude)
{
StartCoroutine(ShakeCoroutine(duration, magnitude));
}
private IEnumerator ShakeCoroutine(float duration, float magnitude)
{
Vector3 originalPosition = transform.localPosition;
float elapsed = 0.0f;
while (elapsed < duration)
{
float x = Random.Range(-1f, 1f) * magnitude;
float y = Random.Range(-1f, 1f) * magnitude;
float z = Random.Range(-1f, 1f) * magnitude;
transform.localPosition = new Vector3(x, y, z);
elapsed += Time.deltaTime;
yield return null;
}
transform.localPosition = originalPosition;
}
}
7. 视角切换动画
为了使视角切换更加平滑和自然,可以添加视角切换动画。
using UnityEngine;
public class CameraSwitchAnimation : MonoBehaviour
{
public Animator cameraAnimator; // 摄像机动画控制器
public void PlaySwitchAnimation()
{
cameraAnimator.SetTrigger("Switch");
}
}
在Unity编辑器中,为摄像机动画控制器创建一个动画状态机,并定义一个名为“Switch”的触发器。这个动画可以包括摄像机的淡入淡出、位置和旋转的平滑过渡等。
8. 摄像机碰撞检测
为了避免摄像机穿模或进入不可见区域,可以添加摄像机碰撞检测。
using UnityEngine;
public class CameraCollision : MonoBehaviour
{
public LayerMask collisionLayer; // 碰撞层
void Update()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, Mathf.Infinity, collisionLayer))
{
transform.position = hit.point - transform.forward * 0.1f; // 避免摄像机穿模
}
}
}
9. 动态视野调整
在FPS游戏中,摄像机的视野(Field of View, FOV)可以根据游戏情况进行动态调整,例如在接近敌人时放大视野以获取更多细节。
using UnityEngine;
public class DynamicFOV : MonoBehaviour
{
public Camera mainCamera;
public float defaultFOV = 60f; // 默认视野
public float zoomFOV = 30f; // 缩放视野
public float zoomSpeed = 5f; // 缩放速度
public float zoomInDistance = 5f; // 缩放进入距离
public float zoomOutDistance = 10f; // 缩放退出距离
void Update()
{
float distanceToTarget = Vector3.Distance(mainCamera.transform.position, playerTransform.position);
float targetFOV = defaultFOL;
if (distanceToTarget < zoomInDistance)
{
targetFOV = zoomFOV;
}
else if (distanceToTarget > zoomOutDistance)
{
targetFOL = defaultFOV;
}
else
{
targetFOV = Mathf.Lerp(defaultFOV, zoomFOV, (zoomInDistance - distanceToTarget) / (zoomInDistance - zoomOutDistance));
}
mainCamera.fieldOfView = Mathf.Lerp(mainCamera.fieldOf, targetFOV, Time.deltaTime * zoomSpeed);
}
}
10. 摄像机路径跟随
在某些情况下,摄像机可能需要沿着预设的路径移动,例如在过场动画或特定任务中。
using UnityEngine;
public class CameraPathFollower : MonoBehaviour
{
public Transform[] pathPoints; // 路径点
public float moveSpeed = 5f; // 移动速度
private int currentPointIndex = 0;
void Update()
{
if (pathPoints.Length == 0) return;
transform.position = Vector3.MoveTowards(transform.position, pathPoints[currentPointIndex].position, moveSpeed * Time.deltaTime);
if (Vector3.Distance(transform.position, pathPoints[currentPointIDex].position) < 0.1f)
{
currentPointIndex++;
if (currentPointIndex >= pathPoints.Length)
{
currentPointIndex = 0; // 循环路径
}
}
}
}
11. 摄像机视角限制
为了防止玩家通过旋转摄像机来获得不公平的优势,可以限制摄像机的视角范围。
using UnityEngine;
public class CameraViewRestrictor : MonoBehaviour
{
public float minPitch = -89f; // 最小俯仰角
public float maxPitch = 89f; // 最大俯仰角
void Update()
{
transform.eulerAngles = new Vector3(
Mathf.Clamp(transform.eulerAngles.x, minPitch, maxPitch),
transform.eulerAngles.y,
transform.eulerAngles.z
);
}
}
12. 摄像机交互
在某些情况下,摄像机可能需要与游戏中的物体进行交互,例如通过摄像机视角来拾取物品。
using UnityEngine;
public class CameraInteraction : MonoBehaviour
{
public LayerMask interactableLayer; // 可交互层
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity, interactableLayer))
{
InteractableObject interactableObject = hit.collider.GetComponent<InteractableObject>();
if (interactableObject != null)
{
interactableObject.Interact();
}
}
}
}
}
13. 摄像机视角切换动画
为了使视角切换更加平滑和自然,可以添加视角切换动画。这个动画可以包括摄像机的淡入淡出、位置和旋转的平滑过渡等。
using UnityEngine;
public class CameraSwitchAnimation : MonoBehaviour
{
public Animator cameraAnimator; // 摄像机动画控制器
public void PlaySwitchAnimation()
{
cameraAnimator.SetTrigger("Switch");
}
}
在Unity编辑器中,为摄像机动画控制器创建一个动画状态机,并定义一个名为“Switch”的触发器。这个动画可以包括摄像机的淡入淡出、位置和旋转的平滑过渡等。
14. 摄像机碰撞检测
为了避免摄像机穿模或进入不可见区域,可以添加摄像机碰撞检测。
using UnityEngine;
public class CameraCollision : MonoBehaviour
{
public LayerMask collisionLayer; // 碰撞层
void Update()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, Mathf.Infty, collisionLayer))
{
transform.position = hit.point - transform.forward * 0.1f; // 避免摄像机穿模
}
}
}
15. 摄像机交互
在某些情况下,摄像机可能需要与游戏中的物体进行交互,例如通过摄像机视角来拾取物品。
using UnityEngine;
public class CameraInteraction : MonoBehaviour
{
public LayerMask interactableLayer; // 可交互层
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity, interactableLayer))
{
InteractableObject interactableObject = hit.collider.GetComponent<InteractableObject>();
if (interactableObject != null)
{
interactableObject.Interact();
}
}
}
}
}
16. 摄像机视角限制
为了防止玩家通过旋转摄像机来获得不公平的优势,可以限制摄像机的视角范围。
using UnityEngine;
public class CameraViewRestrictor : MonoBehaviour
{
public float minPitch = -89f; // 最小俯仰角
public float maxPitch = 89f; // 最大俯仰角
void Update()
{
transform.eulerAngles = new Vector3(
Mathf.Clamp(transform.eulerAngles.x, minPitch, maxPitch),
transform.eulerAngles.y,
transform.eulerAngles.z
);
}
}
17. 摄像机路径跟随
在某些情况下,摄像机可能需要沿着预设的路径移动,例如在过场动画或特定任务中。
using UnityEngine;
public class CameraPathFollower : MonoBehaviour
{
public Transform[] pathPoints; // 路径点
public float moveSpeed = 5f; // 移动速度
private int currentPointIndex = 0;
void Update()
{
if (pathPoints.Length == 0) return;
transform.position = Vector3.MoveTowards(transform.position, pathPoints[currentPointIndex].position, moveSpeed * Time.deltaTime);
if (Vector3.Distance(transform.position, pathPoints[currentPointIDex].position) < 0.1f)
{
currentPointIndex++;
if (currentPointIndex >= pathPoints.Length)
{
currentPointIndex = 0; // 循环路径
}
}
}
}
18. 动态视野调整
在FPS游戏中,摄像机的视野(Field of View, FOV)可以根据游戏情况进行动态调整,例如在接近敌人时放大视野以获取更多细节。
using UnityEngine;
public class DynamicFOV : MonoBehaviour
{
public Camera mainCamera;
public float defaultFOV = 60f; // 默认视野
public float zoomFOV = 30f; // 缩放视野
public float zoomSpeed = 5f; // 缩放速度
public float zoomInDistance = 5f; // 缩放进入距离
public float zoomOutDistance = 10f; // 缩放退出距离
void Update()
{
float distanceToTarget = Vector3.Distance(mainCamera.transform.position, playerTransform.position);
float targetFOV = defaultFOL;
if (distanceToTarget < zoomInDistance)
{
targetFOV = zoomFOV;
}
else if (distanceToTarget > zoomOutDistance)
{
targetFOL = defaultFOV;
}
else
{
targetFOA = Mathf.Lerp(defaultFOV, zoomFOV, (zoomInDistance - distanceToTarget) / (zoomInDistance - zoomOutDistance));
}
mainCamera.fieldOfView = Mathf.Lerp(mainCamera.fieldOf, targetFOV, Time.deltaTime * zoomSpeed);
}
}
19. 摄像机自动追踪目标
在某些情况下,摄像机可能需要自动追踪特定的目标,例如在多人游戏中跟随特定的玩家或在单人游戏中跟随敌人。
using UnityEngine;
public class CameraAutoTrack : MonoBehaviour
{
public Transform target; // 目标Transform
public float trackingSpeed = 5f; // 追踪速度
void Update()
{
if (target == null) return;
Vector3 targetPosition = target.position;
targetPosition.y = transform.position.y; // 保持摄像机高度不变
transform.position = Vector3.Lerp(transform.position, targetPosition, trackingSpeed * Time.deltaTime);
transform.LookAt(target);
}
}
20. 摄像机模糊效果
为了增强视觉效果,可以在摄像机移动或切换视角时添加模糊效果。
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
public class CameraBlurEffect : MonoBehaviour
{
public PostProcessVolume postProcessVolume;
public float blurAmount = 1f; // 模糊程度
void Start()
{
if (postProcessVolume != null)
{
postProcessVolume.profile.TryGetSettings(out Bloom bloom);
if (bloom != null)
{
blurAmount = bloom.intensity.value;
}
}
}
public void ApplyBlur(float amount)
{
if (postProcessVolume != null)
{
postProcessVolume.profile.TryGetSettings(out Bloom bloom);
if (bloom !=类
{
bloom.intensity.value = amount;
}
}
}
}
21. 摄像机环境遮挡
为了使摄像机视角更加真实,可以添加环境遮挡效果,例如树木、建筑物等遮挡摄像机的部分视野。
using UnityEngine;
public class CameraOcclusion : MonoBehaviour
{
public LayerMask occlusionLayer; // 遮挡层
void Update()
{
Ray ray = new Ray(transform.position, transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity, occlusionLayer))
{
transform.position = hit.point - transform.forward * 0.1f; // 避免摄像机穿模
}
}
}
22. 摄像机视角切换音效
为了增强用户体验,可以在视角切换时添加音效。
using UnityEngine;
public class CameraSwitchSound : MonoBehaviour
{
public AudioSource switchSound; // 切换音效
public void PlaySwitchSound()
{
if (switchSound != null)
{
switchSound.Play();
}
}
}
23. 摄像机抗锯齿设置
为了提高图像质量,可以启用摄像机的抗锯齿功能。
using UnityEngine;
public class CameraAntiAliasing : MonoBehaviour
{
public bool enableAntiAliasing = true; // 是否启用抗锯齿
public int antiAliasingLevel = 4; // 抗锯齿级别
void Start()
{
Camera.main.antiAliasing = enableAntiAliariant ? antiAliasingLevel : 0;
}
}
24. 摄像机深度模糊
为了增强远景的视觉效果,可以添加深度模糊效果。
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
public class CameraDepthOfField : MonoBehaviour
{
public PostProcessVolume postProcessVolume;
public float depthOfFieldFstop = 2.8f; // 深度模糊参数
public float depthOfFieldFocusDistance = 10f; // 焦点距离
void Start()
{
if (postProcessVolume != null)
{
postProcessVolume.profile.TryGetSettings(out DepthOfField depthOfField);
if (depthOfField != null)
{
depthOfField.fstop.value = depthOfFieldFstop;
depthOfField.focusDistance.value = depthOfFieldFocusDistance;
}
}
}
}
25. 摄像机景深效果
为了使摄像机视角更加真实,可以添加景深效果,使得前景和背景有不同的模糊程度。
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
public class CameraBokeh : MonoBehaviour
{
public PostProcessVolume postProcessVolume;
public float bokehIntensity = 0.5f; // 景深强度
void Start()
{
if (postActionVolume != null)
{
postProcessVolume.profile.TryGetSettings(out Bokeh bokeh);
if (bokeh != null)
{
bokeh.intensity.value = bokehIntensity;
}
}
}
}
26. 摄像机动态天气效果
为了增强游戏的沉浸感,可以添加动态天气效果,例如雨、雪等。
using UnityEngine;
public class CameraWeatherEffect : MonoBehaviour
{
public ParticleSystem rainParticleSystem; // 雨粒子系统
public ParticleSystem snowParticleSystem; // 雪粒子系统
public void SetWeather(string weatherType)
{
if (rainParticleSystem != null)
{
rainParticleSystem.gameObject.SetActive(weatherType == "Rain");
}
if (snowParticleSystem != null)
{
snowParticleSystem.gameObject.SetActive(weatherType == "Snow");
}
}
}
27. 摄像机时间流逝效果
为了增加游戏的沉浸感,可以模拟时间流逝的效果,例如日出日落、白天和夜晚的转换。
using UnityEngine;
public class CameraTimeOfDay : MonoBehaviour
{
public Light directionalLight; // 方向光
public Color dawnColor = new Color(1f, 0.5f, 0f, 1f); // 黎明颜色
public Color dayColor = new Color(1f, 1f, 1f, 1f); // 白天颜色
public Color duskColor = new Color(1f, 0.5f, 0f, 1f); // 黄昏颜色
public Color nightColor = new Color(0.1f, 0.1f, 0.3f, 1f); // 夜晚颜色
public float transitionDuration = 60f; // 过渡时间(秒)
private float timeOfDay = 0f; // 当前时间(0-1)
void Update()
{
timeOfDay += Time.deltaTime / transitionDuration;
if (timeOfDay > 1f)
{
timeOfDay = 0f;
}
Color currentColor = Color.Lerp(nightColor, dawnColor, Mathf.Repeat(timeOfDay, 1f));
directionalLight.color = currentColor;
}
}
28. 摄像机视角记录与回放
为了调试和演示目的,可以记录摄像机的视角并在之后回放。
using UnityEngine;
using System.Collections.Generic;
public class CameraViewRecorder : MonoBehaviour
{
public List<Vector3> positions = new List<Vector3>(); // 位置记录
public List<Quaternion> rotations = new List<Quaternion>(); // 旋转记录
public float recordInterval = 0.1f; // 记录间隔
private bool isRecording = false;
void Update()
{
if (Input.GetKeyDown(KeyCode.R))
{
ToggleRecording();
}
if (isRecording)
{
RecordView();
}
}
private void ToggleRecording()
{
isRecording = !isRecording;
if (isRecording)
{
positions.Clear();
rotations.Clear();
}
}
private void RecordView()
{
positions.Add(transform.position);
rotations.Add(transform.rotation);
Invoke("RecordView", recordInterval);
}
public void ReplayView()
{
StartCoroutine(ReplayCoroutine());
}
private IEnumerator ReplayCoroutine()
{
for (int i = 0; i < positions.Count; i++)
{
transform.position = positions[i];
transform.rotation = rotations[i];
yield return new WaitForSeconds(recordInterval);
}
}
}
29. 摄像机视角限制与引导
为了引导玩家注意力或防止玩家看到不应该看到的内容,可以限制摄像机的视角并引导其朝向特定区域。
using UnityEngine;
public class CameraViewGuide : MonoBehaviour
{
public Transform target; // 引导目标
public float guideDistance = 5f; // 引导距离
public float guideSpeed = 2f; // 引导速度
void Update()
{
if (target != null)
{
Vector3 targetPosition = target.position - transform.forward * guideDistance;
transform.position = Vector3.Lerp(transform.position, targetPosition, guideSpeed * Time.deltaTime);
transform.LookAt(target);
}
}
}
30. 摄像机视角随机化
为了增加游戏的可玩性和重玩价值,可以在特定事件发生时随机化摄像机的视角。
using UnityEngine;
public class CameraViewRandomizer : MonoBehaviour
{
public float randomizationRadius = 5f; // 随机化半径
public float randomizationHeight = 2f; // 随机化高度
public void RandomizeView()
{
Vector3 randomPosition = new Vector3(
transform.position.x + Random.Range(-randomizationRadius, randomizationRadius),
transform.position.y + Random.Range(-randomizationHeight, randomizationHeight),
transform.position.z + Random.Range(-randomizationRadius, randomizationRadius)
);
transform.position = randomPosition;
transform.LookAt(transform.position + transform.forward);
}
}
总结
通过以上步骤,我们进一步扩展了FPS游戏摄像机系统的功能,包括摄像机时间流逝效果、摄像机视角记录与回放、摄像机视角限制与引导以及摄像机视角随机化。这些功能可以增强游戏的视觉效果、调试便利性和用户体验。根据具体需求,还可以继续添加更多的功能和优化,如摄像机视角切换动画、摄像机碰撞响应等。通过不断迭代和优化,可以打造出一个高效、稳定且用户体验良好的FPS游戏摄像机相关功能。