原始檔案與未來教學更新資訊可於Patreon取得
您可於Twitter上追蹤我
本文屬於遊戲數學系列文
Here is the original English post.
本文之英文原文在此
大綱
三角函數為遊戲開發所用到的數學中,非常基礎的工具。也是我選擇它作為本系列首篇教學主題的原因。能夠掌握三角函數的要領,對解決遊戲開發所會遇到的眾多問題非常有幫助。
你將可透過本教學學會:
- 兩個基礎三角函數的幾何意義:正弦函數與餘弦函數
- 比較兩個不同的角單位:角度與弳度
- 正弦與餘弦的基本特性
- 如何使物體沿著圓形移動與排列:
- 如何使物體沿著螺旋路線移動:
- 如何製作簡諧運動效果:
- 如何製作阻尼彈簧運動效果:
- 如何製作鐘擺運動效果:
- 如何製作漂浮運動效果:
正弦函數與餘弦函數的幾何意義
讓我們先來看看單位圓,即半徑為1且中心位於原點的圓。
選一個位於此圓上的點,連接此點與原點的線段與X軸(+X方向)形成一個夾角 (theta).
這正是正弦( – 唸做”sine of theta”)與餘弦( – 唸做”cosine of theta”)這兩個基本三角函數的幾何意義,點的座標即為。
換句話說,與分別為位於單位圓上一點之Y與X座標,則為X軸(+X方向)與連接此點和圓點的線段之夾角。
和是函數,所以正式寫法理應含有圍在參數兩端的括弧:與,不過很多人和文獻都省略那些括弧而直接寫成與。
和為接收單一參數的函數,並且其運算結果總是介於-1與1之間。仔細想想的話,這很合理,因為一個位於單位圓上的點,其X與Y座標不可能超出這個範圍。
若角隨著時間以固定速度增加大小,我們便能以該點之X與Y座標針對時間作圖。
若把兩個座標的角對時間作圖並排比較,就能觀察到它們基本上是同一個波浪形狀的週期函數,只是位置相差四分之一週期。
這些函數的週期是,也就是函數值每循環一次。舉例來說,與的結果相同,因為比旋轉超出基本上還是得到這個角度。
角度與弳度
傳入三角函數的角參數可以是此兩種單位之一:角度(degree)與弳度(radian),弳度又稱弧度,我在校時學的名稱是弳度,所以接下來都將使用弳度稱呼。大部分的人都很孰悉角度符號,如直角90度寫成。注意和其實是不一樣的,當沒有寫出角度符號時,角的單位不是角度,而是弳度。
180度等同於 (pi)弳,則為著名的圓周率,其代表”圓的周長與直弳的比率”,值大約為3.14。所以1弳大約是,接近。讓我們來做個簡單的驗證,用工程計算機(角單位設為弳度)輸入可得到約,非常接近。
以下為一些常見的角度與弳度的對應值:
使用Unity開發時,呼叫和的函式分別為 Mathf.Sin
和 Mathf.Cos
。請注意此兩個函式的參數單位為弳度,所以如果要計算,不要寫成:
// 這其實是將45弳傳入餘弦函數! float cos45Deg = Mathf.Cos(45.0f);
45弳大約是,對其除以取餘數及得到,此為的等同角,並與不同。
正確的寫法是:
// 將角度轉換成弳度 float cos45Deg = Mathf.Cos(45.0f * Mathf.PI / 180.0f);
或者藉由轉換常數來做角度與弳度的換算:
float cos45Deg = Mathf.Cos(45.0f * Mathf.Deg2Rad);
使用Unity編輯器這類工具時,對使用者來說角度單位比弳度單位還友善,因為大部分的人可以馬上想像大概是多少。然而在推導數學與撰寫程式時,不少人(包括我)仍然偏好使用弳度單位。
使用弳度單位的其中一個好處,是能簡化弧長計算。假設要計算一個對應角為30度( 弳)、半徑為2的弧長:
若使用角度單位,必須先用半徑這個公式計算出完整的圓周長,然後把圓周長乘以佔的比例:
使用弳度單位的話,弧長公式就是單純的半徑弳度:
進一步觀察,便能注意到使用圓周長公式可很容易驗證弳度的弧長公式。一個圓基本上就是對應角為弳的弧,使用弳度公式可以得出此弧長為半徑,與圓周長公式一模一樣。
正弦與餘弦的基本特性
現在讓我們來看看一些對未來數學推導很有用的正弦與餘弦的特性。
單位圓上的一點之座標為,不管的值為何,此點與原點的距離永遠是1。
畢氏定理(Pythagorean Theorem)說明,此點座標與原點的距離為,於是我們可以得到以下恆等式:
與的平方分別寫成與,一般人不寫成與可能是因為太懶了吧。
先前展示過正弦與餘弦的並排作圖比較:
可以觀察到餘弦曲線基本上就是正弦曲線往左移90度(弳),這表示以下恆等式可用於在兩函數之間轉換:
沿著圓形與螺旋線移動
現在我們知道是位於單位圓周上之一點2D座標,便可以開始使用Unity讓物件沿著圓形移動了。
以下程式碼可使一個物件以固定速率沿著圓周運動:
obj.transform.position = new Vector3 ( Radius * Mathf.Cos(Rate * Time.time), Radius * Mathf.Sin(Rate * Time.time), 0.0f );
以下程式碼則可使12個物件以固定速率沿著圓周運動,並且使各物件之間沿著圓周的間距相等:
float baseAngle = Rate * Time.time + angleOffset; for (int i = 0; i < 12; ++i) { float angleOffset = 2.0f * Mathf.PI * i / 12.0f; aObj[i].transform.position = new Vector3 ( Radius * Mathf.Cos(baseAngle + angleOffset), Radius * Mathf.Sin(baseAngle + angleOffset), 0.0f ); }
將沿圓周移動與Z軸移動結合,便可使物件沿著3D螺旋線移動:
obj.transform.position = new Vector3 ( Radius * Mathf.Cos(Rate * Time.time), Radius * Mathf.Sin(Rate * Time.time), ZSpeed * Time.time );
簡諧運動
複習一下上面已經看過的餘弦函數之作圖:
如果把物件的X座標設成餘弦函數值會如何?
float x = Mathf.Cos(Rate * Time.time); obj.transform.position = Vector3(x, 0.0f, 0.0f);
我們將會得到此效果:
這種依正弦曲線/正弦波(sinusoid / sine wave)的運動模式稱為簡諧運動(simple harmonic motion, 簡稱S.H.M.)。
由於上面程式中使用的是餘弦函數,物件的初始X座標是。若改用正弦函數,物件的初始X座標則是。
傳入正弦與餘弦函數的角度參數稱為相位(phase)。當傳入三角函數的相位為時間的倍數時,大多數人會將此模式寫成,是時間,時間的倍數 (omega)稱作角速度(單位為弳/秒)。舉例來說,將產生振盪週期為1秒的簡諧運動。
那麼將簡 諧 運動乘上個指數遞減的係數會如何?
float s = Mathf.Pow(0.5f, Decay * Time.time); float x = Mathf.Cos(Rate * Time.time); obj.transform.position = Vector3(s * x, 0.0f, 0.0f);
物件將會改行受阻尼彈簧運動(damped spring motion):
鐘擺運動
若將沿圓形運動的物件之角度設為正弦曲線又會如何?
float baseAngle = 1.5f * Mathf.PI; // 270度 float halfAngleRange = 0.25f * mathf.PI; // 45度 float c = Mathf.Cos(Rate * Time.time); float angle = halfAngleRange * c + baseAngle; obj.transform.position = new Vector3 ( Radius * Mathf.Cos(angle), Radius * Mathf.Sin(angle), 0.0f );
這時物件將會進行鐘擺運動(pendulum motion):
可以想成是沿圓形運動的角度值本身進行簡 諧 運動。
漂浮運動
再來追加一個範例。這是幽浮兔,她是我的Unity彈彈特效工具包Boing Kit範例中的角色。
來試著將錯開的簡諧運動分別套用到她的X、Y、Z座標:
Vector3 hover = new Vector3 ( RadiusX * Mathf.Sin(RateX * Time.time + OffsetX), RadiusY * Mathf.Sin(RateY * Time.time + OffsetY), RadiusZ * Mathf.Sin(RateZ * Time.time + OffsetZ) ); obj.transform.position = basePosition + hover;
如次便可產生漂浮運動(hover motion)的效果:
漂浮運動的位移可以進一步運來計算傾斜角度。這超出本文的主題範圍,所以我就僅列出程式碼與結果:
obj.transform.rotation = baseRotation * Quaternion.FromToRotation ( Vector3.up, -hover + 3.0f * Vector3.up );
總結
本教學結束了!
我們認識到了與的幾何意義,可表示為於單位圓上的一點之座標。然後,我們了解了兩種不同的角單位:角度與弳度。最後,我們學會了如何使物體沿圓形與螺旋線運動、進行簡諧運動、受阻尼彈簧運動、鐘擺運動、與漂浮運動。
我希望這篇教學能幫助你更加了解兩個基本三角函數:正弦函數與餘弦函數。
下一篇教學,我將介紹另一個基本三角函數:正切函數,並且會介紹更多這三個三角函數的應用。
我們下篇教學再見!
若您喜歡這篇教學,請考慮到Patreon支持我。感謝!