Unity3D实践1.1:解决摄像机跟随中的视野遮挡问题

 

前文:https://blog.csdn.net/Jaihk662/article/details/87632727(摄像机跟随)

前面已经提到了摄像机跟随角色的多种方法以及优化,但是很多时候摄像机与玩家之间可能会存在一些实体物体,这样子玩家的视野就会被遮挡,还有就是在切换视角的时候,摄像机最好可以平滑移动,这些问题当然是要被解决的……

一、当摄像机被遮挡时,调整摄像机与玩家之间的距离

核心:使用射线

前提条件:障碍物(阻挡物)存在BoxCollider组件,或者存在空气墙,建议前者效果更好

一些重要的API:

  • Physics.RaycastAll(当前目标,方向,射线长度):当前目标和方向都是Vector3向量,API返回一个数组RaycastHit[]
  • Vector3.normalized:向量归一化

代码中有注释

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraCtro : MonoBehaviour
{
    Vector3 dis;
    RaycastHit[] hits;
    private int type;
    private float temp;         //摄像机与人之间的距离参数
    public float myUp;
    public float myForward;
    public float mySpeed;
    private Transform playerTran, myTran;
    void Start()
    {
        type = 1;
        temp = 1;
        playerTran = GameObject.Find("Player").transform;
        myTran = this.GetComponent<Transform>();
        LookPlayer(temp);
    }
    void FixedUpdate()
    {
        CameraAsix();
        if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.Z))           //切换摄像机模式,自由模式:可以随时调节视角,但是人转向不会影响视角方向
            type ^= 1;                                                                              //    固定模式:视角方向始终朝向人正方向
        if (Check(-1.7f) && temp > 0.3f)            //通过判断摄像机看不看的到主角(是否被建筑遮挡),调整摄像机与人的距离
            temp -= 0.017f;
        else if (!Check(1.7f) && temp != 1)             //这些参数根据实际情况要进行调整,调整好之后建议定死,不同游戏可能不一样,切记
            temp += 0.017f;
        LookPlayerInPlay(temp);
    }
    bool Check(float p)         //摄像机与人之间是否存在碰撞体,用来判断视野是否被遮挡
    {
        Vector3 dir = -(playerTran.position - myTran.position).normalized;          //向量归一化,也就是返回单位向量
        hits = Physics.RaycastAll(playerTran.position, dir, Vector3.Distance(playerTran.position, myTran.position)+p);      //+p放抖
        if (hits.Length > 0 && hits[0].collider.name != "Player")
            return true;
        return false;
    }
    void CameraAsix()
    {
        float left, up, forward;
        if (Input.GetMouseButton(1) && type==0)            //通过获得鼠标横纵轴移位,来控制摄像头视角移动,z轴保持不变,只能在自由模式下编辑
        {
            up = Input.GetAxis("Mouse Y");
            left = Input.GetAxis("Mouse X");
            myTran.RotateAround(playerTran.position, playerTran.up, left * mySpeed);
            if ((myTran.position.y >= 2.5 || up < 0) && (myTran.position.y <= 7.5 || up > 0))
                myTran.RotateAround(playerTran.position, myTran.right, -up * mySpeed);
            dis = myTran.position - playerTran.position;
        }
        forward = Camera.main.fieldOfView;
        forward -= Input.GetAxis("Mouse ScrollWheel") * 8;
        forward = Mathf.Clamp(forward, 10, 80);
        Camera.main.fieldOfView = forward;
    }
    void LookPlayer(float p)            //初始化
    {
        myTran.position = playerTran.position;
        myTran.position += Vector3.up * myUp * p;
        myTran.position += playerTran.forward * myForward * p;
        myTran.LookAt(playerTran);
        dis = myTran.position - playerTran.position;
    }
    void LookPlayerInPlay(float p)
    {
        if (type == 0)          //两种摄像机跟随方式
        {
            myTran.position = playerTran.position + dis;
            transform.LookAt(playerTran);
        }
        else
        {
            Vector3 temp;
            temp = playerTran.position;
            temp += Vector3.up * myUp * (p+(1-p)/2);
            temp += playerTran.forward * myForward * p;
            myTran.position = Vector3.Lerp(myTran.position, temp, 0.2f);        //实现摄像机平滑移动,如果仍然出现摄像机抖动情况,可能是因为主角移动方式非刚体移动,解决方法为将该方法放入LastUpdate中
            myTran.LookAt(playerTran);
            dis = myTran.position - playerTran.position;
        }
    }
}

 

二、当摄像机被遮挡时,将遮挡物半透明化

……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值