fps游戏摄像机系统代码逻辑架构设计

在设计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游戏摄像机相关功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你一身傲骨怎能输

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值