巴哈姆特

首頁 哈啦區 Unity 遊戲引擎

【問題】當沒有物理引擎,怎樣"跳"?

追蹤話題

【問題】當沒有物理引擎,怎樣"跳"?

問題求解
Canis (canistk) 2018-01-05 02:56:09
#1
用物理引擎跳很簡單.

Vector3 jumpForce = xxxx;
rigidbody.AddForce(jumpForce, ForceMode.VelocityChange);
// 可以用 VelocityChange 或者 Impulse.

但我的情況是做一個假的跳來達到以下條件
  • 頂點 (Apex) 為 2 unit 高 (1 cube = 1 unit)

請數學達人來講解一下...

然後就更加的不明白了....

pohan (brian780405) 2018-01-05 03:42:25
#2
用國中教的拋物線公式導出來的
大概長這樣,x軸是時間,y軸是高度
因為c大有提到是假跳,所以應該只是要路徑而已?

滑鼠左鍵跳,右鍵停,希望能幫到你

public class JumpTest : MonoBehaviour
{
        public float maxHeight = 3;  //跳躍高度
        public float maxHeightTime = 0.5f;  //到最大高度的時間

        private float y0;  //紀錄一開始的高度
        private float t;  //紀錄時間
        private bool jumping;

        private void Start()
        {
                Initialize();
        }

        private void Update()
{
                if (Input.GetMouseButton(0))
                        Jump();
                if (Input.GetMouseButton(1))
                        Initialize();

                if (!jumping)
                        return;

                //y = -(3 / 0.5 ^ 2) * (x - 0.5) ^ 2 + 3
                float m = -maxHeight / Mathf.Pow(maxHeightTime, 2);
                float y = m * Mathf.Pow(t - maxHeightTime, 2) + maxHeight + y0;
                transform.position = Vector2.up * y;
                t += Time.deltaTime;
        }

        private void Jump()
        {
                jumping = true;
        }

        private void Initialize()
        {
                y0 = transform.position.y;
                t = 0;
                jumping = false;
        }
}
Canis: B1 2018-01-05 03:47

感謝提供~ 我會好好的學習一下.

Canis: B2 2018-01-05 03:52

原來 Google 還可以這樣玩, 可惜GP不能給2次.

pohan: B3 2018-01-05 03:55

CanisGoogle OP

Canis (canistk) 2018-01-05 04:54:55
#3
※ 引述《brian780405 (pohan)》之銘言
float m = -maxHeight / Mathf.Pow(maxHeightTime, 2);
float y = m * Mathf.Pow(t - maxHeightTime, 2) + maxHeight + y0;

測試過結果完美,

我自己看公式
x ^ 2 = -2py

求 y 值
y = (x ^ 2 / -2 * p)
假定高度 p = 為 3
y = (x ^ 2 / -2 * 3)

呃, 所以另外加上 3 來合理化地面為 0 的值.
但, 搞不明白你是怎樣把圖表偏移 0.5 的..
-(3 / 0.5 ^ 2) ?! 跟 (X - 0.5) ^ 2 這兩部分是怎樣求出的?!

把代碼修改一下, 方便重覆測試.

  1. using System.Collections;  
  2. using UnityEngine;  
  3.   
  4. public class JumpTest : MonoBehaviour  
  5. {  
  6.     public float m_Height = 3;  //跳躍高度  
  7.     public float m_TimeToApex = 0.5f;  //到最大高度的時間  
  8.     private Coroutine m_JumpCoroutine = null;  
  9.   
  10.     private void Update()  
  11.     {  
  12.         if (Input.GetMouseButtonUp(0) && m_JumpCoroutine == null)  
  13.             m_JumpCoroutine = StartCoroutine(_Jump());  
  14.     }  
  15.   
  16.     IEnumerator _Jump()  
  17.     {  
  18.         //y = -(3 / 0.5 ^ 2) * (x - 0.5) ^ 2 + 3  
  19.         // https://www.google.com.tw/search?ei=DX9OWtfjC8yb8wXfqJOIBQ&q=y+%3D+-(3+%2F+0.5+^+2)+*+(x+-+0.5)+^+2+%2B+3&oq=y+%3D+-(3+%2F+0.5+^+2)+*+(x+-+0.5)+^+2+%2B+3&gs_l=psy-ab.3...1073717.1073717.0.1074218.1.1.0.0.0.0.63.63.1.1.0....0...1c.1.64.psy-ab..0.0.0....0.B2YzciMS_AI  
  20.         float apex = m_TimeToApex; // Notes: Xh = time to reach apex of the jump curve  
  21.         float apexP2 = Mathf.Pow(apex, 2);  
  22.         float startTime = Time.timeSinceLevelLoad;  
  23.         float endTime = startTime + (apex * 2f);  
  24.         Vector3 initPos = transform.position;  
  25.   
  26.         while (Time.timeSinceLevelLoad < endTime)  
  27.         {  
  28.             float t = Time.timeSinceLevelLoad - startTime;  
  29.             float m = -m_Height / apexP2;  
  30.             Vector3 pos = initPos;  
  31.             pos.y = m * Mathf.Pow(t - m_TimeToApex, 2) + m_Height + pos.y;  
  32.             transform.position = pos;  
  33.             yield return null;  
  34.         }  
  35.   
  36.         m_JumpCoroutine = null;  
  37.     }  
  38. }  

後續 :
還希望找到怎樣把3維距離的 XZ軸加入計算.
我預計是這樣測度 XZ 速度的.

Vector3 origin = transform.position;
// 上一幀.

// Start jump.
// calculate reference
Vector3 vector = transform.position - origin;
float distance = vector.magnitude;
float speed = distance / Time.deltaTime;
Debug.LogFormat("Time {0:G}, Speed {1:F2}, Distance {2:F2}", time, speed, distance);

Vector3 direction = vector.normalized;
Vector3 previousVelocity = vector.normalized * speed;

pohan (brian780405) 2018-01-05 06:56:46
#4
※ 引述《canistk (Canis)》之銘言
> x ^ 2 = -2py
> 求 y 值
> y = (x ^ 2 / -2 * p)
> 假定高度 p = 為 3
> y = (x ^ 2 / -2 * 3)
> 呃, 所以另外加上 3 來合理化地面為 0 的值.
> 但, 搞不明白你是怎樣把圖表偏移 0.5 的..
> -(3 / 0.5 ^ 2) ?! 跟 (X - 0.5) ^ 2 這兩部分是怎樣求出的?!
假設頂點是(a,b)
那方程式就是y = m(x - a) ^ 2 + b

m是用(0,0)求出來的
0 = m * a ^ 2 + b
m = -b / a ^ 2

> 後續 :
> 還希望找到怎樣把3維距離的 XZ軸加入計算.
> 我預計是這樣測度 XZ 速度的.
直接打掉重做了...點我觀看
*maxHeight請理解為跳躍高度,這邊就不改了

測試起來應該沒啥問題
要注意的地方是「最終高度-起始高度需<最大高度」
(最大高度設3,結果你從0跳到4就會壞掉)

y的表示式用紙筆手算的,很無聊可以去算算看XD
xz就單純線性,比y好處理很多
pohan: B1 2018-01-05 08:39

突然想到,不應該是設總時間,而是要設重力才對

pohan: B2 2018-01-05 08:39

有空在改 先休息...

Canis: B3 2018-01-05 11:12

重力修改的方式,想法是停用rigidbody.gravity, 然後每幀裡算上phyics.gravity.y

Canis: B4 2018-01-05 11:13

再謝謝,提供了不少有用的模版

Tyrr. R (SemihLafihna) 2018-01-05 10:50:57
#5
其實我都把y軸重力單純看成類似煞車,從一個初始速度減到速度0,完美世界不考慮其他摩擦力(引擎常看到的damping, friction甚麼的)
  • 往上跳躍的初始速度V
  • 重力加速度g
  • 減到0速的時間 T = |V/g|
  • 移動距離 d = V * T / 2 = (V * |V / g|) / 2

了解這些之後.. 還是微調,試到高興為止
不要太糾結在固定高度,別忘了跳的爽感才是最重要

遊戲中角色通常沒有xz軸旋轉,y軸分開計算就會簡單了


沒看影片,不過真的要當作飛彈來計算的話,可以參考 Wikipedia : Projectile_motion
https://gamedev.stackexchange.com/questions/149327/projectile-aim-prediction-with-acceleration

看較舊的 1 則留言

Canis: B2 2018-01-05 10:58

e.g. 空中三角跳, 空中dash, wall run 轉double jump

Canis: B3 2018-01-05 10:59

或許可以用物理的方式達成?但好像更難....

Tyrr. R: B4 2018-01-05 12:54

不大確定你要做的是什麼,不過最重要應該是找到好的參考點,把各軸盡量分開,不要混在一起算,會哭

Tyrr. R: B5 2018-01-05 12:56

比如空中三角大概應該用角色面向當一軸,頭頂當另一個軸

Canis: B6 2018-01-05 13:17

Tyrr. R了解,謝謝提醒,正在看你提供的文件,那個跟bezier curve好像是差不多的東西

Canis (canistk) 2018-01-14 12:17:25
#6
謝謝, 先前幫忙的各位,
跑牆三角跳的問題順利解決.

不過最後我是使用混合的方式來處理,
  • AvatarWallRun 是用 OnTriggerEnter 來到觸發, 然後以Raycast 來進行位置定位,及角度計算, 之後額外產生一個 FixedJoint (breakable) 連結到 avatar 本身. 作位置移動.
日誌:
http://www.clonefactor.com/wordpress/public/1929/

Canis (canistk) 2018-02-16 02:57:38
#7
※ 引述《canistk (Canis)》之銘言

剛把整個跑牆打掉重練.
有點小修正.
其實難的並不是如何用物理來"跳". 而是理解如何操作所有的 velocity
前面大大提到的分拆三軸
利用 Projection, normal 等等抽離不同的速度,以及有條件地寫入不同向性的力 / 加速度.
達到這步, rigidybody.addForce 的四個模式是必需精研的.
然後就是怎樣適時切換制做 真/假物理.

http://www.clonefactor.com/wordpress/program/unity3d/1933/

悠浪貓: B1 2018-02-19 23:36

我這個人很簡單, 有初音就GP

Canis: B2 2018-02-19 23:59

悠閒浪子 Ah, I See You're a Man of Culture As Well

延伸閱讀

問題Unity引擎的遊戲沒有回應或是崩潰 求解!

2023-09-11 22:09:07

心得Unity 遊戲引擎從零開始 - Unity 基本運作篇

2016-05-21 13:26:51

問題Unity游戏服务端物理系统是否有开源解决方案?

2021-10-16 05:57:03

問題想做出類似Unity的遊戲引擎架構

2021-05-23 00:07:13

電梯
開啟 APP

face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】