ue-character-movement について
UE 5.8 の ACharacter と UCharacterMovementComponent を扱う開発者向けスキルです。移動シミュレーション、自作モード、ネットワーク予測、ルートモーション、5.8 の移動ベース変更を解説します。
主な機能
- 01移動モードと遷移
- 02床検出と段差乗り越え
- 03カスタム移動モード
- 04ネットワーク予測と補正
- 05ルートモーションとカスタム重力
- 06UE 5.8 の移動ベース API
活用シーン
- 01壁走りやクライミングの実装
- 02マルチプレイヤー移動補正の調査
- 03キャラクターを足場に追従させる
- 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 のメンバー | 保持先 |
|---|---|---|
MovementBase | MovementBaseInterfaceData | FBasedMovementInfo |
MovementBase | PhysicsObjectOwner | FRepRootMotionMontage |
MovementBase | MovementBasePhysicsObjectOwner | FCharacterNetworkMoveData |
StartBase / EndBase | StartMovementBaseInterfaceData / EndMovementBaseInterfaceData | FSavedMove_Character |
LastServerMovementBase | LastMovementBaseInterfaceData | UCharacterMovementComponent |
以前は 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_JumpPressed | 0x01 | ジャンプ入力 |
FLAG_WantsToCrouch | 0x02 | しゃがみ入力 |
FLAG_Reserved_1 | 0x04 | エンジン用に予約済み |
FLAG_Reserved_2 | 0x08 | エンジン用に予約済み |
FLAG_Custom_0 | 0x10 | 独自用途 |
FLAG_Custom_1 | 0x20 | 独自用途 |
FLAG_Custom_2 | 0x40 | 独自用途 |
FLAG_Custom_3 | 0x80 | 独自用途 |
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_ConstantForce | Force、StrengthOverTime | ノックバック、風 |
FRootMotionSource_RadialForce | Location、LocationActor、Radius、Strength、bIsPush、bNoZForce | 爆発、渦 |
FRootMotionSource_MoveToForce | StartLocation、TargetLocation、PathOffsetCurve | 固定位置へのダッシュ |
FRootMotionSource_MoveToDynamicForce | StartLocation、SetTargetLocation() | ホーミングダッシュ |
FRootMotionSource_JumpForce | Rotation、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 を参照してください。
主なプロパティ
| プロパティ | デフォルト値 | 説明 |
|---|---|---|
MaxWalkSpeed | 600 | 地上での速度上限 |
MaxWalkSpeedCrouched | 300 | デフォルトでは MaxWalkSpeed の半分 |
MaxSwimSpeed | 300 | |
MaxFlySpeed | 600 | |
MaxCustomMovementSpeed | 600 | MOVE_Custom において GetMaxSpeed() が返す上限 |
MaxAcceleration | 2048 | |
BrakingDecelerationWalking | 2048 | デフォルトでは MaxAcceleration と同じ |
GroundFriction | 8 | |
GravityScale | 1 | ワールドの重力に対する倍率 |
JumpZVelocity | 420 | |
AirControl | 0.05 | 落下中の横方向の操作性 |
MaxStepHeight | 45 | |
WalkableFloorZ | 0.71 | 約44.8度。SetWalkableFloorAngle で設定 |
MaxSimulationTimeStep | 0.05 | サブステップの上限 |
MaxSimulationIterations | 8 | フレームあたりのサブステップ数 |
NetworkSmoothingMode | Exponential (CharacterMovementComponent.cpp:718) | ENetworkSmoothingMode::Disabled、Linear、Exponential |
bOrientRotationToMovement | false | 速度の向きに合わせて回転 |
bUseControllerDesiredRotation | false | コントローラーの回転に合わせて回転 |
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::MovementBase | FBasedMovementInfo::MovementBaseInterfaceData | Character.h の UE_DEPRECATED(5.8) |
FRepRootMotionMontage::MovementBase | FRepRootMotionMontage::PhysicsObjectOwner | Character.h の UE_DEPRECATED(5.8) |
FCharacterNetworkMoveData::MovementBase | MovementBasePhysicsObjectOwner | GameFramework/CharacterMovementReplication.h の UE_DEPRECATED(5.8) |
FSavedMove_Character::StartBase/EndBase | StartMovementBaseInterfaceData/EndMovementBaseInterfaceData | CharacterMovementComponent.h の UE_DEPRECATED(5.8) |
GetLastServerMovementBase()/LastServerMovementBase | GetLastServerMovementBaseInterfaceData()/LastMovementBaseInterfaceData | CharacterMovementComponent.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) |
パブリックな CrouchedHalfHeight | SetCrouchedHalfHeight()/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 RPC | ServerMovePacked/ClientMoveResponsePacked | CharacterMovementReplication.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、データとしての移動モード、レイヤー化ムーブ、ChaosMoverue-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 Systemue-input-system— Enhanced Input のアクション、マッピングコンテキスト、トリガー、モディファイアー、ユーザー設定