影片中的專案下載(台幣約30元)
https://gumroad.com/l/iLyXq
Unity 2D遊戲角色移動控制 程式篇
用淺顯易懂的方式解說如何實作2D角色移動的控制 包含走路與跳躍
而且能用 Physics2D.Linecast 判定是否在地板上,是的話才能跳躍(也就是不能在空中連跳)
並且附上2D platform Effector 的簡易說明
延伸閱讀:
Unity 5.5 2D Effectors 力場教學:2D平台, 橫向捲軸, 風吹, 瀑布, 漂浮, 黑洞, 爆炸, 輸送帶
http://www.morningfungame.com/2017/01/unity-55-2d-effectors-2d.html
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
Rigidbody2D playerRigidbody2D;
[Header("目前的水平速度")]
public float speedX;
[Header("目前的水平方向")]
public float horizontalDirection;//數值會在 -1~1之間
const string HORIZONTAL = "Horizontal";
[Header("水平推力")]
[Range(0, 150)]
public float xForce;
//目前垂直速度
float speedY;
[Header("最大水平速度")]
public float maxSpeedX;
[Header("垂直向上推力")]
public float yForce;
[Header("感應地板的距離")]
[Range(0, 0.5f)]
public float distance;
[Header("偵測地板的射線起點")]
public Transform groundCheck;
[Header("地面圖層")]
public LayerMask groundLayer;
public bool grounded;
public void ControlSpeed()
{
speedX = playerRigidbody2D.velocity.x;
speedY = playerRigidbody2D.velocity.y;
float newSpeedX = Mathf.Clamp(speedX, -maxSpeedX, maxSpeedX);
playerRigidbody2D.velocity = new Vector2(newSpeedX, speedY);
}
public bool JumpKey
{
get
{
return Input.GetKeyDown(KeyCode.Space);
}
}
void TryJump()
{
if (IsGround && JumpKey)
{
playerRigidbody2D.AddForce(Vector2.up * yForce);
}
}
//在玩家的底部射一條很短的射線 如果射線有打到地板圖層的話 代表正在踩著地板
bool IsGround
{
get
{
Vector2 start = groundCheck.position;
Vector2 end = new Vector2(start.x, start.y - distance);
Debug.DrawLine(start, end, Color.blue);
grounded = Physics2D.Linecast(start, end, groundLayer);
return grounded;
}
}
void Start()
{
playerRigidbody2D = GetComponent<Rigidbody2D>();
}
/// <summary>水平移動</summary>
void MovementX()
{
horizontalDirection = Input.GetAxis(HORIZONTAL);
playerRigidbody2D.AddForce(new Vector2(xForce * horizontalDirection, 0));
}
void Update()
{
MovementX();
ControlSpeed();
TryJump();
//speedX = playerRigidbody2D.velocity.x;
}
}
作者已經移除這則留言。
回覆刪除你是說輸入rig的時候無法跳出Rigibody2D讓你選嗎?這個功能叫做自動完成,這樣的話要關掉visual studio以後再重開。visual studio正在啟動的時候別執行任何操作,不然有時候自動完成的功能會失效
刪除不好意思~我也遇到一樣的狀況,我有照著做關掉Visual Studio以後重開,可是Rigidbody2D還是不會跳出讓我選,而且Rigidbody2D的顏色是白色不是綠色,請問要怎麼做才好呢?謝謝您~
刪除我找到問題了謝謝你~
刪除您好:
回覆刪除看完您的教學後我想讓角色落地後會減速至0
但慣性太大了,往往衝過頭
改用Translate卻產生抖動
該怎麼讓移動看起來更順暢
更自然呢
你說的衝過頭是指穿透地板嗎? 試試看把地板的Collider加厚吧
刪除我指的是左右移動的速度
刪除我想要在放開按鍵後不再移動,變成靜止狀態
可是如果用addforce他就會有個慣性繼續移動
後來我用Translate有達到我要的效果了
不過在移動時撞到牆壁,持續按著移動按鍵會抖動
有辦法改善嗎?
原因是否為Translate運算改變player位置後發現撞牆,所以又改變一次位置
所以變成一直來回來回的抖動?
還有我是想做連線的2D遊戲
能問你相關的問題嗎?
那你可以試試在移動的程式碼裡加上判定條件,按下移動相關的按鍵同時"沒有"碰到牆壁的時候才能AddForce
刪除你講的原因應該沒錯,就是撞牆後回來又被往前推,結果就是一直抖動...
連線遊戲的話我就沒概念了,建議去臉書社團 Unity應用領域 問問 那邊很多高手喔~
了解!
刪除非常感謝
不好意思,請問一下,角色在加上LineCast判斷後就無法跳躍了,已確定圖層設定正常,是否有遺漏了什麼判斷條件?
回覆刪除你可以把程式碼PO出來嗎 這樣比較好幫你判斷
刪除還有 distance 會不會設定太短?太短的話LineCast打不到地板,就會被判定為在空中喔
刪除public bool grounded;
刪除[Header("射線起點")]
public Transform groundCheck;
[Header("地板")]
public LayerMask Layer;
int distance;
public bool JumpKey
{
get
{
return Input.GetKey(KeyCode.UpArrow);
}
}
void Jump()
{
if (JumpKey && Ground)
{
player.AddForce(Vector2.up * 100f);
}
}
public bool Ground
{
get{
Vector2 start = groundCheck.position;
Vector2 end = new Vector2(start.x, start.y - distance);
Debug.DrawLine(start, end, Color.blue);
grounded = Physics.Linecast(start, end, Layer);
return grounded;
}
}
void Update () {
Jump();
}
void Start () {
distance = 1;
}
不好意思...排版跑掉了...
刪除你找一下這兩行 照著修改:
刪除player.AddForce(Vector2.up * 800f); //力道改大一點,我這邊的玩家質量(重量)設比較大,要大力點才能推動
grounded = Physics2D.Linecast(start, end, Layer);//你少寫一個2D
以後可以上網找一下 程式碼分享 的網站,貼程式碼的時候會有自動上色的效果
然後當你覺得程式碼"看起來"跟範例裡一模一樣,卻又找不出那裡出錯的話,找一下 文字比對 的軟體
就可以發現其實你打的程式碼跟範例的不一樣
我也是用文字比對軟體才知道說你少打了個2D
目前的問題依然是Linecast偵測不到LayerMask(程式碼已修改)
刪除謝謝!以解決問題。
刪除主要好像是因為&&判斷條件先後的問題,而導致無法起跳。
你好
回覆刪除請問如果要讓玩家方向和移動方向一致的話,程式部分應該要怎麼寫呢?
目前情況是
當玩家向右移動的時候,看起來像是倒退那樣
這個要配合Animator動畫器來製作,人物座標向右移動時播放向右的Animation動畫,向左移動時播放向左的動畫Animation。
回覆刪除關鍵字:unity 2d移動動畫
我嘗試用不一樣的方法來控制角色:按下按鈕的時候對player施力,之後放開按鈕則再施一個反向的力,讓其停止,目的是讓player可以用一個固定的速度來行進。但是測試的時候常常偵測不到,有時候只有偵測到按下,有時候只有偵測到放開,請問是哪個地方出了問題呢?
回覆刪除有測試了我的鍵盤確認沒有故障
附上程式碼
private void FixedUpdate()
{
Movement();
}
//在這邊管理所有的行動
void Movement()
{
Walk();
Jump();
}
void Walk()
{
if (Input.GetKeyDown(KeyCode.RightArrow))
{
playerRigidbody2D.AddForce(Vector2.right * walkForce);
Debug.Log("Right key down");
}
if (Input.GetKeyUp(KeyCode.RightArrow))
{
playerRigidbody2D.AddForce(Vector2.left * walkForce);
Debug.Log("Right key up");
}
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
playerRigidbody2D.AddForce(Vector2.left * walkForce);
Debug.Log("Left key down");
}
if (Input.GetKeyUp(KeyCode.LeftArrow))
{
playerRigidbody2D.AddForce(Vector2.right * walkForce);
Debug.Log("Left key up");
}
}
void Jump()
{
if (Input.GetKeyDown(KeyCode.Z))
{
playerRigidbody2D.AddForce(new Vector2(0f, jumpForce));
}
}
你好 請問我角色底下放一個物件(子物件)當作射擊口,用一個物件的位置當作子彈製造點。請問要怎麼寫才能讓發射器跟著人物轉向
回覆刪除字面上來看,把發射器設成人物的子物件就可以了,然後生成子彈的時候,子彈套用發射器的角度,但我擔心誤解你的問題,可以的話還是加LINE傳程式碼跟截圖比較清楚
刪除Line帳號連結
http://line.me/ti/p/pTX9Io9AKW