Unity关于摄像机旋转跟随问题以及视线被挡透明化处理

在3D游戏开发的过程中,第三人称的摄像机是不可逃避的问题。

1.我先献上摄像机缩放,跟随,右键调节角度的代码:
主要是利用差值计算来改变位置,很简单,没什么可说的。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LookAtPlayer : MonoBehaviour {

    private GameObject target;

    private Vector3 offset;
    
	void Start () {
        target = GameObject.FindGameObjectWithTag("Player");
        offset = target.transform.position - this.transform.position;
	}

    void LateUpdate()
    {
        
        this.transform.position = target.transform.position - offset;

        Rotate();
        Scale(); 
    }

    //缩放
    private void Scale()
    {
        float dis = offset.magnitude;
        dis += Input.GetAxis("Mouse ScrollWheel") * 5;
       
        if (dis < 1.5f || dis > 5)
        {
            return;
        }
        offset = offset.normalized * dis;
    }
    //左右上下移动
    private void Rotate()
    {
        if (Input.GetMouseButton(0))
        {
            Vector3 pos = transform.position;
            Vector3 rot = transform.eulerAngles;

            //围绕原点旋转,也可以将Vector3.zero改为 target.position,就是围绕观察对象旋转
            transform.RotateAround(target.transform.position, Vector3.up, Input.GetAxis("Mouse X") * 10);
          //  transform.RotateAround(target.transform.position, Vector3.left, Input.GetAxis("Mouse Y") * 10);
            float x = transform.eulerAngles.x;
      //      float y = transform.eulerAngles.y;
            Debug.Log("x=" + x);
//Debug.Log("y=" + y);
            //控制移动范围
            if (x < 20 || x > 45)
            {
                transform.position = pos;
                transform.eulerAngles = rot;
            }
            //  更新相对差值 
            offset = target.transform.position - this.transform.position;
        }
    }
}

2.献上视线受阻透明化处理的代码

基本原理就是从摄像机发出射线到主角或相反方向,射线碰撞到的gameObject组,改变其材质颜色的透明度。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraHandle : MonoBehaviour {

	private Transform player_Transform;//玩家角色
    private GameObject Player;
	private List<GameObject> collideredObjects;//本次射线hit到的GameObject
	private List<GameObject> bufferOfCollideredObjects;//上次射线hit到的GameObject
	
	void Start () {
		collideredObjects=new List<GameObject>();
		bufferOfCollideredObjects=new List<GameObject>();
        Player = GameObject.FindGameObjectWithTag("Player");
	}
	
	// Update is called once per frame
	void Update () {

		bufferOfCollideredObjects.Clear();
		for(int temp=0;temp<collideredObjects.Count; temp++)
		{
			bufferOfCollideredObjects.Add(collideredObjects[temp]);//得到上次的
		}
		collideredObjects.Clear();


        //发射射线
        player_Transform = Player.transform;
		Vector3 dir = (transform.position - player_Transform.position).normalized;
		RaycastHit[] hits;
		hits = Physics.RaycastAll(player_Transform.position, dir, Vector3.Distance(player_Transform.position,transform.position));
		Debug.DrawLine(player_Transform.position, transform.position, Color.red);//让其显示以便观测
		
		for(int i=0;i<hits.Length;i++)
		{
			if(hits[i].collider.gameObject.tag!="Player")
			{

				collideredObjects.Add(hits[i].collider.gameObject);//得到现在的
                
                 SetMaterialsColor(collideredObjects[i].GetComponent<Renderer>(),true);
               
            }
        }
        //上次与本次对比,本次还存在的物体则赋值为null
        for (int i = 0; i < bufferOfCollideredObjects.Count; i++)
        {          
            for (int j = 0; j < collideredObjects.Count; j++)
            {
                if (collideredObjects[j] != null)
                {                 
                    if (bufferOfCollideredObjects[i].name == collideredObjects[j].name)
                    {                       
                        bufferOfCollideredObjects[i] = null;
                        break;
                    }
                }
            }
        }
        //把上次的还原,这次的透明
        for (int i = 0; i < bufferOfCollideredObjects.Count; i++)
        {
            if (bufferOfCollideredObjects != null)
            {
                print(bufferOfCollideredObjects[i].name);
                SetMaterialsColor(bufferOfCollideredObjects[i].GetComponent<Renderer>(),false);
            }
            
        }
        
    }
	
	//是否搞透明
	void SetMaterialsColor(Renderer r,bool isClear)
	{
		if(isClear)
		{
			int materialsNumber = r.sharedMaterials.Length;
			for (int i = 0; i < materialsNumber; i++)
			{
                Color _color = r.materials[i].color;
                _color.a = 0.6f;
                r.materials[i].SetColor("_Color", _color);

            }
        }
		else
		{
			int materialsNumber = r.sharedMaterials.Length;
			for (int i = 0; i < materialsNumber; i++)
			{
                Color _color = r.materials[i].color;
                _color.a = 1.0f;
                r.materials[i].SetColor("_Color", _color);

            }
        }
	}
   
}

注意的是:如果本次遮挡物中存在上次遮挡物,则置为空,否则会存在闪烁问题。

猜你喜欢

转载自blog.csdn.net/weixin_42927264/article/details/88096593