
Attach는 어떤 SceneComponent(또는 액터의 RootComponent)를 다른 SceneComponent의 자식으로 연결하여, 부모의 이동/회전에 따라가게 만든다. (소켓 이름을 지정하면 소켓 기준으로 붙는다.)
Detach는 이 연결을 끊는다. 액터 단위로 끊으면 RootComponent 기준, 컴포넌트 단위로 끊으면 그 컴포넌트만 분리된다.
AttachToComponent와 DetachFromActor를 사용했을때, 왜 DetachFromComponent를 사용하지 않는지 사용법이 궁금해 적어보는 글이 글은 언리얼 엔진 5.6 기준으로 작성되었습니다.
종류는 굉장히 많지만, 사용 방법은 매우 단순하다.
1. 실행 중 무기를 캐릭터 손 소켓에 부착
WeaponActor->AttachToComponent(
Character->GetMesh(),
FAttachmentTransformRules::SnapToTargetNotIncludingScale,
FName("WeaponSocket_R")
);
2. 액터 전체를 손에서 떼기 (월드 좌표 유지)
WeaponActor->DetachFromActor(FDetachmentTransformRules::KeepWorldTransform);
3. 액세서리 컴포넌트만 분리 후 물리 적용
ScopeMesh->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
ScopeMesh->SetSimulatePhysics(true);
요약
AttachToComponent호출 →USceneComponent::AttachToComponent()내부에서 AttachChildren 배열에 부모-자식 관계 등록- Transform Rule에 따라 RelativeTransform 재계산 및 부모의 이동 시 Tick/Update 단계에서 상대 변환 적용
실제 과정을 살펴보자
Weapon->AttachToComponent(Parent, Rules, SocketName);
이 함수가 호출되면, USceneComponent::AttachToComponent()를 거쳐서 실제 부모-자식 관계를 설정한다.
1. 기존 관계 해제
DetachFromComponent()로 이전 부모의 AttachChildren 배열에서 제거하고 연결을 끊는다.2. 부모 설정 및 소켓 기록
AttachParent에 새로운 부모를 저장하고 소켓 이름을 기록한다((없다면 NAME_None)). 이후 부모의 AttachChildren에 자신을 추가한다.3. Transform Rule 적용
FAttachmentTransformRules에 따라 상대 변환(RelativeTransform)을 계산한다.// 현재 보이는 월드 좌표를 유지하도록 역산
RelativeTransform = Parent->GetComponentToWorld().Inverse() * WorldTransform;
4. 물리 상태 처리
bWeldSimulatedBodies 값에 따라 물리 상태를 처리한다. 값이true면 부모의 물리 바디에 병합되어 하나처럼 움직이게된다.5. 매 프레임마다 위치 갱신
UpdateComponentToWorld()에서ComponentToWorld = RelativeTransform * Parent->GetComponentToWorld();
요약
DetachFromComponent는 AttachChildren에서 제거하고, RelativeTransform을 WorldTransform으로 변환 후 저장DetachFromActor는 RootComponent에 대해 위 과정을 수행
1. Transform 보존
2. 부모-자식 관계 해제
AttachParent=nullptr 수행 후 부모의 AttachChildren에서 자신을 제거한다. 소켓역시AttachSocketName=NAME_None 으로 정리된다.3. 물리 상태 전환
SetSimulatePhysics(true)를 별도 호출을 하는 경우가 많다.호출 주체가 Component인지 Actor인지에 따라 구분된다.
| 함수 | 호출 주체 | 역할 | 주의 |
|---|---|---|---|
AActor::AttachToComponent(Parent, Rules, Socket) | Actor | 이 Actor의 RootComponet를 Parent의 RootComponet를 부착 | Parent가 등록되어있어야 유효함, 소켓부착가능, 성공여부 반환 |
AActor::AttachToActor(ParentActor, Rules, Socket) | Actor | 이 Actor의 RootComponet를 상대 액터의 RootComponet를 부착 | 소켓 가능, 성공 여부 반환 |
AActor::DetachFromActor(DetachmentRules) | Actor | 이 Actor의 RootComponet를 부모에서 분리 | |
USceneComponent::AttachToComponent(Parent, Rules, Socket) | Component | 이 SceneComponet를 Parent에 부착 | 등록 전,후 모두 호출 가능하지만 생성자에서는 SetupAttachment권장 |
USceneComponent::DetachFromComponent(DetachmentRules) | Component | 이 SceneComponet를 부모에서 분리 | 컴포넌트 단위로 세밀하게 분리 가능 |
AActor::AttachToComponent

USceneComponent::AttachToComponent


Actor API와의 관계
void AActor::DetachFromActor(const FDetachmentTransformRules& Rules)
{
if (RootComponent)
{
RootComponent->DetachFromComponent(Rules);
}
}
bool AActor::AttachToActor(AActor* ParentActor, const FAttachmentTransformRules& AttachmentRules, FName SocketName)
{
if (RootComponent && ParentActor)
{
USceneComponent* ParentDefaultAttachComponent = ParentActor->GetDefaultAttachComponent();
if (ParentDefaultAttachComponent)
{
return RootComponent->AttachToComponent(ParentDefaultAttachComponent, AttachmentRules, SocketName);
}
}
return false;
}
DetachFromActor, AttachToActor는 각각 DetachFromComponent, AttachToComponent를 호출하는 래퍼이다.AttachToActor는 내부적으로는 부모 액터의 기본 부착 컴포넌트를 찾아 AttachToComponent()를 호출하는 구조이다.DetachFromActor는 RootComponent를 기준으로 DetachFromComponent()를 호출한다.언리얼엔진은 생성자에서의 연결은 SetupAttachment(Parent, Socket)를 권장한다.
AttachToComponent()를 사용하면 부모 컴포넌트가 아직RegisterComponent()되지 않아 IsRegistered() false로 실패하거나, 월드 변환이 꼬일 수 있다.SetupAttachment()는 등록 전 계층을 미리 지정하는 일종의 예약시스템이다.SetupAttachment: 나중에 여기로 붙여줘!
UActorComponent::RegisterComponent() 함수가 컴포넌트 등록 시, 예약된 부모-자식 관계를 실제 계층 구조로 반영한다!RegisterComponent: 붙일게~! (...)
UActorComponent::RegisterComponent() 함수는 액터가 생성될 때 자동으로 호출 되므로, BeginPlay전에 모든 컴포넌트는 등록된다고 보면 된다.Attach와 Detach 모두 공식문서에서 Transform Rule을 따른다고 적혀있는데, Transform Rule은 뭘까?
FAttachmentTransformRules(EAttachmentRule InLocationRule, EAttachmentRule InRotationRule, EAttachmentRule InScaleRule, bool bInWeldSimulatedBodies)
: LocationRule(InLocationRule) // 부착 시 위치에 적용할 규칙
, RotationRule(InRotationRule) // 부착 시 회전에 적용할 규칙
, ScaleRule(InScaleRule) // 부착 시 스케일에 적용할 규칙
, bWeldSimulatedBodies(bInWeldSimulatedBodies)
{}

bWeldSimulatedBodiestrue면 자식(시뮬레이션 중인 컴포넌트)의 바디를 부모 바디에 병합해, 하나처럼 움직인다. (자식 독립 시뮬레이션 제거)FAttachmentTransformRules Rules(
EAttachmentRule::SnapToTarget, // Location
EAttachmentRule::SnapToTarget, // Rotation
EAttachmentRule::KeepWorld, // Scale
/*bWeldSimulatedBodies=*/false
);
1. KeepRelative
2. KeepWorld
3. SnapToTarget
IncludingScale(=SnapToTarget + Scale: SnapToTarget)
NotIncludingScale(=SnapToTarget + Scale: KeepRelative)
FDetachmentTransformRules(EDetachmentRule InLocationRule, EDetachmentRule InRotationRule, EDetachmentRule InScaleRule, bool bInCallModify)
: LocationRule(InLocationRule)
, RotationRule(InRotationRule)
, ScaleRule(InScaleRule)
, bCallModify(bInCallModify)
{}
bCallModifytrue, 보통은 기본값(false)를 사용한다.1. KeepRelative
2. KeepWorld
내가 이해하기 위해 간단하게 기록해 놓는다
부모 P, 자식 C가 있다고 가정
- 부모 P(World): 위치 (100, 0, 0), 회전 90°, 스케일 (2,2,2)
- 자식 C(World): 위치 (120, 0, 0), 회전 90°, 스케일 (1,1,1)
1. C를 P에 Attach(KeepWorld)
2. C를 P에 Attach(SnapToTargetNotIncludingScale)
3. 분리 Detach(KeepWorld)
4. 분리 Detach(KeepRelative)
// 부모 P(100,0,0)에 상대 위치 (10,0,0)으로 붙어있던 자식 C
Detach(KeepRelative)
// → 월드에서 (110,0,0)이 됨 (P가 사라져 상대=월드로 승격)
맛보기 정리 | 네트워크에서 Attach/Detach(부착 정보)도 서버 권한이 우선한다. 즉, 클라이언트에서 임의로 변경하면 서버가 강제로 서버에 기록된 Attach 관계로 정정한다.
AttachmentReplication이라는 멤버가 있고, 여기에 현재 어떤 액터/컴포넌트에 부착되었는지 정보가 서버기준으로 저장된다.OnRep_AttachmentReplication()가 호출되며 클라이언트의 로컬 상태를 서버 값으로 덮어쓴다.
- Unreal Engine 5.6 소스코드
- Unreal Engind Docs: https://dev.epicgames.com/documentation/en-us/unreal-engine/BlueprintAPI/Transformation/DetachFromActor
- Unreal Engind Docs: https://dev.epicgames.com/documentation/en-us/unreal-engine/components-in-unreal-engine