在我們之前的章節(jié)中,我們已經(jīng)了解了碰撞體和剛體。但是,對于剛體這個組件來講,有兩種使用方式。其一就是用它來模擬現(xiàn)實世界的移動或碰撞效果(例如,門的開關);其二就是使用代碼來控制物體移動或碰撞(例如,角色的行走)。兩種方式使用場景不同而已。
本章節(jié)要講的角色控制器 Character Controller也是一個組件,它用來控制游戲?qū)ο蟮倪\行。需要注意的是,該組件具有碰撞特性(膠囊碰撞體),而沒有剛體特性(不接受剛體的運動控制)。如果我們使用一個具有剛體組件的游戲?qū)ο驛去碰撞具有角色控制器的游戲?qū)ο驜的時候,我們的游戲?qū)ο驜并不會因為碰撞而運動。角色控制器組件提供了Move和SimpleMove等方法進行移動控制。
接下來,我們就來創(chuàng)建一個“SampleScene6.unity”場景,向其中添加一個球體和膠囊體。
其中球體我們添加球體碰撞體組件和剛體組件,以及一個X軸正方向的力
然后就是我們的膠囊體,添加一個CharacterController組件。這里,我們需要注意的是,默認情況下,我們添加的膠囊體會自帶“Capsule Collider”碰撞體組件,我們?nèi)∠纯伞?/span>
然后我們Play運行我們整個工程,如下所示:?
我們發(fā)現(xiàn),當球體碰撞到膠囊體的時候,兩者都停止了運行,并且沒有穿透模型。這說明我們的角色控制器組件具備碰撞體特性,但不具備剛體特性(如果具有剛體屬性的話,它應該受到碰撞影響,向右邊移動)。即使我們加上剛體,也不會有剛體特性的。角色控制器是專門用來控制角色移動的組件,區(qū)別于直接用Transform或者剛體,CharacterController有著更好的效果。接下來,我們就來簡單介紹這個組件。
Slope Limit:坡度限制,設置角色可以走上的最大斜坡角度值(以度為單位)。
Step Offset:臺階高度,設置角色可以邁上的最大臺階高度值。
Skin width:皮膚厚度,決定兩個碰撞體碰撞后相互滲透的程度。較大的皮膚寬度可減少抖動。較小的皮膚寬度可能導致角色卡住。合理設置是將此值設為半徑的 10%。
Min Move Distance:最小移動距離,設置角色對象最小移動值。
Center:設置膠囊碰撞體在世界坐標中的位置。
Radius:設置膠囊碰撞體的橫截面半徑。
Height:設置膠囊碰撞體的高度。
前四個參數(shù)主要解決移動中遇到障礙時候的設置;后面三個參數(shù)則是設置碰撞形狀的設置。CharacterController為我們提供了兩種移動方法:Move 和 SimpleMove,兩者都需要一個Vector3類型的參數(shù)。首先我們先試一試Move方法。我們?nèi)∠鸖phere游戲?qū)ο?,增加一個平面來充當斜坡,如下所示:
?
接下來,我們創(chuàng)建一個“CharacterMove.cs”腳本來控制膠囊體移動。想到移動,大家肯定會聯(lián)想到Translate方法,這個方法是我們之前學的,就是用來移動的。我們先使用它進行移動操作,代碼如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterMove : MonoBehaviour
{
// 移動速度
private float speed = 10.0f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.A))
{
transform.Translate(Vector3.left * speed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.D))
{
transform.Translate(Vector3.right * speed * Time.deltaTime);
}
}
}
上面的代碼非常簡單,就是按下“A”和“D”鍵的時候,讓膠囊體左右移動。
我們發(fā)現(xiàn),膠囊體確實可以移動,但是它穿過了斜坡,并沒有爬上斜坡。接下來,我們就是用CharacterController的Move方法來試試,代碼修改如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterMove : MonoBehaviour
{
// 移動速度
private float speed = 10.0f;
// 角色控制器組件
private CharacterController controller;
// Start is called before the first frame update
void Start()
{
controller = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.A))
{
//transform.Translate(Vector3.left * speed * Time.deltaTime);
controller.Move(Vector3.left * speed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.D))
{
//transform.Translate(Vector3.right * speed * Time.deltaTime);
controller.Move(Vector3.right * speed * Time.deltaTime);
}
}
}
然后我們重新Play運行工程,如下:
?
我們發(fā)現(xiàn),膠囊體可以順利爬上斜坡,但是往回移動的時候,就會停留在空中繼續(xù)移動。也就是說,Move方法并沒有考慮重力的效果。那么SimpleMove方法呢?
if (Input.GetKey(KeyCode.A))
{
//transform.Translate(Vector3.left * speed * Time.deltaTime);
//controller.Move(Vector3.left * speed * Time.deltaTime);
controller.SimpleMove(Vector3.left * speed);
}
if (Input.GetKey(KeyCode.D))
{
//transform.Translate(Vector3.right * speed * Time.deltaTime);
//controller.Move(Vector3.right * speed * Time.deltaTime);
controller.SimpleMove(Vector3.right * speed);
}
請注意,SimpleMove方法的不需要Time.deltaTime時間了,簡化了我們的代碼書寫。接下來,我們重新Play當前工程,效果如下:
這次我們發(fā)現(xiàn),這次在進行移動的時候,就會受到重力的影響了。通過對比,我們可以很清楚的知道Translate,Move和SimpleMove三者的區(qū)別了。毫無疑問,我們肯定最終選擇SimpleMove方法,它提供了碰撞檢測以及重力效果。
另外,CharacterController由于沒有直接的碰撞組件和剛體組件,因此OnCollisionXXX和OnTriggerXXX方法就不能使用了,但角色控制器專門提供了OnControllerColliderHit方法。接下來,我們就試試這個方法,它的參數(shù)為ControllerColliderHit對象,該對象有諸如gameObject,collider,rigidbody,controller等屬性可以使用。
void OnControllerColliderHit(ControllerColliderHit hit)
{
Debug.Log("碰撞物體為:" + hit.gameObject.name);
}
增加以上代碼后,重新運行當前工程。
請注意,“Plane”是我們的地面,而“Plane(1)”是我們的斜坡。由于碰撞檢測非常快,會輸出大量的Log信息,因此我們可以點擊“Collapse”將重復內(nèi)容折疊顯示。另外,角色控制器Character controller 為我們提供了一個isGrounded屬性,我們可以再腳本章通過該屬性判斷當前角色是否碰撞到地面。
接下來,我們總結(jié)剛體,碰撞體以及角色控制器三者的使用場景。
首先,剛體多用于場景中的“道具物體”,他們的運動通過Unity的物理系統(tǒng)來控制,我們要做的的就是使用代碼給這些“道具物體”施加一個力即可,Rigidbody的AddForce()方法。
接下來就是碰撞體,它定義了游戲?qū)ο蟮摹拜喞庑巍?,碰撞檢測就是根據(jù)這個“輪廓外形”進行計算的。幾乎場景中所有需要交互的游戲?qū)ο蠖夹枰鲎搀w,即便是場景中“靜止”的游戲物體,為了不發(fā)生“穿模”現(xiàn)象,我們也需要增加碰撞體(例如場景中的花草樹木,建筑物等等)。碰撞體一般聯(lián)合剛體一起使用,場景中能夠“運動”的游戲?qū)ο?,一般都會同時添加碰撞體和剛體。如果想讓Unity的物理系統(tǒng)來控制“運動物體”的移動,就按照剛體默認屬性即可(例如我們上面說的“道具物體”)。如果想要使用代碼來控制“運動物體”的移動,則需要勾選剛體的Is Kinematic屬性。兩者的區(qū)別還體現(xiàn)在OnCollisionEnter 和 OnTriggerEnter 方法上面。另外,剛體的Is Kinematic屬性還可以通過腳本來控制,從而可以在物理系統(tǒng)和腳本代碼兩者之間切換控制。
最后是角色控制器,多用于游戲中的“角色”,因為游戲角色要進行大量的交互控制,它的移動和旋轉(zhuǎn)相對來說,比較復雜。他們的運動要么是玩家控制,要么是腳本控制,所以一般不需要由物理系統(tǒng)來控制。這個時候,我們使用CharacterController組件來控制“角色”就非常方便了。CharacterController組件的本質(zhì)是“膠囊碰撞體”+“移動代碼封裝”,它沒有剛體特性,不會受到力的作用效果,也不會產(chǎn)生力的作用效果。請注意,使用了CharacterController組件就不需要使用剛體和碰撞體了,也不要使用Translate()來移動了,要用它自己提供的SimpleMove ()方法來移動物體。如果需要使用CharacterController進行碰撞檢測的話,使用它的OnControllerColliderHit即可。文章來源:http://www.zghlxwxcb.cn/news/detail-477815.html
本課程涉及的內(nèi)容已經(jīng)共享到百度網(wǎng)盤:https://pan.baidu.com/s/1e1jClK3MnN66GlxBmqoJWA?pwd=b2id文章來源地址http://www.zghlxwxcb.cn/news/detail-477815.html
到了這里,關于第三十章 Unity角色控制器 Character Controller的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!