• 【Unity3D】相机


    1 简介

            相机用于渲染游戏对象,每个场景中可以有多个相机,每个相机独立成像,每个成像都是一个图层,最后渲染的图层在最前面显示。

            相机的属性面板如下:

    • Clear Flags:设置清屏颜色,Skybox(天空盒)、Solid Color(纯色)、Depth Only(仅深度,画中画效果)、Don't Clear(不渲染);
    • Background:清屏颜色,当 Clear Flags 为 Skybox 或 Solid Color 时,才有 Background;
    • Culling Mask:剔除遮蔽,选择相机需要绘制的对象层;
    • Projection:投影方式,Perspective(透视投影)、Orthographic(正交投影);
    • Field of View:相机视野范围,默认 60°,视野范围越大,能看到的物体越多,看到的物体越小;
    • Clipping Planes:裁剪平面,视锥体中近平面和远平面的位置;
    • Viewport Rect:视口在屏幕中的位置和大小(相对值),以屏幕左下角为原点;
    • Depth:渲染图层深度,用于设置相机渲染图层的显示顺序;
    • Target Texture:将相机画面存储到一个纹理图片(Texture)中。

    2 应用

            本节将通过实现小地图案例展示相机的应用。

            1)游戏界面

            2)游戏对象层级结构

            3)Transform 组件参数

            1. 相机 Transform 组件参数

    NameTypePositionRotationScaleViewport Rect
    Main CameraCamera(0, 4, -5)(38, 0, 0)(1, 1, 1)(0, 0, 1, 1)
    MinimapCameraCamera(0, 12, 0)(90, 0, 0)(1, 1, 1)(0.8, 0.7, 0.2, 0.3)

            2. 玩家 Transform 组件参数

    NameTypePositionRotationScaleColor/Texture
    PlayerEmpty(0, 0.25, -5)(0, 0, 0)(1, 1, 1)#228439FF
    BottonCube(0, 0, 0)(0, 0, 0)(2, 0.5, 2)#228439FF
    TopCube(0, 0.5, 0)(0, 0, 0)(1, 0.5, 1)#228439FF
    GunCylinder(0, 0, 1.5)(90, 0, 0)(0.2, 1, 0.4)#228439FF
    FirePointEmpty(0, 1.15, 0)(0, 0, 0)(1, 1, 1)——

            补充:Player 游戏对象添加了刚体组件。 

            3. 敌人 Transform 组件参数

    NameTypePositionRotationScaleColor/Texture
    Enemy1Empty(7, 0.25, 1)(0, 120, 0)(1, 1, 1)#F83333FF
    Enemy2Enemy(-1, 0.25, 5)(0, 60, 0)(1, 1, 1)#EA9132FF
    Enemy3Enemy(-5, 0.25, -1)(0, -40, 0)(1, 1, 1)#5DC2F4FF

            说明:Enemy1~Enemy3 都是由 Player copy 而来。

            4. 地面和炮弹 Transform 组件参数

    NameTypePositionRotationScaleColor/Texture
    PlanePlane(0, 0, 0)(0, 0, 0)(10, 10, 10)GrassRockyAlbedo
    BulletSphere(0, 0.5, -5)(0, 0, 0)(0.3, 0.3, 0.3)#228439FF

            补充:炮弹作为预设体拖拽到 Assets/Resources/Prefabs 目录下,并且添加了刚体组件。

            4)脚本组件

            MainCameraController.cs

    1. using UnityEngine;
    2. public class MainCameraController : MonoBehaviour {
    3. private Transform player; // 玩家
    4. private Vector3 relaPlayerPos; // 相机在玩家坐标系中的位置
    5. private float targetDistance = 15f; // 相机看向玩家前方的位置
    6. private void Start() {
    7. relaPlayerPos = new Vector3(0, 4, -8);
    8. player = GameObject.Find("Player/Top").transform;
    9. }
    10. private void LateUpdate() {
    11. CompCameraPos();
    12. }
    13. private void CompCameraPos() { // 计算相机坐标
    14. Vector3 target = player.position + player.forward * targetDistance;
    15. transform.position = transformVecter(relaPlayerPos, player.position, player.right, player.up, player.forward);
    16. transform.rotation = Quaternion.LookRotation(target - transform.position);
    17. }
    18. // 求以origin为原点, locX, locY, locZ 为坐标轴的本地坐标系中的向量 vec 在世界坐标系中对应的向量
    19. private Vector3 transformVecter(Vector3 vec, Vector3 origin, Vector3 locX, Vector3 locY, Vector3 locZ) {
    20. return vec.x * locX + vec.y * locY + vec.z * locZ + origin;
    21. }
    22. }

            说明: CameraController 脚本组件挂在 MainCamera 游戏对象上。 

            MinmapCameraController.cs

    1. using UnityEngine;
    2. public class MinimapController : MonoBehaviour {
    3. private Transform player; // 玩家
    4. private float height = 12; // 相机离地面的高度
    5. private bool isFullscreen = false; // 小地图相机是否全屏
    6. private Rect minViewport; // 小地图视口位置和大小(相对值)
    7. private Rect FullViewport; // 全屏时视口位置和大小(相对值)
    8. private void Start() {
    9. player = GameObject.Find("Player/Top").transform;
    10. minViewport = GetComponent().rect;
    11. FullViewport = new Rect(0, 0, 1, 1);
    12. }
    13. private void Update() {
    14. if (Input.GetMouseButtonDown(0) && IsClickMinimap()) {
    15. if (isFullscreen) {
    16. GetComponent().rect = minViewport;
    17. } else {
    18. GetComponent().rect = FullViewport;
    19. }
    20. isFullscreen = !isFullscreen;
    21. }
    22. }
    23. private void LateUpdate() {
    24. Vector3 pos = player.position;
    25. transform.position = new Vector3(pos.x, height, pos.z);
    26. }
    27. public bool IsClickMinimap() { // 是否单击到小地图区域
    28. Vector3 pos = Input.mousePosition;
    29. if (isFullscreen) {
    30. return true;
    31. }
    32. if (pos.x / Screen.width > minViewport.xMin && pos.y / Screen.height > minViewport.yMin) {
    33. return true;
    34. }
    35. return false;
    36. }
    37. }

            说明: MinimapController 脚本组件挂在 MinimapCamera 游戏对象上。 

            PlayerController.cs

    1. using UnityEngine;
    2. public class PlayerController : MonoBehaviour {
    3. private MinimapController minimapController; // 小地图控制器
    4. private Transform firePoint; // 开火点
    5. private GameObject bulletPrefab; // 炮弹预设体
    6. private float tankMoveSpeed = 4f; // 坦克移动速度
    7. private float tankRotateSpeed = 2f; // 坦克转向速度
    8. private Vector3 predownMousePoint; // 鼠标按下时的位置
    9. private Vector3 currMousePoint; // 当前鼠标位置
    10. private float fireWaitTime = float.MaxValue; // 距离上次开火已等待的时间
    11. private float bulletCoolTime = 0.15f; // 炮弹冷却时间
    12. private void Start() {
    13. minimapController = GameObject.Find("MinimapCamera").GetComponent();
    14. firePoint = transform.Find("Top/Gun/FirePoint");
    15. bulletPrefab = (GameObject) Resources.Load("Prefabs/Bullet");
    16. }
    17. private void Update() {
    18. Move();
    19. Rotate();
    20. Fire();
    21. }
    22. private void Move() { // 坦克移动
    23. float hor = Input.GetAxis("Horizontal");
    24. float ver = Input.GetAxis("Vertical");
    25. if (Mathf.Abs(hor) > float.Epsilon || Mathf.Abs(ver) > float.Epsilon) {
    26. Vector3 vec = transform.forward * ver + transform.right * hor;
    27. GetComponent().velocity = vec * tankMoveSpeed;
    28. Vector3 dire = new Vector3(hor, ver, 0);
    29. dire = dire.normalized * Mathf.Min(dire.magnitude, 1);
    30. }
    31. }
    32. private void Rotate() { // 坦克旋转
    33. if (Input.GetMouseButtonDown(1)) {
    34. predownMousePoint = Input.mousePosition;
    35. } else if (Input.GetMouseButton(1)) {
    36. currMousePoint = Input.mousePosition;
    37. Vector3 vec = currMousePoint - predownMousePoint;
    38. GetComponent().angularVelocity = Vector3.up * tankRotateSpeed * vec.x;
    39. predownMousePoint = currMousePoint;
    40. }
    41. }
    42. private void Fire() { // 坦克开炮
    43. fireWaitTime += Time.deltaTime;
    44. if (Input.GetMouseButtonDown(0) && !minimapController.IsClickMinimap() || Input.GetKeyDown(KeyCode.Space)) {
    45. if (fireWaitTime > bulletCoolTime) {
    46. BulletInfo bulletInfo = new BulletInfo("PlayerBullet", Color.red, transform.forward, 10f, 15f);
    47. GameObject bullet = Instantiate(bulletPrefab, firePoint.position, Quaternion.identity);
    48. bullet.AddComponent().SetBulletInfo(bulletInfo);
    49. fireWaitTime = 0f;
    50. }
    51. }
    52. }
    53. }

            说明: PlayerController 脚本组件挂在 Player 游戏对象上。  

            BulletController.cs

    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. public class BulletController : MonoBehaviour {
    4. private BulletInfo bulletInfo; // 炮弹信息
    5. private void Start () {
    6. gameObject.name = bulletInfo.name;
    7. GetComponent().material.color = bulletInfo.color;
    8. float lifeTime = bulletInfo.fireRange / bulletInfo.speed; // 存活时间
    9. Destroy(gameObject, lifeTime);
    10. }
    11. private void Update () {
    12. transform.GetComponent().velocity = bulletInfo.flyDir * bulletInfo.speed;
    13. }
    14. public void SetBulletInfo(BulletInfo bulletInfo) {
    15. this.bulletInfo = bulletInfo;
    16. }
    17. }

            说明:BulletController 脚本组件挂在 Bullet 游戏对象上(代码里动态添加)。   

            BulletInfo.cs

    1. using UnityEngine;
    2. public class BulletInfo {
    3. public string name; // 炮弹名
    4. public Color color; // 炮弹颜色
    5. public Vector3 flyDir; // 炮弹飞出方向
    6. public float speed; // 炮弹飞行速度
    7. public float fireRange; // 炮弹射程
    8. public BulletInfo(string name, Color color, Vector3 flyDir, float speed, float fireRange) {
    9. this.name = name;
    10. this.color = color;
    11. this.flyDir = flyDir;
    12. this.speed = speed;
    13. this.fireRange = fireRange;
    14. }
    15. }
    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

            5)运行效果

  • 相关阅读:
    自定义springboot starter,你学废了吗
    2023.9.18 网络层 IP 协议详解
    【C#项目】使用百度ai人脸库实现人脸识别
    RBAC-基于角色的访问控制
    【编程题】最小农田浇水费用
    C++ 不知树系列之认识二叉树(顺序、链表存储的实现)
    uni-app 之 NoticeBar 滚动通知,横向滚动,竖/纵向滚动
    隐私协议及人脸协议
    学历不高、起点低的人,如何逆袭人生?
    辅助驾驶功能开发-功能规范篇(27)-3-导航式巡航辅助NCA华为
  • 原文地址:https://blog.csdn.net/m0_37602827/article/details/126078998