找回密码
 立即注册
查看: 280|回复: 0

【Unity3D】相机

[复制链接]
发表于 2023-2-27 13:45 | 显示全部楼层 |阅读模式
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:渲染图层深度,用于设置相机渲染图层的显示顺序;

    Rendering Path:渲染路径,用于调整渲染性能(可以在 Stats 里查看性能)

    Target Texture:将相机画面存储到一个纹理图片(RenderTexture)中。

    补充:基于 Target Texture 属性,可以使用 RawImage 显示次相机渲染的 RenderTexture,实现带主题边框的小地图、八倍镜等效果。
2 应用


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

1)游戏界面

2)游戏对象层级结构

3)Transform 组件参数
    相机 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)
    玩家 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 游戏对象添加了刚体组件。
    敌人 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 而来。
    地面和炮弹 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
using UnityEngine; public class MainCameraController : MonoBehaviour {    private Transform player; // 玩家    private Vector3 relaPlayerPos; // 相机在玩家坐标系中的位置    private float targetDistance = 15f; // 相机看向玩家前方的位置     private void Start() {        relaPlayerPos = new Vector3(0, 4, -8);        player = GameObject.Find("Player/Top").transform;    }     private void LateUpdate() {        CompCameraPos();    }     private void CompCameraPos() { // 计算相机坐标        Vector3 target = player.position + player.forward * targetDistance;        transform.position = transformVecter(relaPlayerPos, player.position, player.right, player.up, player.forward);        transform.rotation = Quaternion.LookRotation(target - transform.position);    }     // 求以origin为原点, locX, locY, locZ 为坐标轴的本地坐标系中的向量 vec 在世界坐标系中对应的向量    private Vector3 transformVecter(Vector3 vec, Vector3 origin, Vector3 locX,  Vector3 locY,  Vector3 locZ) {        return vec.x * locX + vec.y * locY + vec.z * locZ + origin;    }}
说明: CameraController 脚本组件挂在 MainCamera 游戏对象上。

MinmapCameraController.cs
using UnityEngine;public class MinimapController : MonoBehaviour {    private Transform player; // 玩家    private float height = 12; // 相机离地面的高度    private bool isFullscreen = false; // 小地图相机是否全屏    private Rect minViewport; // 小地图视口位置和大小(相对值)    private Rect FullViewport; // 全屏时视口位置和大小(相对值)     private void Start() {        player = GameObject.Find("Player/Top").transform;        minViewport = GetComponent<Camera>().rect;        FullViewport = new Rect(0, 0, 1, 1);    }    private void Update() {        if (Input.GetMouseButtonDown(0) && IsClickMinimap()) {            if (isFullscreen) {                GetComponent<Camera>().rect = minViewport;            } else {                GetComponent<Camera>().rect = FullViewport;            }            isFullscreen = !isFullscreen;        }    }     private void LateUpdate() {        Vector3 pos = player.position;        transform.position = new Vector3(pos.x, height, pos.z);    }    public bool IsClickMinimap() { // 是否单击到小地图区域        Vector3 pos = Input.mousePosition;        if (isFullscreen) {            return true;        }        if (pos.x / Screen.width > minViewport.xMin && pos.y / Screen.height > minViewport.yMin) {            return true;        }        return false;    }}
说明: MinimapController 脚本组件挂在 MinimapCamera 游戏对象上。

PlayerController.cs
using UnityEngine;public class PlayerController : MonoBehaviour {    private MinimapController minimapController; // 小地图控制器    private Transform firePoint; // 开火点    private GameObject bulletPrefab; // 炮弹预设体    private float tankMoveSpeed = 4f; // 坦克移动速度    private float tankRotateSpeed = 2f; // 坦克转向速度    private Vector3 predownMousePoint; // 鼠标按下时的位置    private Vector3 currMousePoint; // 当前鼠标位置    private float fireWaitTime = float.MaxValue; // 距离上次开火已等待的时间    private float bulletCoolTime = 0.15f; // 炮弹冷却时间     private void Start() {        minimapController = GameObject.Find("MinimapCamera").GetComponent<MinimapController>();        firePoint = transform.Find("Top/Gun/FirePoint");        bulletPrefab = (GameObject) Resources.Load("Prefabs/Bullet");    }     private void Update() {        Move();        Rotate();        Fire();    }     private void Move() { // 坦克移动        float hor = Input.GetAxis("Horizontal");        float ver = Input.GetAxis("Vertical");        if (Mathf.Abs(hor) > float.Epsilon || Mathf.Abs(ver) > float.Epsilon) {            Vector3 vec = transform.forward * ver + transform.right * hor;            GetComponent<Rigidbody>().velocity = vec * tankMoveSpeed;            Vector3 dire = new Vector3(hor, ver, 0);            dire =  dire.normalized * Mathf.Min(dire.magnitude, 1);        }    }     private void Rotate() { // 坦克旋转        if (Input.GetMouseButtonDown(1)) {            predownMousePoint = Input.mousePosition;        } else if (Input.GetMouseButton(1)) {            currMousePoint = Input.mousePosition;            Vector3 vec = currMousePoint - predownMousePoint;            GetComponent<Rigidbody>().angularVelocity = Vector3.up * tankRotateSpeed * vec.x;            predownMousePoint = currMousePoint;        }    }     private void Fire() { // 坦克开炮        fireWaitTime += Time.deltaTime;        if (Input.GetMouseButtonDown(0) && !minimapController.IsClickMinimap() || Input.GetKeyDown(KeyCode.Space)) {            if (fireWaitTime > bulletCoolTime) {                BulletInfo bulletInfo = new BulletInfo("PlayerBullet", Color.red, transform.forward, 10f, 15f);                GameObject bullet = Instantiate(bulletPrefab, firePoint.position, Quaternion.identity);                bullet.AddComponent<BulletController>().SetBulletInfo(bulletInfo);                fireWaitTime = 0f;            }        }    }}
说明: PlayerController 脚本组件挂在 Player 游戏对象上。

BulletController.cs
using UnityEngine;using UnityEngine.UI;public class BulletController : MonoBehaviour {    private BulletInfo bulletInfo; // 炮弹信息    private void Start () {        gameObject.name = bulletInfo.name;        GetComponent<MeshRenderer>().material.color = bulletInfo.color;        float lifeTime = bulletInfo.fireRange / bulletInfo.speed; // 存活时间        Destroy(gameObject, lifeTime);    }    private void Update () {        transform.GetComponent<Rigidbody>().velocity = bulletInfo.flyDir * bulletInfo.speed;    }    public void SetBulletInfo(BulletInfo bulletInfo) {        this.bulletInfo = bulletInfo;    }}
说明:BulletController 脚本组件挂在 Bullet 游戏对象上(代码里动态添加)。

BulletInfo.cs
using UnityEngine;public class BulletInfo {    public string name; // 炮弹名    public Color color; // 炮弹颜色    public Vector3 flyDir; // 炮弹飞出方向    public float speed; // 炮弹飞行速度    public float fireRange; // 炮弹射程    public BulletInfo(string name, Color color, Vector3 flyDir, float speed, float fireRange) {        this.name = name;        this.color = color;        this.flyDir = flyDir;        this.speed = speed;        this.fireRange = fireRange;    }}
5)运行效果

声明:本文转自【Unity3D】相机

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-6-17 05:54 , Processed in 0.089579 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表