mcpField
U
ue-character-movement

ue-character-movement

github.com/quodsoler開発4191.2k 回インストール4 週間前に更新
リポジトリ

ue-character-movement について

UE 5.8 の ACharacter と UCharacterMovementComponent を扱う開発者向けスキルです。移動シミュレーション、自作モード、ネットワーク予測、ルートモーション、5.8 の移動ベース変更を解説します。

主な機能

  1. 01移動モードと遷移
  2. 02床検出と段差乗り越え
  3. 03カスタム移動モード
  4. 04ネットワーク予測と補正
  5. 05ルートモーションとカスタム重力
  6. 06UE 5.8 の移動ベース API

活用シーン

  1. 01壁走りやクライミングの実装
  2. 02マルチプレイヤー移動補正の調査
  3. 03キャラクターを足場に追従させる
  4. 04CMC と Mover の選択

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/quodsoler/unreal-engine-skills --skill ue-character-movement

インストール後、Claude Code で/ue-character-movementを入力して読み込まれたか確認します。

同梱ファイルreferences/cmc-extension-patterns.mdreferences/movement-pipeline.md

詳細

UE Character Movement

対象エンジン:UE 5.8。以下の API は 5.8 のヘッダーで検証済みです。旧形式は「非推奨 — 使用しないでください」に記載しています。

このスキルでは、UCharacterMovementComponent(CMC)と ACharacter を扱います。移動モードのパイプライン、床の検出とステップアップ、カスタム移動モード、クライアント側の予測と補正、ルートモーション、カスタム重力、5.8 での移動ベースの再設計が対象です。ここに記載されている機能はすべて Engine モジュールに含まれており、プラグインも "Engine" 以外の Build.cs エントリーも必要ありません。公開ヘッダー:GameFramework/CharacterMovementComponent.h(GameFramework/RootMotionSource.h、GameFramework/CharacterMovementReplication.h、CharacterMovementComponentAsync.h、Interfaces/MovementBaseInterface.h をすでに取り込みます)、GameFramework/Character.h。

コンテキスト

存在する場合は .agents/ue-project-context.md を読みます(モジュール名、規約、有効なプラグイン、GAS/ネットワークの構成)。ファイルがなくても作業を中断しないでください。

依頼内容とコードベースから該当領域を特定します。解釈が複数あり、それぞれで異なるコードになる場合に限り、質問してください。

依頼内容参照先
CMC と Mover プラグインの選択CMC と Mover
クラス階層、移動モード、モード遷移CMC のアーキテクチャ
リフト、回転台、乗り物、物理ボディの上に立つ移動ベース
ティックの処理先、PhysWalking/PhysFalling、スイープ、スライド移動パイプライン
床をすり抜ける、ステップアップ、歩行可能な角度、縁での支持床の検出
壁走り、クライミング、ダッシュ、グラップルなど、新しい移動タイプカスタム移動モード
マルチプレイヤーの同期ずれ、ラバーバンド現象、保存ムーブ、圧縮フラグネットワーク予測
ノックバック、ダッシュ、アニメーション駆動の移動ルートモーション
壁や天井での歩行、惑星の重力カスタム重力
AI エージェント、ナビメッシュ駆動の歩行、RVO 回避NavMesh による歩行
ゲームプレイコードからのジャンプ/しゃがみ/発射ACharacter API
速度、摩擦、ブレーキ、回転フラグ主要なプロパティ

詳細なテンプレートは cmc-extension-patterns.md に、モードごとの内部処理とフロー図は movement-pipeline.md にあります。

CMC と Mover

Mover(5.8 では Experimental)は、UMoverComponent、UBaseMovementMode、FLayeredMoveBase、UCharacterMoverComponent を中心に構築された別個のプラグイン(Mover。デフォルトでは有効になっていません)です。CMC とそのまま置き換えられるものではありません。

状況使用するもの
リリース予定のタイトル、エンジン対応のすべてのプラットフォームCMC
既存の ACharacter 階層で、アニメーションや AI がすでに CMC に接続されているCMC
現時点で安定性が必須のネットワークゲームプレイCMC
ロールバックネットワーク対応を必要とする、カプセル型でも人型でもない移動体(乗り物、ドローン)Mover
Phys* サブクラスではなく、データ駆動のモード/モディファイアを組み合わせた移動Mover
Chaos を使用して物理スレッド上でシミュレーションする移動Mover(ChaosMover)
Experimental API の変更を許容できるプロトタイプMover

Mover の詳細は ue-mover を参照してください。同じポーンに両方のコンポーネントを混在させないでください。

CMC のアーキテクチャ

UActorComponent -> UMovementComponent -> UNavMovementComponent -> UPawnMovementComponent -> UCharacterMovementComponent

UNavMovementComponent は INavMovementInterface も実装します。UCharacterMovementComponent はさらに IRVOAvoidanceInterface と INetworkPredictionInterface を実装し、UCLASS(MinimalAPI) として宣言されています。

CMC は ACharacter のデフォルトサブオブジェクトです(ACharacter::CharacterMovementComponentName)。ACharacter はカプセル、メッシュ、高レベルの操作(Jump、Crouch、LaunchCharacter)を所有し、CMC はシミュレーション、床の検出、予測を担当します。

移動モード

EMovementMode(Engine/EngineTypes.h):

モード説明
MOVE_None移動処理を行いません
MOVE_Walking床の検出と段差の乗り越えを行う地上移動
MOVE_NavWalkingナビメッシュへの投影によって制御される歩行
MOVE_Falling空中状態:重力、空中制御、着地
MOVE_Swimming浮力を伴う液体中の移動
MOVE_Flying重力のない自由な 3D 移動
MOVE_Customユーザー定義。uint8 のサブモードを指定して PhysCustom にディスパッチします
// UCharacterMovementComponent. SetMovementMode is BlueprintCallable;
// OnMovementModeChanged is protected and not a UFUNCTION (override it in C++)
virtual void SetMovementMode(EMovementMode NewMovementMode, uint8 NewCustomMode = 0);
virtual void OnMovementModeChanged(EMovementMode PreviousMovementMode, uint8 PreviousCustomMode);

ACharacter::OnMovementModeChanged(EMovementMode PrevMovementMode, uint8 PreviousCustomMode = 0) は、CMC フックの後に呼び出され、MovementModeChangedDelegate(FMovementModeChangedSignature)をブロードキャストします。カスタムモードの開始・終了処理は CMC のオーバーライドに記述してください。現在のサブモードは uint8 CustomMovementMode メンバーです。

移動ベース

移動ベースとは、キャラクターが上に立ち、その動きに追従するオブジェクトです。5.8 では、移動ベースは UPrimitiveComponent* ではなくなり、FMovementBaseInterfaceData(Interfaces/MovementBaseInterface.h)になりました。これは TWeakObjectPtr<UObject> PhysicsObjectOwner と、ベースの動作を提供する IPhysicsBodyInstanceOwner を保持します。これにより、コンポーネント以外の物理オブジェクトもベースとして使用できます。

ベースの取得
// UCharacterMovementComponent
UObject* GetMovementBaseObject() const;                                    // BlueprintCallable
const FMovementBaseInterfaceData* GetMovementBaseInterfaceData() const;
FMovementBaseInterfaceData* GetMovementBaseInterfaceData_Mutable();
const FMovementBaseInterfaceData* GetLastServerMovementBaseInterfaceData() const;

APawn は GetMovementBaseObject()、GetMovementBaseInterfaceData()、GetMovementBaseInterfaceData_Mutable() を宣言しており、ACharacter はこれら 3 つすべてを final としてオーバーライドします。FMovementBaseInterfaceData 自体は、IsValid()、Clear()、Set()、GetBodyInstanceOwner()、GetMovementBaseObject()、GetMovementBaseObjectOwner() を公開しています。

static void MyLogCurrentBase(const UCharacterMovementComponent& Movement)
{
    const FMovementBaseInterfaceData* BaseData = Movement.GetMovementBaseInterfaceData();
    if (!MovementBaseUtility::IsMovementBaseDataValid(BaseData))
    {
        return;
    }

    const FName BoneName = Movement.GetCharacterOwner()->GetBasedMovement().BoneName;
    const FVector BaseVelocity = MovementBaseUtility::GetMovementBaseVelocity(BaseData, BoneName);

    // Component-specific work now needs an explicit cast.
    if (const UPrimitiveComponent* BaseComponent = Cast<UPrimitiveComponent>(BaseData->GetMovementBaseObject()))
    {
        UE_LOG(LogMyGame, Verbose, TEXT("Based on %s at %s"), *BaseComponent->GetName(), *BaseVelocity.ToString());
    }
}
ベースの設定
virtual void SetBase(FMovementBaseInterfaceData* MovementBaseInterfaceData, const FName BoneName = NAME_None, bool bNotifyActor = true); // CMC and ACharacter
void SetBaseFromFloor(const FFindFloorResult& FloorResult);                                                                             // CMC

すでに保持している情報から構造体を構築します。

FMovementBaseInterfaceData NewBase = MovementBaseUtility::GetMovementBaseDataFromHitResult(&Hit);
SetBase(&NewBase, Hit.BoneName);

MovementBaseUtility::GetMovementBaseDataFromPhysicsOwner(UObject*) は、レプリケートされた PhysicsObjectOwner から同様にデータを取得します。

ユーティリティ名前空間

MovementBaseUtility の各ヘルパーは、UPrimitiveComponent* ではなく FMovementBaseInterfaceData* を受け取るようになりました。対象は IsDynamicBase、IsSimulatedBase、UseRelativeLocation、AddTickDependency、RemoveTickDependency、GetMovementBaseVelocity、GetMovementBaseTangentialVelocity、GetMovementBaseTransform、TransformLocationToWorld、TransformLocationToLocal、TransformDirectionToWorld、TransformDirectionToLocal です。5.8 で追加:DoesMovementBaseDataMatch、IsMovementBaseDataValid、GetMovementBaseDataFromPhysicsOwner、GetMovementBaseDataFromHitResult。

保存・レプリケートされるベースの状態
旧メンバー5.8 のメンバー保持先
MovementBaseMovementBaseInterfaceDataFBasedMovementInfo
MovementBasePhysicsObjectOwnerFRepRootMotionMontage
MovementBaseMovementBasePhysicsObjectOwnerFCharacterNetworkMoveData
StartBase / EndBaseStartMovementBaseInterfaceData / EndMovementBaseInterfaceDataFSavedMove_Character
LastServerMovementBaseLastMovementBaseInterfaceDataUCharacterMovementComponent

以前は UPrimitiveComponent* ClientMovementBase を受け取っていたサーバー権限関連および補正関連のすべての仮想関数に、FMovementBaseInterfaceData* を受け取るオーバーロードが追加されました。対象は ServerMoveHandleClientError、ServerCheckClientError、ServerExceedsAllowablePositionError、ServerShouldUseAuthoritativePosition、ClientAdjustPosition_Implementation、ClientVeryShortAdjustPosition_Implementation、ClientAdjustRootMotionPosition_Implementation、ClientAdjustRootMotionSourcePosition_Implementation、OnClientCorrectionReceived(および非仮想関数の RevertMove)です。新しいオーバーロードをオーバーライドしてください。非推奨のオーバーロードをオーバーライドすると、呼び出されなくなります。

通知フックは ACharacter::BaseChange() と ACharacter::OnRep_ReplicatedBasedMovement() です。ACharacter::GetBasedMovement() は FBasedMovementInfo を返します。

移動パイプライン

PerformMovement(float DeltaTime)(protected)は自律移動経路のエントリーポイントです。シミュレートされたプロキシはSimulatedTickを経由し、ルートモーションが有効な場合に限りPerformMovementを呼び出し、それ以外の場合はPhys*関数をスキップするMoveSmoothによる外挿処理であるSimulateMovementを呼び出します。PerformMovementはStartNewPhysics(float deltaTime, int32 Iterations)に到達し、MovementModeに応じて処理を振り分けます。すべてのPhys*関数はvirtualです。PhysFallingはpublic(CharacterMovementComponent.h:1663)、ほかの5つはprotected(:1995-2007)です。

virtual void PhysWalking(float deltaTime, int32 Iterations);
virtual void PhysNavWalking(float deltaTime, int32 Iterations);
virtual void PhysFalling(float deltaTime, int32 Iterations);
virtual void PhysSwimming(float deltaTime, int32 Iterations);
virtual void PhysFlying(float deltaTime, int32 Iterations);
virtual void PhysCustom(float deltaTime, int32 Iterations);

Phys*関数内では、次のように処理します。

// BlueprintCallable
virtual void CalcVelocity(float DeltaTime, float Friction, bool bFluid, float BrakingDeceleration);

// UMovementComponent; also has an FRotator overload
virtual bool SafeMoveUpdatedComponent(const FVector& Delta, const FQuat& NewRotation, bool bSweep,
                                      FHitResult& OutHit, ETeleportType Teleport = ETeleportType::None);

SafeMoveUpdatedComponentはMoveUpdatedComponentをラップし、初期オーバーラップ時にResolvePenetrationを呼び出します。カスタムのPhys*コード内では、常にこちらを使用してください。これをオーバーライドする場合、FRotatorオーバーロードが隠れないように、宣言の隣にusing UMovementComponent::SafeMoveUpdatedComponent;を追加してください。

ブロッキングヒットが発生すると、CMCのSlideAlongSurface(const FVector& Delta, float Time, const FVector& Normal, FHitResult& Hit, bool bHandleImpact)オーバーライドが、残りのデルタを面に沿って投影します(また、歩行中は歩行不可能な斜面を上る方向へのスライドを拒否します)。角でのヒットはTwoWallAdjust(FVector& WorldSpaceDelta, const FHitResult& Hit, const FVector& OldHitNormal) constを経由します。歩行中はComputeGroundMovementDelta(const FVector& Delta, const FHitResult& RampHit, const bool bHitFromLineTrace) constがデルタの向きを斜面に沿うように変更し、その後MaintainHorizontalGroundVelocity()が速度を平坦化します(bMaintainHorizontalGroundVelocityがfalseの場合は、大きさを保つようにスケーリングし直します)。

SetUpdatedComponent(USceneComponent* NewUpdatedComponent)はCMCでオーバーライドされており、移動対象のコンポーネント(カプセル)をバインドし、ティックを再登録します。サブステップはMaxSimulationTimeStepとMaxSimulationIterationsによって制限されます。MIN_TICK_TIMEは、スライスが破棄される最小値です。CMCは、FCharacterMovementComponentAsyncInput/FCharacterMovementComponentAsyncOutput/FCharacterMovementComponentAsyncCallbackを通じて、CVar p.AsyncCharacterMovement(デフォルトは0。エンジンでは未完成の機能として扱われています)のもと、シミュレーション全体を物理スレッドで実行することもできます。ただし、カスタムのPhys*状態はこの経路に自動的には反映されません。移動モードごとの詳細と非同期処理の仕組みについては、movement-pipeline.mdを参照してください。

床の検出

FFindFloorResultはCMCのヘッダーではなく、CharacterMovementComponentAsync.h(USTRUCT(BlueprintType))にあります。

メンバー意味
bBlockingHit初期貫通ではなく、スイープが何かにヒットした
bWalkableFloorヒットした面が歩行可能性の判定を通過した
bLineTrace結果がライン・トレースのフォールバックによるもの
FloorDistスイープしたカプセルからの距離
LineDistライン・トレースからの距離(bLineTraceがtrueの場合のみ有効)
HitResult完全なFHitResult

ヘルパー:IsWalkableFloor()(bBlockingHit && bWalkableFloor)、GetDistanceToFloor()、Clear()、SetFromSweep()、SetFromLineTrace()。

// Both are const on UCharacterMovementComponent
virtual void FindFloor(const FVector& CapsuleLocation, FFindFloorResult& OutFloorResult,
                       bool bCanUseCachedLocation, const FHitResult* DownwardSweepResult = NULL) const;

virtual void ComputeFloorDist(const FVector& CapsuleLocation, float LineDistance, float SweepDistance,
                              FFindFloorResult& OutFloorResult, float SweepRadius,
                              const FHitResult* DownwardSweepResult = NULL) const;

FindFloorはComputeFloorDistに処理を委譲します(下向きのカプセルスイープを行い、その後、接触点を検証するためにライン・トレースを行います)。キャッシュされた結果はCurrentFloorです。AdjustFloorHeight()は、カプセルをMIN_FLOOR_DISTとMAX_FLOOR_DISTの間にスナップします。

歩行可能性は、WalkableFloorAngle(度単位、0~90にクランプ)と、そこから導出されるWalkableFloorZ(デフォルトは0.71、約44.8度)で制御します。角度はSetWalkableFloorAngle(float)を通じて設定してください。WalkableFloorZを直接書き換えると、2つの値の同期が崩れます。virtual bool IsWalkable(const FHitResult& Hit) constは、面ごとのルールを定義するためのオーバーライドポイントです。

段差を上る処理は、MaxStepHeightによって制限されるvirtual bool StepUp(const FVector& GravDir, const FVector& Delta, const FHitResult& Hit, FStepDownResult* OutStepDownResult = NULL)を通じて実行されます。段差の端に乗る際の挙動は、PerchRadiusThresholdとPerchAdditionalHeightによって制御されます。

カスタム移動モード

MOVE_Custom と uint8 CustomMovementMode の組み合わせにより、CMC の予測パイプラインを再利用する 256 個のサブモードを利用できます。

// MyCharacterMovement.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "MyCharacterMovement.generated.h"

UENUM(BlueprintType)
enum class EMyMovementMode : uint8
{
    None      = 0,
    Climbing  = 1,
    Dash      = 2
};

UCLASS()
class MYGAME_API UMyCharacterMovement : public UCharacterMovementComponent
{
    GENERATED_BODY()

public:
    UMyCharacterMovement();

    UPROPERTY(Transient)
    uint8 bWantsToClimb : 1;

    UPROPERTY(Transient)
    FVector ClimbSurfaceNormal;

    virtual void PhysCustom(float deltaTime, int32 Iterations) override;
    virtual void OnMovementModeChanged(EMovementMode PreviousMovementMode, uint8 PreviousCustomMode) override;
    virtual float GetMaxSpeed() const override;

protected:
    void PhysClimb(float deltaTime, int32 Iterations);
};
void UMyCharacterMovement::PhysCustom(float deltaTime, int32 Iterations)
{
    Super::PhysCustom(deltaTime, Iterations);   // dispatches ACharacter::K2_UpdateCustomMovement

    if (CustomMovementMode == static_cast<uint8>(EMyMovementMode::Climbing))
    {
        PhysClimb(deltaTime, Iterations);
    }
}

Super::PhysCustom(deltaTime, Iterations) は最初に呼び出してください。基底実装は ACharacter::K2_UpdateCustomMovement(float DeltaTime) に処理を渡すため、呼び出しを省略したり最後に呼び出したりすると、Blueprint フックと、後から追加される基底クラスの処理が正しく動作しなくなります。このスキルでは、呼び出し順序をこのように定めています。

SetMovementMode(MOVE_Custom, static_cast<uint8>(EMyMovementMode::Climbing)) と SetMovementMode(MOVE_Falling) でモードに入る/モードを抜けます。virtual float GetMaxSpeed() const override をオーバーライドして速度に上限を設定します(基底クラスは MOVE_Custom の場合、MaxCustomMovementSpeed を返します)。予測機能を備えた完全なクライミングモードについては、cmc-extension-patterns.md を参照してください。

ネットワーク予測

自律クライアントはローカルでシミュレーションを実行し、各フレームを FSavedMove_Character として記録してサーバーに送信します。サーバーから修正を受け取ると、未確認の移動をリプレイします。保存と復元が行われないカスタム移動状態は、リプレイ時に失われます。通信処理自体(RPC のルール、ロール、関連性、プッシュモデル)は ue-networking-replication の対象です。

FSavedMove_Character

便利なフィールド:bPressedJump、bWantsToCrouch、bForceMaxAccel、bForceNoCombine、TimeStamp、DeltaTime、StartLocation、StartVelocity、StartFloor、StartRotation、StartControlRotation、StartMovementBaseInterfaceData、SavedLocation、SavedVelocity、EndMovementBaseInterfaceData、Acceleration、MaxSpeed、SavedRootMotion。

オーバーライドする仮想関数(原文のまま):

virtual void Clear();
virtual void SetMoveFor(ACharacter* C, float InDeltaTime, FVector const& NewAccel, class FNetworkPredictionData_Client_Character& ClientData);
virtual void PrepMoveFor(ACharacter* C);
virtual uint8 GetCompressedFlags() const;
virtual bool CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, float MaxDelta) const;
virtual void PostUpdate(ACharacter* C, EPostUpdateMode PostUpdateMode);
virtual bool IsImportantMove(const FSavedMovePtr& LastAckedMove) const;
virtual void CombineWith(const FSavedMove_Character* OldMove, ACharacter* InCharacter, APlayerController* PC, const FVector& OldStartLocation);
圧縮フラグ

FSavedMove_Character::CompressedFlags はネストされた enum です。

フラグ値用途
FLAG_JumpPressed0x01ジャンプ入力
FLAG_WantsToCrouch0x02しゃがみ入力
FLAG_Reserved_10x04エンジン用に予約済み
FLAG_Reserved_20x08エンジン用に予約済み
FLAG_Custom_00x10独自用途
FLAG_Custom_10x20独自用途
FLAG_Custom_20x40独自用途
FLAG_Custom_30x80独自用途

GetCompressedFlags() でフラグをパックし、CMC の virtual void UpdateFromCompressedFlags(uint8 Flags) でアンパックします。使えるのは合計 4 ビットです。それを超えるデータはカスタム移動データで送信します。

予測データ

FNetworkPredictionData_Client_Character は SavedMoves、FreeMoves、PendingMove、LastAckedMove、MaxSavedMoveCount、およびメッシュのスムージングオフセットを保持します。virtual FSavedMovePtr AllocateNewMove() をオーバーライドして独自サブクラスを返し、virtual class FNetworkPredictionData_Client* GetPredictionData_Client() const override でデータを必要に応じて作成します(CMC メンバーは ClientPredictionData、型付きアクセサーは GetPredictionData_Client_Character() です)。

パック済み移動 RPC

移動 RPC は ACharacter にあります。

void ServerMovePacked(const FCharacterServerMovePackedBits& PackedBits);          // Server, unreliable, WithValidation
void ClientMoveResponsePacked(const FCharacterMoveResponsePackedBits& PackedBits); // Client, unreliable, WithValidation

4 つのカスタムフラグに収まらない状態を送るには、FCharacterNetworkMoveData を派生させ(ClientFillNetworkMoveData(const FSavedMove_Character& ClientMove, ENetworkMoveType MoveType) と Serialize(UCharacterMovementComponent&, FArchive&, UPackageMap*, ENetworkMoveType) をオーバーライド)、FCharacterNetworkMoveDataContainer を派生させて NewMoveData/PendingMoveData/OldMoveData の参照先を変更します。その後、コンポーネントより長く存続するコンテナを使って、CMC のコンストラクターで SetNetworkMoveDataContainer(...) を呼び出します。GetCurrentNetworkMoveData() を使うと、MoveAutonomous または UpdateFromCompressedFlags 内からアクティブなデータにアクセスできます。応答側も FCharacterMoveResponseDataContainer と SetMoveResponseDataContainer(...) で同様に実装します。テンプレートについては、cmc-extension-patterns.md を参照してください。

ルートモーション

FRootMotionSource(GameFramework/RootMotionSource.h)は、ゲームプレイコードから移動を駆動します。基本フィールド:Priority(uint16、値が大きいほど優先)、LocalID(uint16)、InstanceName、Duration(負の値の場合は削除されるまで実行)、AccumulateMode(ERootMotionAccumulateMode::Override または Additive)、FinishVelocityParams(ERootMotionFinishVelocityMode)。

構造体主なフィールド用途
FRootMotionSource_ConstantForceForce、StrengthOverTimeノックバック、風
FRootMotionSource_RadialForceLocation、LocationActor、Radius、Strength、bIsPush、bNoZForce爆発、渦
FRootMotionSource_MoveToForceStartLocation、TargetLocation、PathOffsetCurve固定位置へのダッシュ
FRootMotionSource_MoveToDynamicForceStartLocation、SetTargetLocation()ホーミングダッシュ
FRootMotionSource_JumpForceRotation、Distance、Height、TimeMappingCurve目標に向かうジャンプの軌道
// UCharacterMovementComponent
uint16 ApplyRootMotionSource(TSharedPtr<FRootMotionSource> SourcePtr);
TSharedPtr<FRootMotionSource> GetRootMotionSource(FName InstanceName);
TSharedPtr<FRootMotionSource> GetRootMotionSourceByID(uint16 RootMotionSourceID);
void RemoveRootMotionSource(FName InstanceName);
void RemoveRootMotionSourceByID(uint16 RootMotionSourceID);
bool HasRootMotionSources() const;
TSharedPtr<FRootMotionSource_ConstantForce> Knockback = MakeShared<FRootMotionSource_ConstantForce>();
Knockback->InstanceName = TEXT("Knockback");
Knockback->Duration = 0.3f;
Knockback->Force = KnockbackDirection * KnockbackStrength;
Knockback->AccumulateMode = ERootMotionAccumulateMode::Override;
Knockback->Priority = 5;
GetCharacterMovement()->ApplyRootMotionSource(Knockback);

アクティブなソースは CurrentRootMotion(FRootMotionSourceGroup)に格納され、virtual void ApplyRootMotionToVelocity(float deltaTime) によって速度に反映されます。アニメーションルートモーションは別の経路です。アニメーショングラフから設定される RootMotionParams(FRootMotionMovementParams)を HasAnimRootMotion() で確認し、FRepRootMotionMontage を通じて複製します。モンタージュの作成と UAnimInstance::SetRootMotionMode については、ue-animation-system を参照してください。

カスタム重力

virtual void SetGravityDirection(const FVector& GravityDir);
bool HasCustomGravity() const;
FVector GetGravityDirection() const;
FQuat GetWorldToGravityTransform() const;
FQuat GetGravityToWorldTransform() const;
FVector RotateGravityToWorld(const FVector& World) const;
FVector RotateWorldToGravity(const FVector& Gravity) const;
FVector ProjectToGravityFloor(const FVector& Vector) const;
FVector::FReal GetGravitySpaceZ(const FVector& Vector) const;
void SetGravitySpaceZ(FVector& Vector, const FVector::FReal Z) const;

GravityDirection、WorldToGravityTransform、GravityToWorldTransform、bHasCustomGravity は protected です。必ずアクセサーを使用し、キャッシュされたクォータニオンが再構築されるように、方向は必ず SetGravityDirection で設定してください。デフォルト値は UCharacterMovementComponent::DefaultGravityDirection です。HasCustomGravity() が true の場合、歩行、落下、床の検出はすべて重力空間で行われます。カスタムの Phys* コードでは、ハードコードされた Z の演算ではなく、ProjectToGravityFloor / GetGravitySpaceZ を使用してください。

NavMesh 上の歩行

MOVE_NavWalking はワールドジオメトリに対するスイープの代わりに、カプセルを NavMesh に投影します。群衆でははるかに低コストであり、AI キャラクターが何もない場所に立てる理由でもあります。FindNavFloor(const FVector& TestLocation, FNavLocation& NavFloorLocation) const が投影を実行します。

プロパティ効果
bProjectNavMeshWalking下にあるジオメトリへレイキャストし、高さを合わせます
bProjectNavMeshOnBothWorldChannelsそのレイキャストに WorldStatic と WorldDynamic を使用します
bSlideAlongNavMeshEdge点を投影してそこへ移動する代わりに、NavMesh のエッジに沿ってスライドします

回避処理:bUseRVOAvoidance、AvoidanceWeight、AvoidanceGroup(FNavAvoidanceMask)は、SetAvoidanceGroupMask(const FNavAvoidanceMask&) で設定します。ナビゲーションデータ、クエリ、経路探索については、ue-ai-navigation を参照してください。

主なプロパティ

プロパティデフォルト値説明
MaxWalkSpeed600地上での速度上限
MaxWalkSpeedCrouched300デフォルトでは MaxWalkSpeed の半分
MaxSwimSpeed300
MaxFlySpeed600
MaxCustomMovementSpeed600MOVE_Custom において GetMaxSpeed() が返す上限
MaxAcceleration2048
BrakingDecelerationWalking2048デフォルトでは MaxAcceleration と同じ
GroundFriction8
GravityScale1ワールドの重力に対する倍率
JumpZVelocity420
AirControl0.05落下中の横方向の操作性
MaxStepHeight45
WalkableFloorZ0.71約44.8度。SetWalkableFloorAngle で設定
MaxSimulationTimeStep0.05サブステップの上限
MaxSimulationIterations8フレームあたりのサブステップ数
NetworkSmoothingModeExponential (CharacterMovementComponent.cpp:718)ENetworkSmoothingMode::Disabled、Linear、Exponential
bOrientRotationToMovementfalse速度の向きに合わせて回転
bUseControllerDesiredRotationfalseコントローラーの回転に合わせて回転

bOrientRotationToMovement と bUseControllerDesiredRotation は毎フレーム互いに競合するため、どちらか一方を選んでください。

ACharacter API

virtual void Jump();                                     // BlueprintCallable, sets bPressedJump
virtual void StopJumping();                              // BlueprintCallable
bool CanJumpInternal() const;                            // BlueprintNativeEvent, DisplayName "CanJump"
virtual bool CanJumpInternal_Implementation() const;     // override this
virtual void LaunchCharacter(FVector LaunchVelocity, bool bXYOverride, bool bZOverride);
virtual void Landed(const FHitResult& Hit);
virtual void Crouch(bool bClientSimulation = false);
virtual void UnCrouch(bool bClientSimulation = false);

ジャンプ状態:bPressedJump、JumpMaxHoldTime、JumpMaxCount、JumpCurrentCount、JumpCurrentCountPreJump。CMC 側には virtual bool DoJump(bool bReplayingMoves, float DeltaTime) と virtual bool CanAttemptJump() const があります。Blueprint イベント:OnLanded、OnLaunched、OnWalkingOffLedge、OnReachedJumpApex。

bXYOverride/bZOverride は、対応する速度成分に加算するのではなく置き換えます。LaunchCharacter は UCharacterMovementComponent::Launch(FVector const&) と HandlePendingLaunch() を経由します。

しゃがみ:bIsCrouched はレプリケートされるフラグです。カプセルの半高は、CMC の SetCrouchedHalfHeight(const float)/GetCrouchedHalfHeight() で設定・取得します。

アクセサー:GetCharacterMovement()、GetCapsuleComponent()(UCapsuleComponent)、GetMesh()(USkeletalMeshComponent)。

非推奨 — 使用しないでください

使用しないもの5.8 で使用するものソース
ACharacter::GetMovementBase()GetMovementBaseObject() / GetMovementBaseInterfaceData()GameFramework/Character.h の UE_DEPRECATED(5.8)
UCharacterMovementComponent::GetMovementBase()GetMovementBaseObject()GameFramework/CharacterMovementComponent.h の UE_DEPRECATED(5.8)
SetBase(UPrimitiveComponent*, FName, bool)SetBase(FMovementBaseInterfaceData*, FName, bool)Character.h、CharacterMovementComponent.h の UE_DEPRECATED(5.8)
const UPrimitiveComponent* を受け取る MovementBaseUtility ヘルパー全般同名で const FMovementBaseInterfaceData* を受け取るもの(旧形式では AddTickDependency/RemoveTickDependency は非 const の UPrimitiveComponent* を受け取ります)Character.h の UE_DEPRECATED(5.8)
FBasedMovementInfo::MovementBaseFBasedMovementInfo::MovementBaseInterfaceDataCharacter.h の UE_DEPRECATED(5.8)
FRepRootMotionMontage::MovementBaseFRepRootMotionMontage::PhysicsObjectOwnerCharacter.h の UE_DEPRECATED(5.8)
FCharacterNetworkMoveData::MovementBaseMovementBasePhysicsObjectOwnerGameFramework/CharacterMovementReplication.h の UE_DEPRECATED(5.8)
FSavedMove_Character::StartBase/EndBaseStartMovementBaseInterfaceData/EndMovementBaseInterfaceDataCharacterMovementComponent.h の UE_DEPRECATED(5.8)
GetLastServerMovementBase()/LastServerMovementBaseGetLastServerMovementBaseInterfaceData()/LastMovementBaseInterfaceDataCharacterMovementComponent.h の UE_DEPRECATED(5.8)
ServerMoveHandleClientError、ServerCheckClientError、ClientAdjustPosition_Implementation、RevertMove およびその他の UPrimitiveComponent* 修正用仮想関数FMovementBaseInterfaceData* オーバーロードCharacterMovementComponent.h の UE_DEPRECATED(5.8)
DoJump(bool bReplayingMoves)DoJump(bool bReplayingMoves, float DeltaTime)CharacterMovementComponent.h の UE_DEPRECATED_FORGAME(5.5)
パブリックな CrouchedHalfHeightSetCrouchedHalfHeight()/GetCrouchedHalfHeight()CharacterMovementComponent.h の UE_DEPRECATED_FORGAME(5.0)
SetAvoidanceGroup(int32)SetAvoidanceGroupMask(const FNavAvoidanceMask&)CharacterMovementComponent.h の meta=(DeprecatedFunction)
UNavMovementComponent::bUseAccelerationForPaths、FixedPathBrakingDistance、bUpdateNavAgentWithOwnersCollision、bUseFixedBrakingDistanceForPaths、bStopMovementAbortPaths対応する NavMovementProperties.* フィールドGameFramework/NavMovementComponent.h の UE_DEPRECATED(5.5)
ServerMove、ServerMoveDual、ServerMoveOld、ClientAdjustPosition、ClientAckGoodMove RPCServerMovePacked/ClientMoveResponsePackedCharacterMovementReplication.h の DEPRECATED_CHARACTER_MOVEMENT_RPC(SUPPORT_DEPRECATED_CHARACTER_MOVEMENT_RPCS の既定値は 0)

よくある間違い

移動ベースをコンポーネントとして扱う: GetMovementBase() は非推奨であり、FBasedMovementInfo::MovementBase にはベースが保持されなくなりました。GetMovementBaseInterfaceData() を読み取り、UPrimitiveComponent が本当に必要な場合に限り GetMovementBaseObject() をキャストしてください。

UPrimitiveComponent* の補正用仮想関数をオーバーライドする: 非推奨の ServerCheckClientError/ClientAdjustPosition_Implementation オーバーロードをオーバーライドするサブクラスはコンパイルできますが、呼び出されることはありません。そのため、補正は気づかないうちに基底クラスの動作にフォールバックします。FMovementBaseInterfaceData* のオーバーロードをオーバーライドしてください。

Super::PhysCustom を最後に呼び出す、またはまったく呼び出さない: 基底実装は ACharacter::K2_UpdateCustomMovement に転送します。まずこれを呼び出し、その後でモードを実行してください。

CalcVelocity を使わずに Velocity を直接書き換える: 摩擦、ブレーキ、加速度のクランプが回避されます。

// WRONG
Velocity = GetLastInputVector() * MaxWalkSpeed;
// RIGHT
CalcVelocity(DeltaTime, GroundFriction, false, BrakingDecelerationWalking);

カスタム Phys* コードで MoveUpdatedComponent を使用する: 初期貫通を解決しないため、カプセルがジオメトリに引っかかります。SafeMoveUpdatedComponent を使用してください。

カスタム状態を FSavedMove_Character に保存しない: SetMoveFor でキャプチャーし、PrepMoveFor で復元しないデータは、補正後の再生時に失われます。その結果、レイテンシーがある場合にのみラバーバンド現象が発生します。

スタックローカルのネットワーク移動データコンテナを再利用する: SetNetworkMoveDataContainer はポインターを保存します。スコープを抜けたコンテナは、CMC 上にダングリングポインターを残します。

WalkableFloorZ を直接設定する: これは WalkableFloorAngle から計算されます。両者の整合性を保つため、SetWalkableFloorAngle() を呼び出してください。

カスタム重力が有効な状態で Z をハードコードする: Velocity.Z の代わりに ProjectToGravityFloor、GetGravitySpaceZ、RotateWorldToGravity を使用してください。

関連スキル

  • ue-mover — Mover プラグイン(5.8 では Experimental):UMoverComponent、データとしての移動モード、レイヤー化ムーブ、ChaosMover
  • ue-networking-replication — RPC のルール、ネットワークロール、DOREPLIFETIME、プッシュモデル、CMC の予測が利用するトランスポート
  • ue-animation-system — モンタージュ、アニメーショングラフ、SetRootMotionMode、アニメーション駆動のロコモーション
  • ue-gameplay-framework — GameMode/Controller/Pawn の階層における ACharacter、ポゼッション、入力ルーティング
  • ue-physics-collision — 床の検出とステップアップに使用するスイープ、コリジョンチャンネル、レスポンス
  • ue-gameplay-abilities — 移動モードやルートモーションソースをトリガーするアビリティとアビリティタスク
  • ue-ai-navigation — MOVE_NavWalking の基盤となるナビメッシュの生成とクエリ、回避設定
  • ue-actor-component-architecture — アクターとコンポーネントのライフサイクル、アタッチメント、スポーン、ティック設定
  • ue-gameplay-cameras — スプリングアーム、ビュ―ターゲット、カメラモディファイアー、シェイク、Gameplay Camera System
  • ue-input-system — Enhanced Input のアクション、マッピングコンテキスト、トリガー、モディファイアー、ユーザー設定

コメント