利用射線檢測實現光束照射啟用功能——2024TapTap聚光燈GameJam
簡介
專案主題:Light
專案名稱:《OneLastLight》(2D平臺跳躍解密)
我的職責:gamepaly程式,負責實現遊戲玩法功能
簡述:
策劃的設計為角色控制燈光,燈光照射到平臺,可以使平臺顯現實體,玩家可以藉助平臺解密。
燈光可以被不是平臺的實體阻擋,而且燈光不能被平臺阻擋,可以穿透平臺。
角色有兩種形態的燈光,光圈會以玩家為中心形成圓形照亮區域,光束會從玩家開始射出一個扇形區域跟隨滑鼠探測。
光束有紅、藍、白三種顏色,光圈有紅、藍兩種顏色。白色可以使所有平臺顯現實體,紅、藍光只能令相反顏色的平臺顯現實體,可以使相同顏色的平臺隱藏。
這裡記錄我實現這個玩法所使用的解決辦法。
正文
構想
採用射線檢測方法,從角色的位置開始,每次讓射線移動一個角度,設定角度限制,使射線檢測形成扇形區域,而光圈模式只要將角度限制改為360度
普通的 Physics2D.Raycast只能檢測射線碰到的第一個實體,不可穿透,所以這次選擇Physics2D.RaycastAll方法,此方法可以返回一個射線上的所有實體從近到遠的陣列.(Physics2D-RaycastAll - Unity 指令碼 API
實現
- 建立角色Player,建立兩個空物體LightBeam、LightCircle作為Player的子物體
- 新建兩個指令碼:LightBeamController、LightCircleController,分別掛載在:LightBeam、和LightCircle上,指令碼內容為構想中RayCastAll方法的實現使用,先獲取射線上的所有物體,然後遍歷,呼叫物體上指令碼中的啟用程式碼
LightBeamController(LightCircleControl相似):
//此方法用於實現光線啟用平臺、阻擋、穿透
void DrawFieldOfView(){
// 計算最左側方向的向量
// -transform.up看情況設定,最好與LightBeam的旋轉一致
Vector3 forward_down = Quaternion.Euler(0, 0, -(viewAngle / 2f)) * -transform.up * viewRadius;
//在限制角度內建立viewAngleStep條射線,每條射線偏移一定的角度
for (int i = 0; i <= viewAngleStep; i++){
Vector3 v = Quaternion.Euler(0, 0, (viewAngle / viewAngleStep) * i + 180f) * forward_down; // 根據當前角度計算方向向量
Vector3 pos = transform.position + v; // 計算射線終點
// 在Scene中繪製線條(僅在Scene中可見,方便檢視)
Debug.DrawLine(transform.position, pos, Color.red);
// 設定射線檢測射線
Ray2D ray = new Ray2D(transform.position, v);
//射線檢測
RaycastHit2D[] hits =
Physics2D.RaycastAll(ray.origin, v, viewRadius, LayerMask.GetMask("Trigger")); //這裡設定只檢測Trigger層級
//遍歷檢測到的物體
for (int j = 0; j < hits.Length; j++){
RaycastHit2D hitInfo = hits[j];
if (hitInfo.collider != null){
if (hitInfo.collider.CompareTag("BluePlatform") || hitInfo.collider.CompareTag("RedPlatform")){
//檢測到為BluePlatform或者RedPlatform執行平臺上的顯現操作
}
}
}
}
}
}
- 射線穿透做完了,現在射線可以穿透所有的物體,為其新增阻擋功能,非常簡單。已知Physice2D.RayCastAll方法是將射線碰撞到的所有物體按從近到遠的順序排列在陣列中。那麼在遍歷時遇到不是啟用平臺的物體直接跳出此次遍歷即可,即在判斷平臺的條件句後加上break即可
if (hitInfo.collider.CompareTag("BluePlatform") || hitInfo.collider.CompareTag("RedPlatform")){
//檢測到為BluePlatform或者RedPlatform執行平臺上的顯現操作
}
else break;
}
- 製作平臺,建立一個空物體叫platform,建立一個矩形叫Entity,給它們掛載碰撞體,將platform的碰撞體設定為trigger,layer層級設定為Trigger(我設定的射線只能檢測Trigger層的物體),tag設定為BluePlatform或RedPlatform,最後將Entity作為platform的子物體
- 建立指令碼PlatformController,在指令碼中新增BoxAppear()和BoxDisappear()方法,用來控制實體的啟用和失活
public void BoxDisappear()
{
_entity.SetActive(false);
}
public void BoxAppear()
{
_entity.SetActive(true);
timer=0;//將計時器置為0
}
- 在update中新增計時器,在燈光照射時不斷將計時器置為0,燈光不照射時計時器開始累計時間,到達一定時長後將平臺實體自動失活。
private void Update()
{
timer += Time.deltaTime;
if (timer > canSeeTime)
{
BoxDisappear();
}
- 最後在LightBeamController和LightCircleController中加入燈光顏色判斷
if (hitInfo.collider.CompareTag("BluePlatform")||
hitInfo.collider.CompareTag("RedPlatform")){
switch (_colorID){
case 0:
if (hitInfo.collider.CompareTag("BluePlatform"))
hitInfo.collider.gameObject.GetComponent<PlatFormController>().BoxAppear();
if (hitInfo.collider.CompareTag("RedPlatform"))
hitInfo.collider.gameObject.GetComponent<PlatFormController>().BoxDisAppear();
break;
case 1:
if (hitInfo.collider.CompareTag("BluePlatform"))
hitInfo.collider.gameObject.GetComponent<PlatFormController>().BoxDisAppear();
if (hitInfo.collider.CompareTag("RedPlatform"))
hitInfo.collider.gameObject.GetComponent<PlatFormController>().BoxAppear();
break;
case 2:
if (hitInfo.collider.CompareTag("BluePlatform"))
hitInfo.collider.gameObject.GetComponent<PlatFormController>().BoxAppear();
if (hitInfo.collider.CompareTag("RedPlatform"))
hitInfo.collider.gameObject.GetComponent<PlatFormController>().BoxAppear();
break;
}
}
else break;
}
將射線檢測的方法放在UpDate中呼叫,完成!
其它
光束與光圈模式的切換隻需啟用對應物件。
光束跟隨滑鼠,只需要令遊戲物件LightBeam跟隨滑鼠旋轉即可。
專案整體影片演示
專案程式碼GitHub連結(由於專案後面要配合Shader實現視覺效果,原始碼可能與上文略有差別)
總結
這算是我第一次參加GameJam,組隊是從官方組隊群中組的,比賽過程中學到了很多東西,但與他人的團隊協作體驗比較差。
隊伍有9個人,兩程式兩美術5策劃,策劃基本都是完全沒有經驗,每次開會固定5人:兩策劃,兩程式,主美。其它三人完全沒有交流過,也有可能他們與開會來的兩策劃是同一個學校的,他們會線下交流。但是他們交流的內容不會即時的傳遞給我們,有時候就會發現他們又策劃了什麼新功能,但是沒有告訴程式和美術。
策劃是完全沒有經驗的,其中一個策劃要求我等他寫程式需求,然後按照程式需求開發,結果寫了兩天就寫了五條需求,而且很籠統,約等於沒有寫。關卡體量也過於龐大了,美術有很大壓力。然後21天的gamejam唯一一個測試版本是距離ddl還有兩個小時做出來的,導致遊戲有很多影響體驗的小問題。(我一直催促出測試版測試,但策劃貌似更熱衷於新增新功能)
我也有一些不足的地方,我雖然能夠實現遊戲程式邏輯,但我沒有與他人合作的經驗,不擅長留介面給Shader、UI、音樂音效等。
總的來說開發的過程還是很有意思的,從查詢、設計解決問題的方法到實際解決給了我很大成就感。現在的我依然喜歡玩遊戲,比以前更喜歡開發遊戲了。我會繼續學習,持續進步。