1. 程式人生 > >(官網)虛幻3--角色技術指南

(官網)虛幻3--角色技術指南

ims osi 1.0 基本知識 延遲 加速 health 一個 rup

角色技術指南


使用2011 年 6 月的UDK版本進行了最後測試

  • 角色技術指南
    • 概述
    • Controllers(控制器)
      • Controllers(控制器)
        • Pawns和Possession(占有)
        • Inventory(武器庫)
        • 運動和導航
        • 相機/ 瞄準
      • Player Controllers(玩家控制器)
        • 綜述
        • 玩家 輸入/運動
      • AI Controller(控制器)
        • 決策
    • Pawn
      • Controllers(控制器)和Possession(占有)
      • 武器庫和武器
      • 受到傷害
      • 動畫
      • 相機視角 /瞄準
    • 玩家示例
      • Player Pawn 類
      • Player Controllers(玩家控制器)類
      • GameInfo類
    • NPC示例
      • NPC Pawn類
      • NPC Controller 類
    • 測試新的自定義NPC

概述


虛幻引擎中的角色由兩部分組成: Pawn和Controller。Pawn是世界中的玩家或非玩家控制角色(NPC)的物理表示。它不知道角色由玩家控制和由AI控制之間的區別。Pawn具有網格物體、碰撞以及使它們處理角色和世界進行物理交互所涉及的所有功能。它們也包含了利用其它玩家或它們周圍的環境的功能、產生聲音、播放動畫以及武器功能比如持有 並/或 開火武器(盡管武器開火過程從技術上講是從controller (控制器類開始的))。

任何時刻每個Pawn都可以有一個單獨的Controller(控制器)。Controller,正如它的名字所暗示的,它負責告訴Pawn做什麽及如何表現。它實質上是Pawn後面的大腦。Controllers具有不同的形式,比如PlayerControllers和AIControllers,但是它們的主要目的是從世界中的玩家或其它刺激物接受輸入,處理那個輸入,並展現相應的行為。這通常會導致向Pawn傳送一個命令或一系列命令。

在正常情況下,GameInfo 類將會處理在玩家登陸時為所有玩家創建Controller,然後比賽開始時為每個Controller(控制器)創建一個Pawn並把它分配給那個Controller。這最後一步處理稱為 possession(占有) ,因為現在Pawn被Controller所占有並且在它的控制之下。完整的玩家創建過程在以下時序圖中進行了表示。

技術分享

當然,不一定全是這樣的情況。您的遊戲或許由在世界中手動地到處放置的NPC組成,而不是動態地創建NPC。這些NPC大多數是基類Pawn的子類,Pawn類將處理它們的Controller的創建,並把那些NPC分配給那個Controller。

Controllers(控制器)


Controller(控制器)是一個非物理的Actor,它附加到Pawn上來控制Pawn的動作。它使用從玩家或它的周圍環境接收的信息,並使用那個信息來使得玩家產生相應的行為。Controller負責運動,無論它是對玩家輸入做出反應、遍歷導航系統產生的路徑還是基於各種事件執行一些動作。當Pawn在遊戲中運動時,Pawn那樣運動是因為Controller告訴它那樣做。Controller接收為它們控制的Pawn產生很多事件通知,比如查看或監聽敵人。Controller使用這些事件來實現Pawn對相應事件做出反應的適當的行為。

Controller的兩個主要子類是 PlayerController AIController 。當創建您的新角色時,您將需要根據您要創建的角色類型來繼承這些類其中的一個,或者它們的其中一個子類。

Controller,特別是AIControllers,大量地使用了States(狀態),它允許控制器重載同一個類中函數,並讓它們根據Controller的當前狀態執行不同的動作。States(狀態)也提供了使用latent代碼和latent函數的功能,比如AI角色使用其導航世界的運動函數。

Controllers(控制器)

Controller 基類包含了關於Pawn控制的一般性的函數和事件,它沒有必要特定地針對Pawn是玩家控制的Pawn 還是AI控制的Pawn。

Pawns和Possession(占有)

這些函數涉及到了占有及不占有Pawns。

  • Possess [inPawn] [bVehicleTransition] - 這把指定的 Pawn分配作為Controller的Pawn,並且通過調用它的PossessedBy()函數來通知Pawn。
  • UnPossess - 這個函數清除了這個Controller的Pawn引用,並通過調用UnPossessedBy()函數通知Pawn它將不再被這個Controller所控制。

Inventory(武器庫)

這些函數是和拾取物、武器及其它和武器相關的功能有關。

  • RatePickup [PickupHolder] [PickupClass] - 這是個從PickupFactory中調用的函數,它計算了拾取物的吸引力。
  • HandlePickup [InvetoryItem] - 這個函數是一個空的占位符,重載這個函數可以允許您實現一些處理您已經拾取到的武器項的附加功能。
  • FireWeaponAt [inActor] - 這個函數導致Controller的Pawn 向指定actor開火當前活動的武器。
  • StopFiring - 這強制使得Controller的Pawn 停止開火當前活動的武器。
  • SwitchToBestWeapon [bForceNewWeapon] - 這用於計算這個Controller的Pawn的武器庫中哪個武器是最好的,並且使它成為活動武器。無論活動的武器是否是最好的武器,這個布爾參數選項可以強制選擇一個不同的武器而不是當前活動的武器。
  • ClientSetWeapon [WeaponClass] - 這個函數強制Controller的Pawn 切換到指定武器,假設Pawn的武器庫中存在哪種類型的武器。

請參照武器技術指南頁面獲得關於武器的更多信息。

運動和導航

這些函數和使得被占用的Pawn在世界上到處移動有關;這意味著將給Pawn一個命令讓它到達特定的目標,並且運動是動態的不需要每次tick都進行更新。

  • MoveTo [NewDestination] [ViewFocus] [DestinationOffset] [bShouldWalk] - 這導致Pawn運動到指定的位置,或可選的指定偏移量中的某個位置,同時會保持它的聚焦在給定的可選actor上。這個函數將會使用路徑網絡來幫助Pawn導航到目的地。
  • MoveToDirectNonPathPos [NewDestination] [ViewFocus] [DestinationOffset] [bShouldWalk] - 除了它僅用於當直接運動到最終目標而不是遵循路徑運動的情況外,這個函數和MoveTo()的功能一樣。
  • MoveToward [NewTarget] [ViewFocus] [DestinationOffset] [bUseStrafing] [bShouldWalk] - 這會導致Pawn運動到給定的actor處,該actor由NewTarget指出。當移動到另一個Pawn或一個武器actor時,這個函數將利用導航網絡。
  • FindPathTo [aPoint] [MaxPathLength] [bReturnPartial] - 這個函數計算出到距離給定目的地最近的導航節點的路徑並返回沿著那條路徑的下一個節點。
  • FindPathToward [anActor] [bWeightDetours] [MaxPathLength] [bReturnPartial] - 這個函數計算出到距離給定actor 最近的導航節點的路徑並返回沿著那條路徑的下一個節點。
  • FindPathTowardNearest [GoalClass] [bWeightDetours] [MaxPathLength] [bReturnpartial] - 這個函數計算出到距離給定類別最近的導航節點的路徑並返回沿著那條路徑的下一個節點。
  • FindPathToIntercept [Pawn] [InRouteGoal] [bWeightDetours] [MaxPathLength] [bReturnpartial] - 這個函數計算攔截給定pawn的路徑,並且隨著他在世界中運動,返回沿著那條路徑的下一個節點。
  • PointReachable [aPoint] - 根據當前Pawn的運動能力,這個函數返回了它是否可以直接地到達給定位置。這個函數的性能消耗是非常大的,所如果可能請避免使用它,可以使用ActorReachable()作為替換。
  • ActorReachable [anActor] - 這個函數根據給定Pawn的運動能力返回了它是否可以直接到達指定的actor。盡管它比PointReachable()做了更多的優化,但是這個函數的性能消耗仍然是很大的,應該謹慎地使用。
  • FindRandomDest - 這個函數返回導航網絡中的一個隨機節點。這對於創建一個中Pawn在世界中到處閑逛的狀態是有用的。

請參照AI 概述獲得關於人工智能和導航的更多信息。

相機/ 瞄準

這個部分的函數是於視口和Controller及它的Pawn瞄準有關的函數。

  • GetPlayerViewPoint [out_Location] [out_Rotation] - 這個函數返回了Controller的Pawn的視角。對於人類玩家來說,這是指相機的視角。對於AI-控制的玩家來說,這個函數是Pawn眼中的視角。在這個基本的實現過程中,它只是 Controller 自己的位置和旋轉量。
  • GetActorEyesViewPoint [out_Location] [out_Rotation] - 如果存在Controller或它的Pawn,這個函數則返回Controller或他的Pawn的視角。基本上,它會返回玩家從哪個位置和方向觀看。
  • IsAimingAt [Target] [Epsilon] - 這個函數返回在給定的變動幅度內,這個Controller當前是否正在朝著指定的目標瞄準。Epsilon為1.0意味著直接朝目標瞄準,但是較低的值允許一些誤差。

Player Controllers(玩家控制器)

PlayerController及它的子類實現了從人類玩家接受輸入並把那個輸入處理成為您在遊戲中可以看到的動作的功能。在很大程度上,這意味著PlayerController 處理這樣的動作,比如移動Pawn、控制相機(通過Pawn的方式)、及根據玩家已經按下的按鈕或按鍵切換武器或是武器開火。以下是PlayerController 類的一些主要函數,並逐個對它們進行了解釋。

綜述

這些函數從本質上是具有通用性的,它們不屬於特定的類別。

  • Playertick [DeltaTime] - 這是玩家的主要更新函數。每次循環都會執行這個函數。
  • ConsoleCommand [Command] - 這執行給定的命令,就像玩家輸入的控制臺命令那樣。

玩家 輸入/運動

這些函數是關於玩家的輸入和運動的。

  • InitInputSystem - 這個函數通過創建PlayerController的PlayerInput類的新的實例初始化輸入系統。
  • PlayerMove [DeltaTime] - 這個函數計算當前運動的新的加速度和旋轉值,然後調用ProcessMove()函數(對於單玩家或監聽服務器)或ReplicateMove()函數(對於網絡客戶端)。這只是基本 PlayerController 類中的一個存根,但是它在與運動有關的特定狀態中被覆蓋,例如 PlayerWalking 狀態。每個循環都會從 PlayerTick() 函數中調用這個函數。
  • ProcessMove [DeltaTime] [newAccel] [DoubleClickMove] [DeltaRot] - 這處理客戶端的當前運動。該函數被覆蓋在運動需要特殊功能才能運動的特定狀態內部。
  • ReplicateMove [DeltaTime] [newAccel] [DoubleClickMove] [DeltaRot] - 這個函數啟動了運動過程。它在PendingMove 列表中保存了當前運動,然後調用ProcessMove()和ServerMove() (在服務器上執行)。
  • ServerMove [TimeStamp] [inAccel] [ClientLoc] [MoveFlags] [ClientRoll] [View] - 這個函數僅在服務器端執行,通過調用MoveAutonomous()來執行當前的運動。它也根據自從上次更新是否已經過去了足夠的時間或者在客戶端和服務器的位置之間是否有足夠的誤差來決定是否需要進行更新。
  • Move Autonomous [DeltaTime] [MoveFlags] [newAccel] [DeltaRot] - 這個函數調用ProcessMove(),並且會更新任何需要執行的自治物理計算。
  • ClientUpdatePosition - 這個函數更新了玩家在客戶端的位置以便它可以和服務器端的位置相匹配。會從 PlayerTick()函數中調用這個函數,但是僅當ServerMove()已經判定需要時才進行調用。
  • UpdateRotation [DeltaTime] - 這個函數根據玩家的輸入更新了Controller和Controller的Pawn的旋轉值。
  • ProcessViewRotation [DeltaTime] [out_ViewRotation] [DeltaRot] - 這個函數根據玩家的輸入處理玩家的視角旋轉,並輸出最終旋轉值。從 UpdateRotation() 中調用。

AI Controller(控制器)

AIController及它的子類實現了觀察Pawn的周圍環境,並根據那個信息做出智能決策的功能。它從本質上使用了它自己自包含的決策循環來不斷地在決策過程中進行循環,並基於這些決策執行適當的動作。下面解釋了AIController 類的主函數。

決策

當處理 AI控制的敵人時,決策過程顯然是非常重要的。如果沒有東西處理信息並根據那些信息決定做什麽或怎麽表現行為,那麽您的NPC角色只是雕像而已,沒有任何用途。顯然,關於如何創建好的AI的討論已經超出了本文檔的範圍,但是您仍然需要知道如何及在哪裏把您的AI代碼添加到AIController 類結構中。以下的函數是在決策過程中的主要函數。

註意: 這些函數是在UDKBot 類中實現的,而不是在AIController 基類中。您需要擴展UDKBot或UTBot來使用這些函數。

  • ExecuteWhatToDoNext - 這是決策過程的主要入口點,並且它應該包含大部分的決策邏輯。這個函數在物理tick(更新)中執行,所以它不能包含任何改變物理狀態的信息。
  • WhatToDoNext - 這個函數會導致在下一個tick(更新)中調用ExecuteWhatToDoNext()函數,同時這個函數也可以包含在物理更新過程中不安全執行的任何代碼。這個函數不能從狀態代碼中進行調用,請使用LatentWhatToDonext()作為替換。
  • LatentWhatToDoNext - 這個函數封裝了WhatToDoNext()函數調用,並且它等待更新延遲的決策過程發生。這個函數從狀態代碼中進行調用,以便在等待下一個決策循環的過程中暫停狀態。

Pawn


Pawn類是Unreal中的所有玩家、角色、怪物和其它類型敵人的基類。正如之前所提到的,它負責玩家或AI同世界間的物理交互。當創建一個自定義的Pawn類時,您首先要知道的是已經存在了哪些功能,以便您可以合理地決定通過重載哪個現有函數來實現您的新角色要需要的行為,同時節約必要的時間,使您有更充足的時間來添加那些全新的功能。為了幫助大家解決這個問題,下面解釋了Pawn類的重要函數,把它們按照功能進行了分類。

Controllers(控制器)和Possession(占有)

這些函數包含了Pawn和Controller進行交互、Controller占有Pawn和不占有Pawn相關的功能。

  • PossessedBy [controller] [bVehicleTransition] - 這個函數設置傳入的Controller 作為Pawn的新Controller,並執行任何其它必要的動作或初始化。當Controller要占有Pawn時調用這個函數。
  • Unpossessed - 這個函數清除Pawn的Controller並重新設置任何相關屬性。當Pawn死亡、回合結束、或者當Controller 不再像占有這個Pawn時(也就是如果Controller 想占有不同的Pawn時),將會從Controller 中調用這個函數。
  • SpawnDefaultController - 這個函數會為Pawn產生一個ControllerClass實例,如果Pawn當前沒有controller,它會使得那個Controller占有那個Pawn。將會在Pawn的PostBeginPlay() 函數中調用這個函數,來確保放在關卡中的Pawn或在遊戲性過程中產生的Pawn被Controller所占有。
  • DetatchFromController [bDestroyController] - 這會導致Controller 不會再占有那個Pawn,當占有關系破壞後則可以任意地銷毀那個Controller 。當Pawn死亡、重置、被銷毀或者被分配給另一個Controller時調用這個函數。

武器庫和武器

武器庫的大部分功能是由PostBeginPlay()事件中產生的Pawn的InventoryManager(武器庫管理器)處理的。雖然,Pawn確實處理了某些功能並且通過使用幾個特定的武器庫函數把命令傳遞給InventoryManager(武器庫管理器)。但是Pawn類也包含了幾個關於武器和這些武器開火相關的函數。以下列出了這些函數。

  • AddDefaultInventory - 這把列在默認武器庫中的武器項添加到Pawn的武器庫中。這個函數從GameInfo 類的AddDefaultInventory()函數中進行調用。
  • CreateInventory [inventoryClass] [bDoNotActivate] - 這創建了一個特定武器庫的實例,把它添加到Pawn的武器庫中,並且返回新的武器項。這個函數簡單地把函數調用傳遞到InventoryManager(武器庫管理器)來處理實際工作。
  • FindInventoryType [inventoryClass] [bAllowSubclass] - 這個函數搜索Pawn的武器庫獲得指定類的實例,如果找到則返回那個實例。
  • TossInventory [invenetoryItem] [forceVelocity] - 這會導致Pawn以任意的速度扔掉指定的武器項,把它從Pawn的武器庫中刪除。
  • ThrowActiveWeapon - 這會導致Pawn把當前活動的武器扔到地面上,把它從Pawn的武器庫中刪除。這會簡單地把命令傳遞到TossInventory()來處理實際的操作。
  • SetActiveWeapon [newWeapon] - 這個函數設置自定武器作為Pawn的活動武器。這會簡單地把命令傳遞到InventoryManager 來處理實際的操作。
  • PlayWeaponSwitch [oldWeapon] [newWeapon] - 這個函數會導致Pawn播放必要的動畫來把武器從一個舊的武器切換為新的武器。將會從InventoryManager的ChangeWeapon()函數中調用這個函數。
  • StartFire [fireModeNum] - 這個函數會導致Pawn使用指定的開火模式使得獲得活動的武器開火。這會把命令傳遞到Inventorymanager中。
  • StopFire [fireModeNum] - 這個函數會導致Pawn停止活動武器及開火模式的開火。這會把命令傳遞到Inventorymanager中。
  • WeaponFired [weapon] [bViaReplication] [hitLocation] - 這用於delegate(代理)所有和開火活動武器相關的特效的創建。這個函數調用了活動武器的PlayFireEffects()函數。
  • WeaponStoppedFiring [weapon] [bViaReplication] - 這用於delegate(代理)所有和開火活動武器相關的特效的銷毀。這個函數調用活動武器的PlayFireEffects()函數。

受到傷害

Pawn類包含了治愈及從武器和其它環境受到傷害的功能。和傷害及生命值相關的函數如下所示。

  • TakeDamage [damage] [instigatedBy] [hitLocation] [momentum] [damageType] [hitInfo] [damageCauser] - 這個函數會把Pawn的生命值降低指定量。
    • Damage - 所降低的生命值的量。
    • InstigatedBy - 受到傷害的Pawn的Controller (控制器)。
    • HitLocation - 應用傷害的位置。
    • Momentum - 受到傷害後應用於Pawn的速度。
    • DamageType -傷害類型類描述了所產生的傷害的類型。
    • HitInfo - 可選的關於傷害的TraceHitInfo結構體的信息。
    • DamageCauser - 負責產生傷害的任意Actor。
  • HealDamage [amount] [healer] [damageType] - 這會把Pawn的生命值增加指定量,如果Pawn沒有死亡或者具有全部的生命值,那麽它會把最終的生命值量限定在Pawn的最大生命值內。
  • TakeFallingDamage - 這會根據Pawn的下降速度來對它應用傷害。這會把適當的傷害量傳遞到TakeDamage() 函數中。
  • CrushedBy [otherPawn] - 當另一個Pawn基於一個Pawn上時,它會導致這個Pawn受到傷害。傷害量是根據基於這個Pawn上的Pawn的速度決定的。這個函數會從Pawn的BaseChange()函數中進行調用,並且會傷害量傳入到TakeDamage()函數中。
  • TakeRadiusDamageOnBones [instigatedBy] [baseDamage] [damageRadius] [damageType] [momentum] [hurtOrigin] [bFullDamage] [damageCauser] [bones] - 這個函數把根據半徑進行衰減的傷害應用到Pawn的骨架網格物體的一系列特定骨骼上。
  • NotifyTakeHit [instigatedBy] [hitLocation] [damage] [damageType] [momentum] - 這個函數會發送通知給任何需要知道Pawn已經受到傷害的東西。這個函數調用Controller的 NotifyTakeHit()函數。
  • TakeDrowningDamage - 這個函數會根據Pawn是否在水中以及它已經在水中待了多長時間來應用傷害。

動畫

Pawn使用骨架網格物體作為它們的主要可視化組件。盡管動作(比如運動)的大量動畫播放都是由分配給Pawn的AnimTree 進行處理的,但是它們確實有一些播放內置動畫的有限功能。這樣的大多數函數都是以幫助函數的形式出現的,它會把命令傳遞給Pawn的骨架網格物體組件。以下解釋了這些函數。

註意: Mesh變量引用了Pawn的SkeletalMeshComponent,它包含了播放單獨的動畫序列相關的功能。請記住使用這個功能時要求在Pawn的AnimTree中的唯一的動畫節點是AnimNodeSequence 節點。這意味著您將失去AnimTree 系統的許多高級功能,比如混合;但是如果需要,這個功能是存在的。

  • SetMorphWeight [MorphNodeName] [MorphWieght] - 設置分配給Pawn的AnimTree 中的特定頂點變形節點的權重。
  • SetSkelControlScale [SkelControlName] [Scale] - 設置分配給Pawn的AnimTree 中的特定SkelControl節點的比例。
  • PlayActorFaceFXAnim [AnimSet] [GroupName] [SeqName] [SoundCueToPlay] - 這會導致Pawn 播放特定的FaceFX臉部動畫序列。
  • StopActorFaceFXAnim - 這會停止當前播放FaceFX臉部動畫序列。
  • IsActorPlayingFaceFXAnim - 這會返回一個布爾值,表明Pawn當前是否正在播放FaceFX臉部動畫。

相機視角 /瞄準

當Pawn是當前的視圖目標以及為玩家或NPC設置當前的目標時,這些函數包含了控制玩家的相機位置及方位的功能。

  • CalcCamera [DeltaTime] [out_CamLoc] [out_CamRot] [out_FOV] - 當從Pawn處開始查看時這個函數計算了相機的視角。這是玩家的主要相機計算。
  • GetDefaultCameraMode [controller] - 這個函數返回了這個Pawn使用的默認相機模式的名稱。通常在具有 Pawn 的時候由控制器進行調用。
  • ProcessViewRotation [deltaTime] [out_ViewRotation] [out_DeltaRot] - 這個函數處理玩家的視圖旋轉,返回最終的視圖旋轉值作為out_ViewRotation參數。可以從 PlayerController 的 UpdateRotation() 函數中調用它。
  • SetViewRotation [NewRotation] - 如果存在一個Controller則設置該Controller的旋轉值,如果不存在Controller ,則設置Pawn本身的旋轉值。
  • GetActorEyesViewPoint [out_Location] [out_Rotation] - 這返回了Pawn的眼睛的位置及方位或者玩家的視角。對於第一人稱視角來說,這和相機的位置及朝向一樣。它也是會從這裏開始執行大多數跟蹤的視點。
  • GetBaseAimRotation - 這個函數返回了沒有經過任何調整比如瞄準誤差、自動鎖定、附著等的Pawn的瞄準旋轉值Rotator。
  • GetAdjustedAimFor [Weapon] [StartFireLoc] - 這允許一個中間點來對基礎的瞄準旋轉值應用任何調整,比如瞄準誤差、自動瞄準等。默認情況下,這會把命令傳遞到Controller的GetAdjustedaimFor()函數。如果Pawn沒有Controller,那麽它將返回基礎的瞄準旋轉值。

玩家示例


為了示範使用自定義網格物體添加一個新的玩家控制的角色,我們將會使用3個新類: Pawn、PlayerController和GameInfo。這個示例的目標是展示創建由玩家控制的角色的基本知識。一旦您具有了基本的實現,您所需要做的就是簡單地使用已有的東西或添加您自己的自定義功能來創建一個適合您遊戲的新的角色。

技術分享

Player Pawn 類

在這個示例中,我們對新的Pawn類添加了一點新功能。我們決定給它設置一個內置的生命值再生功能。在Tick()函數中,有時會給Pawn的當前Health (生命值)添加指定量的生命值。為了完成這個功能,需要添加一些類變量,然後重載Tick函數,添加生命值再生功能。

UDNPawn.uc
class UDNPawn extends UTPawn;

var float ElapsedRegenTime;
var float RegenAmount;
var float RegenTime;

event Tick(float DeltaTime)
{
  //計算已經過去的時間
  ElapsedRegenTime += DeltaTime;

  //已經過去了足夠的時間量了嗎?
  if(ElapsedRegenTime >= RegenTime)
  {
    //治愈Pawn並充值已經過去的時間量
    HealDamage(RegenAmount, Controller, class‘DamageType‘);
    ElapsedRegenTime = 0.0f;
  }
}

defaultproperties
{
  //為再生屬性設置默認值
  RegenAmount=2
  RegenTime=1
}

Player Controllers(玩家控制器)類

新的PlayerController 類是UTPlayerController 類的子類。它簡單地添加了新的類成員變量來存放用作為玩家的角色類,然後通過使用現有的ServerSetCharacterClass()函數把它設置為玩家角色。

UDNPlayerController.uc
class UDNPlayerController extends UTPlayerController;

var class<UTFamilyInfo> CharacterClass;

simulated event PostBeginPlay()
{
  super.PostBeginPlay();

  SetupPlayerCharacter();
}

/** 設置玩家的角色信息類&執行任何其它的初始化*/
function SetupPlayerCharacter()
{
  //把角色設置為我們的自定義角色
  ServerSetCharacterClass(CharacterClass);
}

defaultproperties
{
  //把您的自定義角色指向UTFamilyInfo 類
  CharacterClass=class‘UTFamilyInfo_Liandri_Male‘
}

GameInfo類

為了滿足將要使用的新的Pawn和PlayerController 類,我們需要一種新的遊戲類型。當您使用UDK創建您自己的遊戲時,您大部分時候都會使用一個自定義的遊戲類型,以便您僅需要想那個類中添加一些適當的默認屬性即可,而不必創建一個新類。這個示例中,創建了新的遊戲類型,並簡單地設置DefaultPawnClass和PlayerControllerClass屬性指向新的Pawn和PlayerController 類。

UDNGame.uc
class UDNGame extends UTDeathMatch;

defaultproperties
{
  //指向您的自定義Pawn類
  DefaultPawnClass=class‘UDNPawn‘

  //指向您自定義的PlayerController類
  PlayerControllerClass=class‘UDNPlayerController‘
}

現在,如果我們使用這個新的遊戲類型運行一張地圖,當玩家受到傷害時它應該可以自動復原,並且使用自定義的角色。

NPC示例


為了演示簡單的AI控制的Pawn,需要創建一個新的 Pawn和Controller類。Pawn 類在虛幻編輯器中是可以放置的,並且它將會處理設置網格物體、動畫、物理屬性以及設置要使用的Controller類的工作。Controller將負責使NPC在世界中到處閑逛,每當NPC到達當前的目的地時再給它選擇一個隨機目的地。

技術分享

NPC Pawn類

Pawn類是非常簡單的。它添加了一些屬性,但是這些屬性僅是現有屬性的復制,這樣可以使得設計人員更加容易使用。使用一個SkeletalMeshComponent(骨架網格物體組件)來設置所有的可見屬性,比如網格物體、AnimTree、AnimSets、PhysicsAsset等。在默認屬性塊匯總設置這些屬性的默認值。類用於設置控制NPC所使用的Controller 類。PostBeginPlay()函數用於設置現有的ControllerClass 變量給新的NPCController變量。最後,重載 SetCharacterClassFromInfo() 函數,它沒有做任何事情,因為這個NPC實現不需要它。

類的完整代碼顯示在這裏:

UDNPawn_NPC.uc
class UDNPawn_NPC extends UTPawn
  placeable;

var(NPC) SkeletalMeshComponent NPCMesh;
var(NPC) class<AIController> NPCController;

simulated event PostBeginPlay()
{
  if(NPCController != none)
  {
    //為我們新的NPCController 類設置現有的ControllerClass
    ControllerClass = NPCController;
  }

  Super.PostBeginPlay();
}

//重載該函數並且不做任何操作
simulated function SetCharacterClassFromInfo(class<UTFamilyInfo> Info)
{
}

defaultproperties
{
  //設置默認的NPC網格物體
  Begin Object class="SkeletalMeshComponent" Name=NPCMesh0
    SkeletalMesh=SkeletalMesh‘CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode‘
    PhysicsAsset=PhysicsAsset‘CH_AnimCorrupt.Mesh.SK_CH_Corrupt_Male_Physics‘
    AnimSets(0)=AnimSet‘CH_AnimHuman.Anims.K_AnimHuman_BaseMale‘
    AnimtreeTemplate=AnimTree‘CH_AnimHuman_Tree.AT_CH_Human‘
  End Object
  NPCMesh=NPCMesh0
  Mesh=NPCMesh0
  Components.Add(NPCMesh0)

  //指向您的自定義AIController類 - 作為默認值
  NPCController=class‘UDNBot‘
}

NPC Controller 類

Controller類是關於最基本的導航實現的類。ExecuteWhatToDoNext()函數,它是主要的決策函數,我們重載了該函數使得可以持續地把Controller發送到Roaming(閑逛)狀態。這個狀態簡單地檢查目的地是否存在或者Pawn是否到達了當前的目的地,如果必要可以設置新的目的地,然後告訴Controller向那個目的地運動。最後,調用LatentWhatToDoNext()函數來時的在下一個tick(更新)時再次調用ExecuteWhatToDoNext()函數,從而可以再次重新啟動所有的決策循環。

controller類的完整代碼顯示在這裏:

UDNBot.uc
class UDNBot extends UTBot;

var Actor Destination;

protected event ExecuteWhatToDoNext()
{
  //跳轉到roaming(閑逛)狀態
  GotoState(‘Roaming‘);
}

state Roaming
{
Begin:
  //如果我們剛剛開始或者我們已經到達了特定目的地
  //隨機地獲取一個新的目的地
  if(Destination == none || Pawn.ReachedDestination(Destination))
  {
    Destination = FindRandomDest();
  }

  //找到一條到達目的地的路徑,並移動到這個路徑的下一個節點。
  MoveToward(FindPathToward(Destination), FindPathToward(Destination));

  //啟動下一個決策循環
  LatentWhatToDoNext();
}

defaultproperties
{
}

測試新的自定義NPC


您的新的NPC類別可以在Actor Classes(Actor 類別)中找到。可以使用搜索控件輕松地進行查找。

技術分享

一旦在內容瀏覽器的Actor列表標簽中選中了該actor,那麽您現在就可以在遊戲視口中右擊來彈出關聯菜單。在關聯菜單中,選擇菜單項 Add UDN_PawnNPC Here(在這裏添加UDN_PawnNPC)

技術分享

現在,該NPC就在世界中了。您可以使用PIE(在編輯器中播放)功能來測試遊戲。

技術分享

(官網)虛幻3--角色技術指南