7-6 Creating A Simple 2D Game For Reinforcement Learning (2)
本章要繼續來建構我們的2D遊戲場景啦!接下來,請先到Sunnlyland/artwork/Environment資料夾底下,找到tileset-sliced檔案,這是一個已經切割好的場景圖檔。
選擇圖片以後,在Inspector選擇Sprite Editor。
接著會開啟編輯視窗,大家可以看到這邊已經切割好每一個小元件了。假設大家自己的素材是沒有切割好的話,就請先切割吧。
然後在tileset-sliced旁有一顆小箭頭,按下去後會展開所有小元件。然後我們將第一個小元件拉進場景吧。
拉進場景以後,再進行複製,可以使用下圖的方式進行排列。另一個更好的選擇,是使用Unity提供的TileMap,這是一個免費提供的工具,但因為我使用的Unity版本2018.1.0的TileMap無法正常使用,所以我才使用比較原始的方式佈置場景。
排列好以後,就會長得如下圖。
接著我又進行了更多的複製與排列,這結構看起來略為複雜。
最後,請在結構最上層的tileset-sliced_0新增一個Box Collider 2D。
player-idle-1新增Box Collider 2 D,以及Rigidbody2D。
然後請自己調整Box Collider 2 D的大小。
場景的Box Collider 2 D也是如此設置。
接著,在Animator中新增一個名為Jump的Boolean參數。
並將Animator如下佈置。
然後記得在Jump新增補間動畫,Samples設為6。如不會操作Animator與Animation的話,可以參考上一篇文章:
7-5 Creating A Simple 2D Game For Reinforcement Learning (1)
https://3dactionrpg.blogspot.com/2018/07/7-5-creating-simple-2d-game-for.html
然後我在Animator中的每一個Transition,都關掉了Has Exit Time,並將Transition Duration(s)設為0。這樣就會快速切換不同的動畫,由於2D動畫的影格變化很急速,跳起來就應該要立即換成跳躍的圖片,並不會像3D動畫那樣需要切換時間。
然後player-idle-1的Rigidbody2D的Constraints要設定Freeze Rotation Z,這樣角色跳躍的時候,才不會因為撞到牆壁的邊邊角角,導致角色倒下來。
接著來撰寫PlayerMovement的程式吧,以下提供程式碼和註解,只要你有依照上面的教學做好前置步驟的話,下面的腳本就可以直接拿去用啦:
using UnityEngine; public class PlayerMovement : MonoBehaviour { [SerializeField] Rigidbody2D myRigidbody2D; [SerializeField] Animator animator; [SerializeField] float speed = 30; [SerializeField] float jumpHeight = 2; bool isGround = false; const int MOVE_STOP = 0; const int MOVE_RIGHT = 1; const int MOVE_LEFT = -1; const int RIGHT_DIRECTION = 0; const int LEFT_DIRECTION = 1; void Update() { // 按下方向鍵左鍵,或右鍵時進行移動,開啟Run動畫 if (Input.GetKey(KeyCode.RightArrow)) { Move(MOVE_RIGHT); ChangeDirection(RIGHT_DIRECTION); SetRunAnimator(true); } else if (Input.GetKey(KeyCode.LeftArrow)) { Move(MOVE_LEFT); ChangeDirection(LEFT_DIRECTION); SetRunAnimator(true); } // 放開方向鍵左鍵或右鍵時關閉Run動畫 else if (Input.GetKeyUp(KeyCode.RightArrow) || Input.GetKeyUp(KeyCode.LeftArrow)) { Move(MOVE_STOP); SetRunAnimator(false); } // 按下Z鍵呼叫Jump方法,開啟Jump動畫 if (Input.GetKey(KeyCode.Z)) { Jump(); SetJumpAnimator(true); } // 當Player回到地面時,關閉Jump動畫 if (isGround) { SetJumpAnimator(false); } } void Jump() { // 當Player不在地面時,不要再設定Velocity if (!isGround) { return; } // 設定Player的Velocity的Y值,即可讓Player跳起 Vector2 velocity = myRigidbody2D.velocity; velocity.y = jumpHeight; myRigidbody2D.velocity = velocity; } void Move(int i) { // 設定Player的Velocity的X值,即可讓Player移動 Vector2 velocity = myRigidbody2D.velocity; velocity.x = i * speed * Time.deltaTime; myRigidbody2D.velocity = velocity; } void ChangeDirection(int i) { // 若i為1則會將Y軸轉向180度,若i為0則會轉回原方向 // 藉此控制角色的轉向 transform.eulerAngles = new Vector3(0, 180 * i, 0); } void SetRunAnimator(bool isMove) { animator.SetBool("Run", isMove); } void SetJumpAnimator(bool isJump) { animator.SetBool("Jump", isJump); } private void OnCollisionStay2D(Collision2D collision) { //若接觸點的法線向量不為上的話,代表並非撞到地板 if (collision.contacts[0].normal != Vector2.up) return; isGround = true; } private void OnCollisionExit2D(Collision2D collision) { isGround = false; } }
將PlayerMovement.cs加入player-idle-1,並拉入Rigidbody2D與Animator,然後Speed設為30,Jump Height設為3.5。這個數值是我測試後,覺得還滿意的數值,大家可以依自己的需求修改唷。
最後,執行遊戲看看吧,下面就是執行後的動畫圖啦!
留言
張貼留言