unity3d 攝像機跟隨角色時被物體遮擋解決方案


參考文章:http://www.xuanyusong.com/archives/1991

 

在看此文章時請先看上面的參考文章

 

看完以上文章后,你也許會想人家都已經給出所有代碼了,你還寫個毛啊

別急,現在進入主題

 

在我的項目中,我采用的是物體遮擋作半透明處理,如果按照上述文章中的思路來寫代碼的話,那么結果就是當多個物體遮擋角色時,只有第一個物體會半透明,如圖:

角色被牆和屋頂遮擋住了,但是可以清楚的看見左下角的牆呈半透明狀態,而屋頂依舊不透明

 

為了解決這個問題,我們不采用上述文章中的 physics.Linecast,在這里我們需要用到 Physics.RaycastAll;使用方法詳見聖典

 

ok,現在我們開始敲代碼

 

首先 ,我們引入命名空間 System.Collections.Generic,然后在聲明三個需要用到的變量

using System.Collections.Generic;//引入命名空間

public class MyCamera1 : MonoBehaviour
{
    //觀察目標
    public Transform Target;

    //上次碰撞到的物體
    private List<GameObject> lastColliderObject;

    //本次碰撞到的物體
    private List<GameObject> colliderObject;
}

 

 

我們需要發射一條射線,這條射線從角色當前位置發射置攝像機的方向

 1         /*射線可以從頭部起始*/
 2 
 3         //這里是計算射線的方向,從主角發射方向是射線機方向
 4         Vector3 aim = Target.position;
 5         //得到方向
 6         Vector3 ve = (Target.position - transform.position).normalized;
 7         float an = transform.eulerAngles.y;
 8         aim -= an * ve;
 9 
10         //在場景視圖中可以看到這條射線
11         //Debug.DrawLine(target.position, aim, Color.red);
12 
13         RaycastHit[] hit;
14         hit = Physics.RaycastAll(Target.position, aim, 100f);//起始位置、方向、距離

 

射線發送完畢后,我們獲取發送射線時碰撞到的所有物體,並且添加進本次碰撞到的物體(colliderObject)變量中

因為我的地圖、護欄碰撞(不可見)、地面碰撞(不可見)是三個模型,也就是說地圖本身是沒有任何碰撞的

所以當碰撞到的物體名為護欄或地面時,就不修改其透明度,因為他本身就不可見

這里我偷懶了,直接判斷物體名稱,可自行改為判斷物體 tag

當視角旋轉的時候,射線有時候會碰撞到角色,所以,我們獲取 tag 判斷是否碰撞的物體為角色

 1         //將 colliderObject 中所有的值添加進 lastColliderObject
 2         for (int i = 0; i < colliderObject.Count; i++)
 3             lastColliderObject.Add(colliderObject[i]);
 4 
 5         colliderObject.Clear();//清空本次碰撞到的所有物體
 6         for (int i = 0; i < hit.Length; i++)//獲取碰撞到的所有物體
 7         {
 8             if (hit[i].collider.gameObject.name != "Editable Poly 1"//護欄
 9                 && hit[i].collider.gameObject.name != "Editable Poly"//地面
10                 && hit[i].collider.gameObject.tag != "Player")//角色
11             {
12                 //Debug.Log(hit[i].collider.gameObject.name);
13                 colliderObject.Add(hit[i].collider.gameObject);
14                 SetMaterialsColor(hit[i].collider.gameObject.renderer, 0.4f);//置當前物體材質透明度
15             }
16         }

 

當獲取到所碰撞到的所有物體后,我們要修改他的材質透明度,有些物體有很多材質,不知道怎么解決的請看我下面這個方法:

 1     /// 置物體所有材質球顏色 <summary>
 2     /// 置物體所有材質球顏色
 3     /// </summary>
 4     /// <param name="_renderer">材質</param>
 5     /// <param name="Transpa">透明度</param>
 6     private void SetMaterialsColor(Renderer _renderer, float Transpa)
 7     {
 8         //獲取當前物體材質球數量
 9         int materialsNumber = _renderer.sharedMaterials.Length;
10         for (int i = 0; i < materialsNumber; i++)
11         {
12             //獲取當前材質球顏色
13             Color color = _renderer.materials[i].color;
14 
15             //設置透明度  取值范圍:0~1;  0 = 完全透明
16             color.a = Transpa;
17 
18             //置當前材質球顏色
19             _renderer.materials[i].SetColor("_Color", color);
20         }
21     }

 

如果本次碰撞到的物體存在於上個物體,那么則說明當前物體還處於遮擋角色狀態,所以我們賦值為null

 1         //上次與本次對比,本次還存在的物體則賦值為null
 2         for (int i = 0; i < lastColliderObject.Count; i++)
 3         {
 4             for (int ii = 0; ii < colliderObject.Count; ii++)
 5             {
 6                 if (colliderObject[ii] != null)
 7                 {
 8                     if (lastColliderObject[i] == colliderObject[ii])
 9                     {
10                         lastColliderObject[i] = null;
11                         break;
12                     }
13                 }
14             }
15         }


還處於遮擋狀態的物體已被賦值為null,那么剩下的物體就是沒有處於遮擋狀態的,所以我們要重置該物體材質為不透明

1 //當值為null時則可判斷當前物體還處於遮擋狀態
2         //值不為null時則可恢復默認狀態(不透明)
3         for (int i = 0; i < lastColliderObject.Count; i++)
4         {
5             if (lastColliderObject[i] != null)
6                 SetMaterialsColor(lastColliderObject[i].renderer, 1f);//恢復上次物體材質透明度
7         }

 

好了,所有代碼已完成,我們看一下運行結果

未遮擋時:

 

遮擋時:

 

怎么樣,有木有感覺很酷炫呢,哈哈哈

 

最后,附上完整代碼鏈接:http://pan.baidu.com/s/1gdGLwiv 密碼:pbrd

 

原文鏈接:http://www.cnblogs.com/shenggege/p/4113316.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM