Unity Platformer 2D: Moving Platform
持續前幾篇的練習。
關於平台移動
製作移動式的平台來增加遊戲性,移動式平台可以使用 Animator 去製作,或者是寫 Scripts 來達成。但不管使用哪種一方式,應該都在物理更新時,才重新計算平台的位置。Animator 可以設定 Update Mode
為 Animate Physicals
,則 Scripts 將計算 transform 新位置的程式碼從 Update
改寫到 FixedUpdate
中。
可是,移動式平台沒有辦法這麼簡單就完成,如此這樣做的平台實際遊戲結果,可以參考以下兩個示意動畫,很明顯得平台並不會帶著角色移動。角色站在水平移動平台上,看起來就是懸空在空中。在垂直移動平台下降時,反而角色會一直處於下落 (Landing) 的情況,演出不正確的動畫。
讓平台帶著角色移動
簡單的解決方案是,當角色移動到移動式平台後,使得角色物件變成該平台的子物件 (to child transform)。如果一來可以像以下兩張示意動畫,平台移動時會帶著角色一起移動,上下移動的平台也不會造成角色處於下落的奇怪狀態。
因此需要寫一段程式來達到這功能,當 OnCollisionEnter2D
發生時判斷設定子物件,OnCollisionExit2D
則將角色設定原本的父物件 (original transform parent)。邏輯上有兩條路可以選:
- 在角色物件上加入 Script,當移動到任意平台時,設定角色的 transform parent
- 在每一個移動平台上加入 Script,當角色移動在此平台時,設定角色的 transform parent
最後不選實作方法一的理由為,避免持續切換角色 transform parent 所可能發生的 bugs,且在靜態平台上並不需要設定 transform parent,不必要的 transform parent 修改會造成一些記憶體負擔。
此外若平台物件的 transform lossyScale 在 X 軸上為負值的話 (<0),若角色成為該平台的子物件時,會使得之前為角色移動所做的 Flip()
功能錯誤……。
因此實作方法二,在每一個移動平台物件上加入此組件 (Component):
using UnityEngine;
public class MovingPlatform : MonoBehaviour
{
void OnCollisionEnter2D(Collision2D c)
{
if (c.gameObject.tag == "Player")
{
var target = c.gameObject.transform;
target.SetParent(this.transform);
}
}
void OnCollisionExit2D(Collision2D c)
{
if (c.gameObject.tag == "Player")
{
var target = c.gameObject.transform;
var original = target.GetComponent<TransformState>().OriginalParent;
target.SetParent(original);
}
}
}
判斷 Collision2D.gameObject,若為角色物件,則設定角色物件成為該移動平台的子物件。反之則設定為該角色物件原始的 transform parent。
另外還得在角色物件上加入 TransformState
組件,用來記錄原始角色物件的 transform parent,以提供移動平台 MovingPlatform
重新設定角色 transform parent,其程式碼:
using UnityEngine;
public class TransformState : MonoBehaviour
{
public Transform OriginalParent
{
get;
set;
}
void Awake()
{
this.OriginalParent = this.transform.parent;
}
}
Done, it’s works。
Source Code
Series
- Unity Platformer 2D: Character Movement using Physical
- Unity Platformer 2D: Character Animations
- Unity Platformer 2D: Ragdoll
- Unity Platformer 2D: Moving Platform
沒有留言: