ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
この記事の要点
- On Component Hit は物理シミュレーション中のコンポーネントが何かに衝突した瞬間に発火するイベント
- 前提: Simulate Physics = true かつ Simulation Generates Hit Events = true
- 受け取れる引数: Hit Component / Other Actor / Other Component / Normal Impulse / Hit Result
- スイープ移動 (
MoveComponent) で当たった場合の OnComponentHit はキャラクター系では Notify Rigid Body Collision の設定で分岐 - 使い道: 弾の命中、爆発トリガー、衝突時パーティクル、ダメージ計算
1On Component Hit とは
OnComponentHit は、物理シミュレーション中のコンポーネント (RigidBody) が他のオブジェクトと衝突した瞬間に呼ばれるイベントです。手榴弾の爆発、弾丸の命中、転がる物理オブジェクトの音再生など、衝突を契機としたゲームロジックの起点になります。
2イベント発火の前提条件
| 設定 | 必要な値 | 場所 |
|---|---|---|
| Simulate Physics | true | Component → Physics |
| Simulation Generates Hit Events | true | Component → Collision |
| Collision Enabled | Query and Physics | Component → Collision |
| 相手 Collision Response | Block | 相手側のチャンネル応答 |
3Blueprint での使い方
- Components → 物理シミュレーションする Mesh を選択
- Details パネル右上の + Add Event → On Component Hit
- Event Graph に新しいイベントノードが追加される
- 必要に応じて Hit Result を分解して使用
4イベントの引数
| 引数 | 型 | 意味 |
|---|---|---|
| HitComponent | PrimitiveComponent | 自分のコンポーネント(衝突した側) |
| OtherActor | Actor | 衝突した相手アクター |
| OtherComp | PrimitiveComponent | 相手のコンポーネント |
| NormalImpulse | Vector | 衝突時に加わった力 (運動量変化) |
| Hit | FHitResult | 衝突詳細(位置・法線・物理マテリアル等) |
5C++ で OnComponentHit にバインド
// Projectile.h
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Projectile.generated.h"
UCLASS()
class MYGAME_API AProjectile : public AActor
{
GENERATED_BODY()
public:
AProjectile();
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* Mesh;
UPROPERTY(EditAnywhere, Category = "Damage")
float BaseDamage = 50.0f;
protected:
virtual void BeginPlay() override;
UFUNCTION()
void OnHit(UPrimitiveComponent* HitComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
FVector NormalImpulse,
const FHitResult& Hit);
};// Projectile.cpp
AProjectile::AProjectile()
{
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
RootComponent = Mesh;
Mesh->SetSimulatePhysics(true);
Mesh->SetNotifyRigidBodyCollision(true); // ★ Hit Events 有効
Mesh->SetCollisionProfileName(TEXT("PhysicsActor"));
}
void AProjectile::BeginPlay()
{
Super::BeginPlay();
Mesh->OnComponentHit.AddDynamic(this, &AProjectile::OnHit);
}
void AProjectile::OnHit(UPrimitiveComponent* HitComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
FVector NormalImpulse,
const FHitResult& Hit)
{
if (!OtherActor || OtherActor == this) return;
UE_LOG(LogTemp, Log, TEXT("Hit %s at %s, impulse=%s"),
*OtherActor->GetName(),
*Hit.ImpactPoint.ToString(),
*NormalImpulse.ToString());
// ダメージ計算 (運動量に比例)
const float Damage = BaseDamage * (NormalImpulse.Size() / 10000.0f);
UGameplayStatics::ApplyDamage(OtherActor, Damage, nullptr, this, nullptr);
// 衝突パーティクル
UGameplayStatics::SpawnEmitterAtLocation(
GetWorld(), ImpactEffect, Hit.ImpactPoint, Hit.ImpactNormal.Rotation());
// 自分は消滅
Destroy();
}
6Hit Result の主要フィールド
| フィールド | 型 | 意味 |
|---|---|---|
| ImpactPoint | Vector | 衝突したワールド座標 |
| ImpactNormal | Vector | 衝突面の法線ベクトル |
| Location | Vector | 命中時の自分の位置 |
| Normal | Vector | 進行方向の法線 |
| BoneName | FName | 当たったボーン名 (SkeletalMesh) |
| PhysMaterial | PhysicalMaterial | 当たった面の物理マテリアル |
| bBlockingHit | bool | ブロック衝突か(Overlap でなく) |
7Notify Rigid Body Collision 設定の重要性
C++ では SetNotifyRigidBodyCollision(true)、Blueprint では Details → Collision → Simulation Generates Hit Events にチェックを入れないと、物理衝突しても OnComponentHit が呼ばれません。
// 動的に切替
Mesh->SetNotifyRigidBodyCollision(true); // = bGenerateHitEvents = true
Mesh->BodyInstance.bNotifyRigidBodyCollision = true; // 内部フラグ
8OnComponentHit vs OnActorHit
| イベント | 対象 | 用途 |
|---|---|---|
| OnComponentHit | 個別の Primitive Component | 細かい制御(特定パーツのみ判定) |
| OnActorHit | アクター全体 | 大まかな衝突検知 |
9Sweep Hit との違い
キャラ移動 (MoveComponent) や AddActorWorldOffset(Sweep=true) で動かしたときの衝突は、物理シミュレーションではなくスイープテストです。これも OnComponentHit を発火させるには NotifyRigidBodyCollision 相当の設定が必要です:
// Sweep 移動でも OnComponentHit を発火させる
FHitResult Hit;
SetActorLocation(NewLocation, /*bSweep=*/true, &Hit);
if (Hit.bBlockingHit)
{
// 手動で同等の処理
OnHit(GetRootComponent(),
Hit.GetActor(),
Hit.GetComponent(),
FVector::ZeroVector,
Hit);
}
10サンプル: 弾の命中処理
[Blueprint: BP_Bullet]
Event BeginPlay
→ Set Notify Rigid Body Collision (Mesh, true)
Event On Component Hit (Mesh)
├ Other Actor → Cast to BP_Enemy
│ └ Apply Damage (Damage=20)
│
├ Spawn Emitter At Location
│ Template: P_Impact
│ Location: Hit Result → Impact Point
│ Rotation: Hit Result → Impact Normal → Make Rot From X
│
├ Spawn Sound At Location (Hit Result → Impact Point)
│
└ Destroy Actor (Self)
11サンプル: 衝突強度でダメージを変える
void AMyVehicle::OnHit(... FVector NormalImpulse, const FHitResult& Hit)
{
const float Speed = GetVelocity().Size(); // cm/s
const float ImpactMag = NormalImpulse.Size();
// 5 m/s 未満は無視
if (Speed < 500.0f) return;
// ImpactMag が大きいほどダメージ
const float Dmg = FMath::Clamp(ImpactMag / 5000.0f, 0.0f, 100.0f);
if (AActor* Hit_ = Hit.GetActor())
{
UGameplayStatics::ApplyDamage(Hit_, Dmg, nullptr, this, nullptr);
}
// 物理マテリアルで音を変える
if (Hit.PhysMaterial.IsValid())
{
UPhysicalMaterial* PM = Hit.PhysMaterial.Get();
if (PM == MetalPhysMat)
UGameplayStatics::PlaySoundAtLocation(this, MetalHitSound, Hit.ImpactPoint);
else if (PM == WoodPhysMat)
UGameplayStatics::PlaySoundAtLocation(this, WoodHitSound, Hit.ImpactPoint);
}
}
12よくあるトラブル
| 症状 | 原因 | 対処 |
|---|---|---|
| イベントが発火しない | Notify Rigid Body Collision OFF | true に |
| キャラを撃っても無反応 | Capsule の Collision が Overlap | Block に変更 or 弾を Trace 方式に |
| 高速の弾が貫通 | Tunneling | CCD 有効化 or Projectile Component の Sweep 使う |
| 同じ衝突で何度も発火 | 跳ね返り中も呼ばれる | 一度処理したらフラグ立てる / Destroy |
| NormalImpulse が常にゼロ | 物理シミュレーションでない | Simulate Physics 有効に |
13FAQ
Q: Projectile Movement Component の場合は?
A: UProjectileMovementComponent の OnProjectileBounce / OnProjectileStop イベントを使うのが一般的。OnComponentHit も併用可能。
Q: ImpactNormal が思った方向と違う
A: ImpactNormal は衝突面の法線(壁の向き)です。弾の進行方向と反対側を向きます。粒子効果の向きには Impact Normal をそのまま使うのが正解。
Q: マルチプレイで二重ダメージになる
A: OnComponentHit はサーバとクライアント両方で発火します。HasAuthority() でサーバ側だけで ApplyDamage を実行してください。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
- Event BeginPlay
- Event ActorBeginOverlap
- Event Tick
- on component begin overlap
- On Component Hit
- CameraBoom(Spring Arm)
- Get Player Character
- Nav Mesh Bounds Volume
- AI MoveTo
- Pawn
- Create Render Target 2D
- Take High Res Screenshotノード
- Sphere Reflection Capture
- Event Tickノード
- ウィジェットのキャンバスパネル
- DefaultSceneRoot
- FloatingPawnMovement
- Set World Rotation
- Event Any Damage
- Set World Rotation
- VInterp To
- Get Socket Transform
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 Spring Frameworkのアノテーション一覧
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- PHP $_SERVERとは|DOCUMENT_ROOT・PHP_SELFなど主な要素 2026-08-07 17:15:57
- PHPでのファイルアップロード方法|multipart/form-dataと$_FILES 2026-08-07 17:15:57
- Scratchのアカウントの作り方|メールアドレスとユーザー名の登録手順 2026-08-07 17:15:57
- Bluetoothとは|仕組み・BLEとClassicの違い・用途 2026-08-07 17:15:57
- Spring Bootのテスト入門|@SpringBootTestとJUnitでの単体・結合テスト 2026-08-07 17:15:57
- djangoにおけるMVCアプリケーション実装例 2026-08-07 17:15:57
- Scratch 作品の公開方法 2026-08-07 17:15:56
- 【PHPフレームワーク】Laravelの使い方 2026-08-07 17:15:56
- Google OAuth 2.0 認証の実装方法 2026-08-07 17:15:56
- APIキー取得方法 2026-08-07 17:15:56
- インストール方法(Windows版) 2026-08-07 17:15:56
- Java とは?言語仕様・JVM・主要フレームワーク一覧 2026-08-07 17:15:56
- データベースとは?RDB / NoSQL / SQL の基礎 2026-08-07 17:15:56
- インストール(eclipseプラグイン) 2026-08-07 17:15:56
- Spring Frameworkの使い方 2026-08-07 17:15:56
コメントを削除してもよろしいでしょうか?