Unity 2D Movement 物體移動案例
導入工程
可通過Unity Asset Store導入或者自行下載導入Sunny Land
繪制地圖
-
制作Tile Palette
通過Window > 2D > Tile Palette調整面板
新建Palette
-
導入素材:將Sunnyland/artwork/Environment/titleset-sliced拖入Tile Palette面板
最后導入效果如圖,如其他畫板功能類似,左鍵單擊(長按)選取,然后繪制。
注:如果導入素材后繪制像素過小,請檢查素材Pixels Per Unit值的大小(本工程為16)
-
開始繪制
在場景中添加TileMap(右鍵2D Object > Tilemap),即可利用Tile palette中的功能在場景中進行繪制。
注:如果有多個Tilemap,可以通過在Tile palette中激活需要操作的TileMap。
在繪制完后我們可通過組件Tilemap Collider 2D快速地添加碰撞盒
前景:草、植物等
ground層:地面等
背景:牆、柱子等(通過改變Transform.Position.Z的值來改變前后關系)
ground層
人物制作
首先簡單地導入Sunnyland\artwork\Sprites\player\idle\player-idle-1.png到場景中
為Player添加剛體及碰撞盒
Character Controller
包含Object受力、速度、狀態判斷的變量
函數:
-
Move(float move, bool crouch, bool jump)
move:橫向移動量
-
Flip() —— 人物轉向
using UnityEngine;
public class CharacterController2D : MonoBehaviour {
[SerializeField] private float m_JumpForce = 400f; // Amount of force added when the player jumps.
[Range(0, 1)] [SerializeField] private float m_CrouchSpeed = .36f; // Amount of maxSpeed applied to crouching movement. 1 = 100%
[Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f; // How much to smooth out the movement
[SerializeField] private bool m_AirControl = false; // Whether or not a player can steer while jumping;
[SerializeField] private LayerMask m_WhatIsGround; // A mask determining what is ground to the character
[SerializeField] private Transform m_GroundCheck; // A position marking where to check if the player is grounded.
[SerializeField] private Transform m_CeilingCheck; // A position marking where to check for ceilings
[SerializeField] private Collider2D m_CrouchDisableCollider; // A collider that will be disabled when crouching
const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded
private bool m_Grounded; // Whether or not the player is grounded.
const float k_CeilingRadius = .2f; // Radius of the overlap circle to determine if the player can stand up
private Rigidbody2D m_Rigidbody2D;
private bool m_FacingRight = true; // For determining which way the player is currently facing.
private Vector3 velocity = Vector3.zero;
private void Awake() {
m_Rigidbody2D = GetComponent<Rigidbody2D>();
}
private void FixedUpdate() {
m_Grounded = false;
// The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
// This can be done using layers instead but Sample Assets will not overwrite your project settings.
Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
for (int i = 0; i < colliders.Length; i++) {
if (colliders[i].gameObject != gameObject)
m_Grounded = true;
}
}
public void Move(float move, bool crouch, bool jump) {
// If crouching, check to see if the character can stand up
if (!crouch) {
// If the character has a ceiling preventing them from standing up, keep them crouching
if (Physics2D.OverlapCircle(m_CeilingCheck.position, k_CeilingRadius, m_WhatIsGround)) {
crouch = true;
}
}
//only control the player if grounded or airControl is turned on
if (m_Grounded || m_AirControl) {
// If crouching
if (crouch) {
// Reduce the speed by the crouchSpeed multiplier
move *= m_CrouchSpeed;
// Disable one of the colliders when crouching
if (m_CrouchDisableCollider != null)
m_CrouchDisableCollider.enabled = false;
} else {
// Enable the collider when not crouching
if (m_CrouchDisableCollider != null)
m_CrouchDisableCollider.enabled = true;
}
// Move the character by finding the target velocity
Vector3 targetVelocity = new Vector2(move * 10f, m_Rigidbody2D.velocity.y);
// And then smoothing it out and applying it to the character
m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref velocity, m_MovementSmoothing);
// If the input is moving the player right and the player is facing left...
if (move > 0 && !m_FacingRight) {
// ... flip the player.
Flip();
}
// Otherwise if the input is moving the player left and the player is facing right...
else if (move < 0 && m_FacingRight) {
// ... flip the player.
Flip();
}
}
// If the player should jump...
if (m_Grounded && jump) {
// Add a vertical force to the player.
m_Grounded = false;
m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
}
}
private void Flip() {
// Switch the way the player is labelled as facing.
m_FacingRight = !m_FacingRight;
// Multiply the player's x local scale by -1.
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
Player Move Controller
Input.GetAxisRaw("Horizontal") —— 獲取橫向移動量,x的正方向移動為1,x的負方向移動-1,站立不動為0
Input.GetButtonDown("Jump") —— 判斷按下"Jump"的指令
Edit > Project Settings > Input Manager設定Input系統
例如:Jump通過space鍵觸發
我們需要添加Crouch判定,觸發爬行行為
using UnityEngine;
public class PlayerMoveController : MonoBehaviour {
private CharacterController2D cc;
private float move = 0f;
private bool jump = false;
private bool crouch = false;
private void Awake() {
cc = GetComponent<CharacterController2D>();
}
// Update is called once per frame
void Update() {
move = Input.GetAxisRaw("Horizontal");
if (Input.GetButtonDown("Jump"))
jump = true;
if (Input.GetButtonDown("Crouch"))
crouch = true;
else if (Input.GetButtonUp("Crouch"))
crouch = false;
}
private void FixedUpdate() {
cc.Move(move, crouch, jump);
jump = false;
}
}
其他設置
- Player腳本相關設置
也可以通過Rigidbody調整物體的重力因素等,如Gravity Scale()、Collision Detection(剛體的碰撞檢測模式)。
-
設置Collider的Material(減少摩擦)
在project面板中右鍵 > Create > Physics Material 2D,將Friction參數設置為0。
拖動該material到collider上。
演示
按住"Crouch"鍵,進入爬行狀態,隱藏頭部碰撞盒