Agent Avoidance
Quantum執行各種稱為混合相互速度障礙物的碰撞迴避技術。這是一篇文章以簡單介紹其技術:針對電玩遊戲的相互碰撞迴避及導航。
設定迴避代理
開啟和檢閱您的模擬設定:AvoidanceRange
對於迴避系統的品質及性能成本來說是重要的。它定義了代理開始影響彼此的範圍。範圍是在兩個代理的半徑之間進行測量。
MaxAvoidanceCandidates
定義了各個代理使用的迴避候選項目的最大數量。更多候選項目需要更多記憶體及CPU時間,但在使用很多代理時也能增加品質。首先試著減少數量,並且看看實際上究竟可以減到多少。AvoidanceQuality
越高,代理遇見彼此的數量越高,這個數量也就需要越高。
設定EnableAvoidance
為關,如果您希望有路徑尋找器及轉向代理,但永不使用迴避。這將最佳化性能,因為不排程迴避工作。如果已經從SystemSetup.cs
完全地移除NavigationSystem
的話,就不需要這樣做。
為了啟用迴避,新增一個NavMeshAvoidanceAgent
元件到已經有一個NavMeshPathfinder
及 一個NavMeshSteeringAgent
元件的實體。
之後設定其NavMeshAgentConfig
的迴避區段:
AvoidanceType.None
將產生一個效果,也就是代理不會迴避其他人,但是其他人會迴避它。很像NavMeshAvoidanceObstacle
元件的效果。
Priority
如同在Unity般工作。最重要 = 0。最不重要 = 99。預設 = 50。因為迴避系統依存於相互性,迴避工作(誰將迴避,迴避多少)總是在代理之間進行分配。高優先級別的代理只處理25%的工作,而同樣優先級別的代理將工作平分。
使用Unity圖層,並且設定AvoidanceLayer
及AvoidanceMask
以篩選代理。舉例而言,設定一些代理到Heroes
圖層,而其他到Minions
圖層,並且設定針對英雄的遮罩以忽略小僕人。
如果您希望針對迴避有一個不同於路徑尋找及轉向的Radius
,切換OverrideRadiusForAvoidance
。
解決迴避問題的同時也試著遵循導航點來在角落轉向或通過狹窄通道,這可能很困難。為了避免問題,以及接受有利於代理封鎖彼此的視覺重疊,切換ReduceAvoidanceAtWaypoints
。當代理接近一個導航點時,運用的迴避將減少。ReduceAvoidanceFactor
值與代理半徑相乘,並且代表迴避影響的平方面積的減少距離。
切換DebugAvoidance
以轉譯Gizmos為場景檢視。頂部的迴避代理正在迴避右側的移動代理及左側的障礙物。紅色圓錐是頂部代理的速度障礙物,而綠色線是候選項目,最後白色點是被選中的候選項目。固定物件的速度障礙物被截斷(請見Navigation.Constants.VelocityObstacleTruncationFactor
以遊玩這個)。
設定迴避障礙物
Avoidance Obstacles
是靜態的或移動物件,其影響導航網格代理的迴避行為,但是它們本身不是代理。它們不影響路徑尋找器,並且不應使用於封鎖遊戲關卡的某些部分。
一個NavMeshAvoidanceObstacle
元件需要一個Transform2/3D
元件以適當地工作。
如果有著一個NavMeshAvoidanceObstacle
元件的實體正在移動,其他代理需要其速度資訊以預測其未來的位置。請確保定期手動更新屬性NavMeshAvoidanceObstacle.Velocity
。
設定一個迴避障礙物:
- 作為一個在Unity中的實體原型元件:
- 或是作為一個在原始程式碼中的Quantum元件:
C#
var c = f.Create();
f.Set(c, new Transform2D { Position = position });
var obstacle = new NavMeshAvoidanceObstacle();
obstacle.AvoidanceLayer = 0;
obstacle.Radius = FP._0_50;
obstacle.Velocity = FPVector2.Up;
f.Set(c, obstacle);
抖動代理
解決多個不同移動方向的代理的迴避問題,可能導致代理快速切換它們的目標方向,直到找到一個好的路線。為了避免這種情況,可以調低代理的Angular Speed
,或像這樣透過覆寫EntityView
來在檢視中運用額外的平滑處理。其中混合數學只是一個建議。
C#
using UnityEngine;
public class SmoothRotationEntityView : EntityView {
private Quaternion rotation;
public float Blending;
protected override void ApplyTransform(ref UpdatePostionParameter param) {
// Override this in subclass to change how the new position is applied to the transform.
transform.position = param.NewPosition + param.ErrorVisualVector;
// Unity's quaternion multiplication is equivalent to applying rhs then lhs (despite their doc saying the opposite)
rotation = param.ErrorVisualQuaternion * param.NewRotation;
transform.rotation = Quaternion.Lerp(transform.rotation, rotation, Time.deltaTime * Blending);
}
}
Back to top