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);

            }
        }
	}
   
}

注意的是:如果本次遮擋物中存在上次遮擋物,則置爲空,否則會存在閃爍問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章