Unity基礎教程-物體運動(十)——環境交互(Movement with Consequences)

2021-02-26 壹種念頭

目錄

1 加速區域

1.1 Zone 組件

1.2 阻止檢測地面

1.3 持續加速

1.4 任意方向

2 意識到存在

2.1 檢測區域

2.2 材質選擇

2.3 最開始進入和最後退出

2.4 檢測突然出現和消失的物體

2.5 熱重載

2.6 更複雜的行為

3 簡單運動

3.1 自動滑動條

3.2 位置插值

3.3 自動倒置

3.4 平滑步長

3.5 更多控制

3.6 壓碎的碰撞體

3.7 局部插值

本文重點內容:

1、通過加速區域創建跳板和浮空

2、製作一個多功能區域

3、不同材質的交互以及關閉或者激活對象

4、通過事件觸發簡單對象插值運動

這是關於控制角色移動的教程系列的第十期。它讓環境可以以各種方式和對象運動產生交互。

本教程是CatLikeCoding系列的一部分,原文地址見文章底部。


本教程使用Unity 2019.4.4f1製作。它還使用ProBuilder軟體包。


(和環境交互)


1 加速區域


一個活躍的環境比一個靜態的環境更有意思,特別是它們還能對正在發生的行為做出反應的時候。這個行為表示可以對任何事情做出反應,也可以做任何事情,但是一個簡單的例子是類似於跳板的東西:每當有東西落在跳板上時,它就會向上彈起。這可以是我們運動的球體,也可以是其他掉落或被推到跳板上的物體。因此,該行為在邏輯上屬於跳板。其他物體不需要意識到它的存在,它們只是突然被彈飛起來了。


1.1 Zone 組件


描述跳板行為的最通用方法是,它是一個區域,可加速進入區域的任何物體。因此,我們將創建AccelerationZone組件類型,其可配置的速度不能為負。


區域可以通過添加一個帶有觸發器碰撞器的對象到場景中來創建,然後將 zone behavior 附加到它上。你也可以添加可視化的跳板對象,但是我只是用半透明的黃色材質使區域可見。


(Acceleration zone 組件)


當具有剛體的物體進入區域時,我們應該對其進行加速。為此添加一個OnTriggerEnter方法,該方法將觸發並調用新的Accelerate方法。進入該區域的所有物體都被執行,但是如果需要的話,可以使用Layer來防止檢測到不需要的處理的物體。



(在區域中的物體被推開)


1.2 阻止檢測地面


這種簡單的方法在發射常規物體時效果很好,但是我們的球體卻沒有正確發射。相反,它進入該區域時似乎獲得了很大的前進速度。發生這種情況是因為我們將其壓在了地面上。在這種情況下,可以通過降低「Max Snap Speed 」來解決,但這種方法不適用於設置為低速的加速區域。通常,為了防止被地面捕捉,我們必須指示MovingSphere暫時不要執行捕捉。為此,我們可以向其添加一個公共的PreventSnapToGround方法,該方法將stepsSinceLastJump設置為-1。


現在,如果物體具有MovingSphere組件,則AccelerationZone.Accelerate可以調用此方法,我們可以通過使用Sphere作為輸出參數調用TryGetComponent來進行檢查和檢索。


(發射)


請注意,這種方法不會重置跳躍階段,因此在沒有著陸的情況下彈跳跳板不會刷新空氣跳躍。


1.3 持續加速


瞬時速度變化對於跳板很合適,但是我們也可以使用該區域創建其他連續的加速度現象,例如懸浮區域。我們可以通過簡單地添加一個與OnTriggerEnter相同的OnTriggerStay方法來支持這個特性。


如果效果持續時間較長,那麼通過適當的加速度來實現速度變化會更好一些,因此讓我們向該區域添加一個可配置的加速度,最小還是為零。如果將其設置為零,我們將立即進行更改,否則將應用加速。



(升空區域 air加速度為1)


也可以施加力,這樣質量較大的物體最終加速得較慢,但是固定的加速度使關卡設計變得更容易,因此我使用這個方式。


1.4 任意方向


最後,為了使其可以在任何方向上加速,請在「Accelerate」開始時將體速度轉換為區域的局部空間,並在應用時將其轉換回世界空間。使用InverseTransformDirection和TransformDirection進行此操作,以便區域的比例不會對其產生影響。現在可以通過旋轉區域來控制加速度方向。


(跳躍區域之間的彈跳)


2 意識到存在


加速區域只是如何創建具有特定行為的觸發區域的一個示例。如果你需要一個做其他事情的區域,你將不得不為它編寫新的代碼。但是,檢測和響應某個地方出現的某些東西的簡單行為是如此普遍,我們理想情況下只想編寫一次。有很多行為非常簡單,比如只是激活一個對象,就為它創建一個專用的組件類型可能就有些設計過渡了。更複雜的行為通常只是幾個簡單動作的組合。如果關卡設計師可以通過簡單的對象來創建它,那會是非常方便的。


2.1 檢測區域


讓我們首先創建一個DetectionZone組件,該組件檢測其區域中是否存在某些東西,並在有物體進入或退出時通知感興趣的模塊。我們通過從UnityEngine.Events命名空間為它提供類型為UnityEvent的onEnter和onExit欄位進行配置來實現。


只需讓它在OnTriggerEnter和OnTriggerExit中的適當事件上調用Invoke方法。這將觸發對事件註冊的所有內容的方法調用。


檢查器會將組件的事件作為名為On Enter()和On Exit()的列表公開,這些列表最初是空的。名稱後面的括號中沒有任何內容,表示這些事件沒有參數。


(沒有事件)


2.2 材質選擇


為了演示其工作原理,我們將創建一個簡單的MaterialSelector組件類型,該組件類型具有可配置的材質數組和MeshRenderer參考。它具有一個帶有索引參數的公共Select方法,該方法將有效的材質分配給渲染器(如果有效的話)。


創建一個帶有紅色非活動區域和綠色活動區域的材質選擇器組件,這將用於更改檢測區域的可視化。雖然不需要將其添加到受影響的遊戲對象中,但這仍然是有意義的。


(材質選擇器)


現在,通過按項目的+按鈕將其添加到檢測區域組件的輸入事件列表中。通過材質選擇器的左下角欄位將遊戲對象連結到該項目。之後,可以選擇MaterialSelector.Select方法。由於此方法具有整數參數,因此其值將顯示在方法名稱下方。默認情況下,它設置為零,表示不活動狀態,因此將其設置為1。然後對退出事件執行相同的操作,這次將參數保留為零。


(設置材質)


區域對象默認使用不活動的紅色材質。只要有物體進入區域,將切換材質到綠色。當有東西離開這個區域時,它又會變成紅色。

(和檢測區域的交互)


2.3 最開始進入和最後退出


該檢測區域可以工作,並確實可以完成其編程的目的,即每次進入時調用一次進入,每次離開時調用一次退出。因此,我們可以混合使用enter和exit事件(例如enter,enter,exit,enter,exit,exit),並且當其中仍然有東西時,最終會出現視覺上無效的區域。在區域中保持活動狀態時,使區域保持活動狀態更加直觀。使用保證進入和退出事件將嚴格交替的區域進行設計也更加容易。因此,它僅應在第一件東西進入時和最後一件東西離開時發出信號。重構事件重命名為onFirstEnter和onLastExit可以使這一點變得清晰,這將需要再次連接事件。


(重命名事件)


為了使這種行為成為可能,我們必須跟蹤區域中當前的碰撞體。通過為DetectionZone提供一個List  欄位(從System.Collections.Generic命名空間初始化為新列表)來完成此操作。


該列表如何工作?

請參閱「對象管理」系列的「持久對象」教程。

在OnTriggerEnter中,只有在列表為空時才調用enter事件,然後始終將碰撞器添加到列表中以跟蹤它。


在OnTriggerExit中,我們從列表中移除碰撞器,並且只有在列表為空時才調用退出事件 列表的Remove方法返回刪除是否成功 這應該總是這樣的,因為否則我們就無法追蹤碰撞器。


(只要有物體在區域就保持激活狀態)


2.4 檢測突然出現和消失的物體


不幸的是,OnTriggerExit不可靠,因為在停用,禁用或銷毀遊戲對象或其碰撞器時便不會再調用它。不應該單獨禁用碰撞器,因為那樣會導致物體掉落到幾何體中,因此我們將不支持這種方法。但是我們應該能夠處理整個遊戲對象在區域內時被禁用或銷毀的情況。


在每一個物理步長中,我們都要檢查區域內的碰撞器是否仍然有效。添加一個在碰撞器列表中循環的FixedUpdate方法。如果一個碰撞器計算為false,這意味著它或它的遊戲對象已經被銷毀。如果不是的話,我們就需要檢查它的遊戲對象是否被禁用了,這一點我們可以通過它的遊戲對象的active屬性來發現。如果碰撞器不再有效,則將其從列表中刪除並遞減循環迭代器。如果列表為空,則調用退出事件。


大多數情況下,檢測區域中沒有物體。為了避免不必要地連續調用FixedUpdate,我們可以在組件喚醒時和最後一個碰撞器退出後禁用該組件。然後我們只有在有東西進入後才啟用它。之所以這樣有效,是因為無論是否啟用行為,總是會觸發觸發器方法。


接下來,我們還應該處理區域對象自身被停用或銷毀的情況,因為當事件仍在區域中時發生時,調用退出事件是有意義的。我們都可以通過添加一個OnDisable方法來完成這兩項工作,該方法清除列表並在列表不為空時調用exit事件。


請注意,檢測區的組件不應由其他代碼禁用,因為它可以管理自己的狀態。一般規則是不要禁用檢測區域組件,也不要禁用任何可能影響該區域的碰撞器。這些遊戲對象應全部停用或銷毀。


2.5 熱重載


因為熱重載(在編輯器播放模式下重新編譯)將調用OnDisable,所以它違反了我們剛剛聲明的規則。這將導致退出事件被調用以響應熱重載,此後已經在區域中的對象會被忽略。幸運的是,我們可以在OnDisable中檢測到熱重載。如果同時啟用了該組件並且遊戲對象處於活動狀態,則我們將進行熱重載,並且什麼也不做。當遊戲對象沒有被銷毀而組件被銷毀時,情況也是如此,但是我們仍然什麼都不做。


我們只需要在編輯器中播放時進行檢查,就可以將代碼包裝在#if UNITY_EDITOR和#endif中。


OnDisable中有哪些相關狀態組合?

如果禁用了該組件,僅僅是禁用或反激活遊戲對象,則應該繼續進行。否則,如果遊戲對象未處於活動狀態,則該遊戲對象將被停用或銷毀,應該繼續。否則,要麼是熱重載,要麼是僅組件被銷毀,則將其忽略。

2.6 更複雜的行為


這只是通過事件可以完成的簡單演示。你可以通過將更多條目添加到事件列表來創建更複雜的行為。甚至不必為此創建新方法,直接使用現有方法。而限制則是它必須是與事件的參數列表匹配的無效方法或屬性設置器,或者最多具有一個可序列化的參數。例如,我進行了一些設置,以便在更改檢測區域本身的可視化效果的同時,在檢測區域內有東西時關閉懸浮區域。


(切換懸浮區域)


您必總是對所有事件都響應。有時候可能只有在進入或退出時才觸發某些事件。例如,在進入區域時激活某些內容。然後退出並不會取消激活它,而重新進入則會再次激活它,雖然二級激活實際上沒有任何用處。


這種基於事件的方法可以用於整個遊戲嗎?

從理論上講,是的,它對於快速原型製作非常有用,但是卻很麻煩。一旦發現自己重複了複雜的模式,便有必要為其創建專用的方法或行為,這種方法或方法應該更容易使用,並在以後必要時進行優化。

3 簡單運動


我們將在本教程中介紹的最後一種情況是移動環境對象。複雜的運動可以通過動畫來完成,可以通過檢測區域觸發。但是通常兩點之間的簡單線性插值就足夠了,例如,對於門,電梯或浮動平臺。現在,讓我們添加對此的支持。


3.1 自動滑動條


無論插值什麼,它在概念上都由從0到1的滑塊控制。如何更改值是與插值本身不同的問題。保持滑塊分離還可以將其用於多個插值。因此,我們將創建一個專用於該值的AutomaticSlider組件。它的可配置持續時間必須為正。當我們使用它為物理對象設置動畫時,我們將使其在FixedUpdate方法中增加其值,並確保它不會溢出。一旦值達到1,我們就可以完成並可以禁用滑塊。


再一次,我們將使用Unity事件使它能夠附加行為到滑動條。在本例中,我們需要一個隨值變化的事件,我們將使用它來傳遞滑塊的當前值。所以我們的事件需要一個浮點參數,可以使用UnityEvent類型。在FixedUpdate結束時調用事件。


但是,Unity無法序列化通用事件類型,因此該事件不會顯示在檢查器中。我們必須創建自己的具體可序列化事件類型,該事件類型只是擴展UnityEvent。此類型特定於我們的滑塊,因此可以通過在類內部以及事件欄位本身進行聲明來使其成為嵌套類型。


進入播放模式時,滑塊將立即開始增加。如果你不希望這樣做,請在默認情況下將其禁用。然後,你可以將其連接到檢??測區域,以在以後啟用它。


(禁用具有值更改事件的滑塊)


請注意,在這種情況下,事件的名稱後跟(Single),表示它具有一個參數。單精度是指浮點類型,它是單精度浮點數。


3.2 位置插值


接下來,創建一個PositionInterpolator組件類型,該類型通過帶有float參數的公共Interpolate方法在兩個可配置位置之間插值可配置剛體的位置。使用Vector3.LerpUnclamped,以使提供的值不會被鉗位,而是由調用者決定。我們需要通過其MovePosition方法更改身體的位置,以便將其解釋為運動,否則將成為閃現。



(位置插值和滑塊相連接)


通過將sider和interpolator都添加到同一平臺對象,我創建了一個簡單的移動平臺。插值器的Interpolate方法的動態版本綁定到滑塊的事件,這就是為什麼其值沒有欄位的原因。然後,我將滑塊連接到檢測區域,以便在有物體進入該區域時激活平臺。請注意,插值點在世界空間中。


(激活移動的平臺)


3.3 自動倒置


我們可以通過向AutomaticSlider添加可配置的自動反向切換來使插值來回移動。這需要我們跟蹤它是否反轉,並在FixedUpdate中加倍代碼,同時必須支持雙向。同樣,當自動反轉激活時,我們必須跳動而不是鉗制該值。在持續時間極短的情況下,這可能會導致溢出,因此反彈後我們仍然會鉗住。



(自動升降的平臺)


3.4 平滑步長


線性插值的運動是剛性的,反轉時速度會突然變化。通過將值的平滑變體傳遞給事件,可以使其加速和減速。通過對其應用smoothstep函數來實現。並使它成為可配置的選項。



(線性VS平滑)



(開啟了平滑步長的平臺)


3.5 更多控制


可以通過檢測區域事件,並禁用滑塊組件來暫停動畫,但讓我們也可以控制其方向。最簡單的方法是通過公共屬性提供其反轉狀態。將反向欄位替換為自動反向屬性,調整其他代碼的大小寫以使其匹配。


讓我們對自動反轉選項執行相同的操作。在這種情況下,我們必須保留序列化欄位,因此添加一個顯式屬性。



(更複雜的平臺控制)


請注意,方向反轉是突然的,因為它仍然是簡單的插值。如果要在任何時候平穩停止和反轉,則需要創建使用加速度和速度的更複雜的邏輯。


3.6 壓碎的碰撞體


移動場景的危險在於,物體最終可能會陷入兩個接近的碰撞器之間。當碰撞器之間的縫隙關閉時,身體要麼被彈出,要麼最終被壓入碰撞器或穿過碰撞器。如果碰撞表面成一定角度,則存在清晰的逃生路徑,物體將朝該方向被推動。如果不是這樣,或者如果沒有足夠的時間逃脫,則物體最終會被壓碎,穿透碰撞體。如果一個物體卡在兩個足夠厚的簡單碰撞器之間,那麼它可以留在它們內部,一旦有一條清晰的道路就彈出。否則會掉下去。


(物體被壓入地表內了)


如果碰撞表面成一定角度,則物體會被推到一邊,並且很有可能逃脫。因此,通過在表面之間留出足夠的空間或通過引入傾斜的碰撞器(無論是否可見)來設計這樣的配置是一個好主意。此外,將box碰撞器隱藏在地板上可以使它更牢固,以免物體被推入。或者,添加一個區域,在適當的時候觸發該區域的銷毀,表示它被壓碎了。


(帶有角度的碰撞器,並且地表下面隱藏了盒碰撞器)


3.7 局部插值


世界空間中的配置可能會帶來不便,因為它無法在多個位置用於同一動畫。因此,讓我們通過在PositionInterpolator中添加一個局部空間選項進行總結。為此,我們添加了一個可選的可配置的Transform,該插值相對於應該發生的插值。通常用插值器引用對象,但這不是必需的。



(相對插值讓復用成為可能)


下一章節,滾動。


歡迎掃描二維碼,查看更多精彩內容。點擊 閱讀原文 可以跳轉原教程。


本文翻譯自 Jasper Flick的系列教程

原文地址:

https://catlikecoding.com/unity/tutorials

相關焦點

  • Unity基礎教程-物體運動(七)——移動地面(Going for a Ride)
    為該對象提供一個啟用了運動功能的剛體組件,因為它是動態PhysX對象。雖然這不是必要的,但可以確保所有交互均按預期進行。但是默認情況下,交互的時間並不正確。當將軌道攝像機的「Focus Radius」設置為零,使其隨球體剛性移動時,這個現象非常明顯。
  • 喵的Unity遊戲開發之路 - 搭便車:移動地面
    通常,這意味著球體可以隨時與可能運動的另一個物體連接。第一步是跟蹤此主體,我們將其稱為「連接主體」。可能同時存在多個這樣的主體,但是這種情況很少見,因此我們將自己限制為一個單一的主體。因此,如果球體最終與多個物體接觸,我們將使用任意物體,而忽略其他物體。一旦知道了身體,我們就必須檢測其運動並將其以某種方式應用於球體。
  • 王者榮耀是怎樣煉成的(三)unity組件與腳本
    順便提一句,Start()和Update()都是unity內部的「事件方法」,不需要我們人工調用,系統會自動調用和管理這些方法的。6.使用腳本直接將腳本拖拽到Hiearchy面板的物體上直接將腳本拖拽到物體的Inspector面板上 運行遊戲,腳本自動執行。
  • Unity編碼篇 Rigidbody類
    Rigidbogy組件可以使遊戲對象在物理系統的控制下運動 , 發射一顆子彈 ,如果子彈沒有命中任何物體 ,最後 子彈會因為重力落下 , 此時就可以利用 Rigidbody 組件實現 , 但是使用該組件一般在 FixedUpdate 函數中執行 , 因為物理仿真一般都在固定頻率下進行計算的 .
  • Unity 實用技巧 - 物理系統初識
    由於該組件代替了它本身的運動,所以不應該通過Transform來改變位置,旋轉;相反應該使用Forces來推動GO並讓物理引擎計算結果。Rigidbody組件擁有一個Is Kinematic 的屬性,該屬性可以將其從引擎的控制中移除,從而可以用腳本控制GO的運動。注意:儘量不要使用腳本控制該屬性的開關。
  • Unity基礎之物理引擎
    我們在unity裡面建了一個正方體cube , 要如何使這個cube可以跟現實中的物體一樣受重力呢 ? 這就需要用到Rigidbody(剛體)組件了 .單擊cube , 在右邊的Inspector面板添加Rigidbody組件添加完Rigidbody組件後,cube1就可以受重力影響了,運行unity時,cube1會因為受到重力往下落.下面為大家介紹 Rigidbody 組件常用參數 : 1. Mass : 物體的質量 .
  • 航天員展示失重環境下物體運動及液體表面張力
    神舟十號航天員在天宮一號開展基礎物理實驗,展示失重環境下物體運動特性、液體表面張力特性等物理現象。
  • unity遊戲製作初始人物控制代碼
    大家好,今天小編帶大家學習一哈unity遊戲製作中初始人物控制代碼。1.我們知道遊戲中,選中人物,在人物未開始運動前,往往會有一個初始的動作,好的,我們這節課通過unity中相關代碼和基礎設置來實現這一效果。
  • 使用Unity 粒子系統實現 2D 人物足跡效果
    部分腳本參考 基本思路: 首先來梳理一下想要的人物足跡的特性: 在人物移動時生成,並在一段特定時間後消失,最好有個淡出效果 足跡會沿人物移動軌跡左右交互排列
  • 小學英語作文記事篇:060 Life is movement 生命在於運動
    運動給我帶來了無窮的樂趣。I like____. Sports____endless fun.C.現在我們每周有超過三節的體育課。我們每天都有不少於一小時的鍛鍊時間。(2)作文實戰Life is movement. Participate in sports, enjoy sports.生命在於運動。參與體育運動,享受體育運動。請你用英文描述一下你最喜歡、最享受的體育運動吧。
  • unity實戰之大主宰
    然後回到unity,點擊windows ->package manager,就能找到自己的資源,全部import這裡是獲取場景後的結果:一起運動!遊戲中有很多移動的平臺,如果踩在這些移動的平臺上,會與平臺一起運動,這非常像是現實中的摩擦力。
  • 識音辯物-通過聲音來預測物體的外觀及運動
    卡內基梅隆大學的研究人員在一項新的研究中聲稱,聲音可以用來預測物體的外觀及其運動。研究人員創建了一個&34;數據集和一系列AI算法,以研究音頻,視覺和運動之間的相互作用。結果表明,從聲音中可以用來預測物體在受到力作用時移動的位置。儘管視覺是感知的基礎,但聲音卻同樣重要。
  • 顏色的混合 ---Illustrator 基礎教程
    顏色的混合 ----Illustrator 基礎教程  1 混合工具  1 混合工具
  • Unity3D 尋路系統
    給需尋路的物體添加NavMeshAgent組件(Unity主要通過NavMeshAgent組件實現自動尋路的功能,角色添加NavMeshAgent組件後,就可以在NavMesh尋路網格上尋找最優路徑找到目標)選中物體,然後在屬性面板中點擊Add Component,搜索Nav Mesh Algent,添加此組件。
  • 巧用Unity 2D功能:只需六步開發簡單的2D UFO遊戲
    using UnityEngine.UI;public class CompletePlayerController : MonoBehaviour {public float speed; //Floating point variable to store the player’s movement speed.
  • 運動物體做波形曲線運動
    這表明了牛頓運動定律存在缺陷。本論文通過研究宏觀天體的運動狀態、微觀粒子的運動狀態、地球上普通物體的運動狀態,論證得出新的牛頓運動定律,一切運動的物體在不受外力時,都是做波形曲線運動。1宇宙中天體的運動軌道1.1 地球公轉的運動軌道眾所周知,地球公轉的運動軌道是一個橢圓,太陽位於橢圓的一個焦點上。
  • 互動設計的最後一公裡(一)——動效設計
    自然自然是高階要求中最難把握的一點,參照現實環境的物體物理運動特點,用戶會將現實生活中的運動感受,帶入到具體的動效過程,若動效不符合用戶運動感受的動效,會給人怪異的情感。因此,不同的動效節奏和形式,會給用戶帶來不同的體驗。例如:在加載過程中的加速運動,要比勻速運動與減速運動的的體驗好。
  • 使用unity製作RPG遊戲3——2D精靈
    context=%7B%22nid%22%3A%22news_9564882242542237691%22%2C%22sourceFrom%22%3A%22bjh%22%2C%22url_data%22%3A%22bjhauthor%22%7D下面需要利用Tiled2Unity把01地圖導入unity下載Tiled2Unity,在根目錄下打開可執行文件進入unity。
  • [專欄精選]Unity剛體詳解
    我們昨天學習過物理系統很重要的是模擬物體的受力情況,物體根據物理規則運動呀。」「那通過代碼修改物體的位置不就能運動起來了麼?」「通過代碼直接修改物體的位置並沒有通過受力的方式改變物體,所以這種方式並沒有應用到物理系統,要想讓物體通過受力運動,我們首先要了解一下Rigidbody組件。物體只有添加了Rigidbody組件,才會對受力作出反應。
  • 手勢交互新突破!ContactPose或助力未來XR再無手柄?
    目前,由於涉及複雜的手指手掌結構和相關軟組織在運動時的變化,以及手和物體之間的接觸互動有著非常複雜的接觸點位和運動區域,強大的實時手部運動感知和追蹤已成為公認的一項極具挑戰性的計算機視覺任務,是科技研究領域中的大熱項目。