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的程式吧,以下提供程式碼和註解,只要你有依照上面的教學做好前置步驟的話,下面的腳本就可以直接拿去用啦:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | 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。這個數值是我測試後,覺得還滿意的數值,大家可以依自己的需求修改唷。
最後,執行遊戲看看吧,下面就是執行後的動畫圖啦!
留言
張貼留言