https://dev.epicgames.com/documentation/ko-kr/unreal-engine/common-ui-plugin-for-advanced-user-interfaces-in-unreal-engine

https://velog.io/@yoo06/%EC%96%B8%EB%A6%AC%EC%96%BC-%EC%97%94%EC%A7%84-UE5-Common-UI-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0

 

언리얼 엔진 UE5 Common UI 알아보기

멀티플랫폼에서 UI를 생성하는 CommonUI 알아보기

velog.io

https://ctdidier27.medium.com/common-ui-plugin-ue5-b12050bf1fc0

 

Common UI Plugin UE5

Go to Edit>plugins>Common UI and check and restart Unreal.

ctdidier27.medium.com

https://dev.epicgames.com/community/learning/tutorials/BKJ7/unreal-engine-common-ui-tutorial-create-cross-platform-ui-easily-with-this-new-ue5-system

  • 화면을 그대로 유지하면서 Overlay 되는 UI를 노출하고, 화면입력을 막고 싶은 경우
  • 플랫폼 별로 UI Element를 다르게 관리하고 싶을 때
  • Popup들의 버튼을 누를 시 UI가 특정 상태가 되도록 흐름을 제어하고 싶을 때
  • 키보드나 콘솔 컨트롤러의 방향키로 UI 선택을 이동시키고 싶을 때(Cardinal Navigation)

핵심 개념

Input Routing

  • Selective Interaction을 구현하기 위해 채택한 방식
    • 입력을 수신하는 조건과 시기를 컨트롤 할 수 있다.
  • 예를 들어, 서로 다른 Widget에 버튼 별 Input을 분배해서 배치할 수 있다.
    • 이는 입력이 각 Widget에서 처리되는 것이 아니라 공용 Class에 전달되어 일괄처리 되기 때문이다.

Node

  • Common UI는 Widget을 Node로 변환해 Visual Hierarchy에 따라 상위에 Rendering 된 Widget의 입력을 Route한다.

  • 몇 가지 예외를 제외하고, 대부분의 Common UI는 Slate의 Hierarchy와 동일하게 구성된다.
    • 각 Tree는 Viewport에 직접 배치 된 Widget을 Root Node로,
      Button과 같은 개별 UI Element를 Leaf Node로 취급하여 구성된다.
  • Common UI는 Tick당 1번씩 다른 Tree보다 상단에 Render 된 Tree를 탐색해 Root Node로 Input을 Route한다.
  • 그럼 Root Widget은 Input을 처리할 수 있는 첫번째 Leaf Node에 입력을 전달한다.
  • 입력을 전달 받은 Leaf Node는 이를 처리하거나, 필요하다면 다른 곳으로 재전달한다.

ActivatableWidget

  • Common UI 중 Input 처리를 위해 Node로 변환되고, 이를 수신할 수 있는 Widget
    • Input 수신 시 Active 상태로 간주한다.
  • Activatable Widget은 다음 기능을 제공한다.
    • Input 수신 가능 여부(Active/Inactive) 상태 토글
    • 같은 Tree 내 다른 Activatable Widget에 Input 전달
    • 뒤로가기 등 특정 상황에서 Inactivate
  • 이 Widget을 이용해 현재 Input을 수신중인 Overlay UI가 닫힐 경우,
    적절한 Element로 복구해주는 기능을 작업할 수 있다.
    • Input은 항상 최상단에 Layer에만 Route 되기에 하단 Layer의 Widget도 문제 없이 Active 상태로 둘 수 있다.
    • 이 때 상단 Layer가 닫히면 자연스럽게 하단 Layer에 Input이 Route 된다.

사용법

Viewport Configure

  • Edit -> Project Settings -> Engine -> General Settings으로 이동
  • Game Viewport Client Class를 CommonGameViewportClient 혹은 이를 상속받은 Custom Class로 설정

Create InputActionDataTable

  • 한가지 잊지 말아야 할 점이 있다.
    • CommonUI InputAction DataTable은 Project Setting, Advanced Input System에 사용하는 것과 무관하다.
    • 오직 UI Input 관리에만 사용된다.

  • Content Browser 영역 우클릭 -> Miscellaneous -> CommonUI ActionInput Data Table선택

  • 위와 같이 Row를 추가해 Input을 설정한다.

  • 이렇게 추가된 InputAction은 CommonUI Widget에서 Mapping할 수 있다.
    • 위 사진은 CommonButtonBase의 Class Defaults에서 DataTable과 RowName을 통해
      InputAction을 Button에 Mapping 한 예시이다.
  • 좀 더 용이하게 관리하려면 관련된 Action들을 하나의 DataTable에서 작업하여 그룹화 하는 것이 좋다.

CommonInputActionDataBase

더보기
USTRUCT(BlueprintType)
struct COMMONUI_API FCommonInputActionDataBase : public FTableRowBase
{
	GENERATED_BODY()

	FCommonInputActionDataBase();
	
	/** User facing name (used when NOT a hold action) */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CommonInput")
	FText DisplayName;

	/** User facing name used when it IS a hold action */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CommonInput")
	FText HoldDisplayName;

	/** Priority in nav-bar */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "CommonInput")
	int32 NavBarPriority = 0;

protected:
	/**
	* Key to bind to for each input method
	*/
	UPROPERTY(EditAnywhere, Category = "CommonInput")
	FCommonInputTypeInfo KeyboardInputTypeInfo;

	/**
	* Default input state for gamepads
	*/
	UPROPERTY(EditAnywhere, Category = "CommonInput")
	FCommonInputTypeInfo DefaultGamepadInputTypeInfo;

	/**
	* Override the input state for each input method
	*/
	UPROPERTY(EditAnywhere, Category = "CommonInput", Meta = (GetOptions = "CommonInput.CommonInputBaseControllerData.GetRegisteredGamepads"))
	TMap<FName, FCommonInputTypeInfo> GamepadInputOverrides;

	/**
	* Override the displayed brush for each input method
	*/
	UPROPERTY(EditAnywhere, Category = "CommonInput")
	FCommonInputTypeInfo TouchInputTypeInfo;
};
  • DisplayName
    • 해당 InputAction의 이름
    • Navigation Bar가 있는 경우 해당 Bar에 표시된다.
  • HoldDisplayName
    • 버튼 Hold 동작이 필요한 InputAction의 이름
  • NavBarPriority
    • Navibation Bar Action을 왼쪽에서 오른쪽으로 Sort할 때 사용하는 Priority
  • KeybaordInputTypeInfo
    • 마우스 및 키보드 Action의 InputType
  • DefaultGamepadInputTypeInfo
    • Gamepad Action의 InputType
  • GamepadInputOverrides
    • 특정 Gamepad에서 해당 Action에 사용되는 키
    • 콘솔 플랫폼 별 버튼 Override에 유용하다.
      • Nintendo Switch Gamepad의 앞뒤 버튼을 바꾸는 것 
  • TouchInputTypeInfo
    • Touch Interface Action의 InputType

CommonInputTypeInfo

더보기
USTRUCT(BlueprintType)
struct COMMONUI_API FCommonInputTypeInfo
{
	GENERATED_USTRUCT_BODY()

	FCommonInputTypeInfo();
private:
	/** Key this action is bound to	*/
	UPROPERTY(EditAnywhere, Category = "CommonInput")
	FKey Key;
public:

	/** Get the input type key bound to this input type, with a potential override */
	FKey GetKey() const;

	/** Get the input type key bound to this input type, with a potential override */
	void SetKey(FKey InKey)
	{
		Key = InKey;
	};

	/** EInputActionState::Enabled means that the state isn't overriden and the games dynamic control will work */
	UPROPERTY(EditAnywhere, Category = "CommonInput")
	EInputActionState OverrrideState;

	/** Enables hold time if true */
	UPROPERTY(EditAnywhere, Category = "CommonInput")
	bool bActionRequiresHold;

	/** The hold time in seconds */
	UPROPERTY(EditAnywhere, Category = "CommonInput", meta = (EditCondition = "bActionRequiresHold", ClampMin = "0.0", UIMin = "0.0"))
	float HoldTime;

	/**
	*	Time (in seconds) for hold progress to go from 1.0 (completed) to 0.0.
	*	If the hold interaction was interrupted, then hold progress starts to roll back decreasing its value.
	*	Set to 0.0 to disable the rollback functionality.
	*/
	UPROPERTY(EditAnywhere, Category = "CommonInput", meta = (EditCondition = "bActionRequiresHold", ClampMin = "0", UIMin = "0", ClampMax = "10.0", UIMax = "10"))
	float HoldRollbackTime;
	
	/** Override the brush specified by the Key Display Data  */
	UPROPERTY(EditAnywhere, Category = "CommonInput")
	FSlateBrush OverrideBrush;
};
  • Key
    • Bind 될 Input Key
  • OverrideState
    • Input 및 Callback 호출 여부의 상태를 담당
  • bActionRequiredsHold
    • Input이 Hold로 작동되어야 하는지 여부
  • HoldTime
    • Input이 Hold로 작동 되어야 할 때, Hold해야 하는 시간
  • HoldRollbackTime
    • Hold가 작동하고 나서 완전히 비활성화 상태로 되돌아갈 때까지의 시간.
  • OverrideBrush
    • Key Display Data에서 정의된 Brush로 Override

EInputActionState

더보기
UENUM(BlueprintType)
enum class EInputActionState : uint8
{
	/** Enabled, will call all callbacks */
	Enabled,
	/** Disabled, will call all the disabled callback if specified otherwise do nothing */
	Disabled,
	
	/** The common input reflector will not visualize this but still calls all callbacks. NOTE: Use this sparingly */
	Hidden,
	
	/** Hidden and disabled behaves as if it were never added with no callbacks being called */
	HiddenAndDisabled,	
};
  • Enabled
    • Input이 활성화 되어 있음
    • Callback이 호출 됨
  • Disabled
    • Disable Callback이 선언되어 있는 경우 이를 호출 함
    • 그 외의 모든 Callback이 반응하지 않음
  • Hidden
    • Reflector가 시각적으로 보이지는 않지만 Callback이 호출 됨.
    • 자주 사용하지 않을 것을 권장 함.
  • HiddenAndDisabled
    • Reflector가 시각적으로 보이지 않고, Callback도 동작하지 않음.

Default Navigation Action Configure

  • Unreal Engine에서 Native Navigation을 지원하지만,
    CommonUI을 사용하면 CommonUIInputData를 기반으로 한 별도의 Navigation이 정의되어야 한다.

  • Create New Plueprint Class에서 CommonUIInputData를 선택해 BP 생성
    • 생성한 파일 내에 CommonUI InputActionDataTable과 Row를 지정하여 Navigation을 지정
    • HoldData의 경우 CommonUIHoldInputData를 기반으로 신규 BP를 생성한 뒤, 해당 파일을 연결해줘야 한다.
  • Click Action
    • 버튼이나 기타 상호작용 가능한 Element를 Highlight 할 때 Mouse Click을 대체
  • Back Action
    • 현재 Menu에서 이전 Menu로 이동할 때 공통으로 사용

  • Project Settings -> Game -> Common Input Settings의 InputData에 연결한다.
  • 설정 시, 지정된 Asset을 Default Navigation에 사용한다.

Bind Controller Data per Platform

  • Controller Data Asset은 Key-Action을 UI Elemnt에 연결해준다.
    • 각 Controller Data Asset은 Input Type, Gamepad, Platform과 연관되어 있다.
  • CommonUI는 이 정보를 이용해 현재 Platform과 Input Type을 기반으로
    올바른 Platform 별 UI Element를 자동으로 사용한다.
    • 이를 통해 다수의 Input Type이나 고유한 Gamepad를 지원하는 Platform에서
      User Input을 올바른 GamePad에 전달하거나, Runtime에서 UI Elemnt를 교체할 수도 있다.

  • Create New Blueprint Class에서 CommonInputBaseControllerData를 선택해 생성

  • 생성한 모든 Controller Data Asset은
    Project Settings -> Game -> Common Input Settings의 Platform Input에 추가되어야 한다.
    • Platform Input에서 입력하는 Default Gamepad Name은
      Controller Data Asset들의 Gamepad Name 필드들로만 입력되어야 한다.
    • 이 값이 일치하지 않으면 Controller Data를 인식하지 못하고 Icon이 표시되지 않는다.
  • 보통은 한 Platform의 Controller Data Array에 여러 개의 Gamepad Data를 작성해 다양한 컨트롤러를 지원한다.
    • 만약 별도의 Controller에 대한 게임플레이 지원을 해야 한다면,
      Gamepad Data를 새로 작성해 Controller Data에 추가하면 된다.

CommonInputBaseControllerData

더보기
/* Derive from this class to store the Input data. It is referenced in the Common Input Settings, found in the project settings UI. */
UCLASS(Abstract, Blueprintable, ClassGroup = Input, meta = (Category = "Common Input"))
class COMMONINPUT_API UCommonInputBaseControllerData : public UObject
{
	GENERATED_BODY()

public:
	virtual bool NeedsLoadForServer() const override;
	virtual bool TryGetInputBrush(FSlateBrush& OutBrush, const FKey& Key) const;
	virtual bool TryGetInputBrush(FSlateBrush& OutBrush, const TArray<FKey>& Keys) const;

	virtual void PreSave(FObjectPreSaveContext ObjectSaveContext) override;
	virtual void PostLoad() override;

private:
#if WITH_EDITORONLY_DATA
	UPROPERTY(Transient, EditAnywhere, Category = "Editor")
	int32 SetButtonImageHeightTo = 0;
#endif

public:
	UPROPERTY(EditDefaultsOnly, Category = "Default")
	ECommonInputType InputType;
	
	UPROPERTY(EditDefaultsOnly, Category = "Gamepad", meta=(EditCondition="InputType == ECommonInputType::Gamepad", GetOptions = GetRegisteredGamepads))
	FName GamepadName;

	UPROPERTY(EditDefaultsOnly, Category = "Gamepad", meta = (EditCondition = "InputType == ECommonInputType::Gamepad"))
	FText GamepadDisplayName;

	UPROPERTY(EditDefaultsOnly, Category = "Gamepad", meta=(EditCondition="InputType == ECommonInputType::Gamepad"))
	FText GamepadCategory;

	UPROPERTY(EditDefaultsOnly, Category = "Gamepad", meta = (EditCondition = "InputType == ECommonInputType::Gamepad"))
	FText GamepadPlatformName;

	UPROPERTY(EditDefaultsOnly, Category = "Gamepad", meta=(EditCondition="InputType == ECommonInputType::Gamepad"))
	TArray<FInputDeviceIdentifierPair> GamepadHardwareIdMapping;

	UPROPERTY(EditDefaultsOnly, Category = "Display")
	TSoftObjectPtr<UTexture2D> ControllerTexture;

	UPROPERTY(EditDefaultsOnly, Category = "Display")
	TSoftObjectPtr<UTexture2D> ControllerButtonMaskTexture;

	UPROPERTY(EditDefaultsOnly, Category = "Display", Meta = (TitleProperty = "Key"))
	TArray<FCommonInputKeyBrushConfiguration> InputBrushDataMap;

	UPROPERTY(EditDefaultsOnly, Category = "Display", Meta = (TitleProperty = "Keys"))
	TArray<FCommonInputKeySetBrushConfiguration> InputBrushKeySets;

	UFUNCTION()
	static const TArray<FName>& GetRegisteredGamepads();

private:
#if WITH_EDITOR
	virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
#endif
};
  • InputType
    • CommonUI에서 인식하는 Input의 종류
UENUM(BlueprintType)
enum class ECommonInputType : uint8
{
	MouseAndKeyboard,
	Gamepad,
	Touch,
	Count
};
  • GamepadName
    • Controller가 Gamepad인 경우에 해당 Gamepad가 대응 할 Platform
USTRUCT()
struct FInputDeviceIdentifierPair
{
	GENERATED_BODY()

	UPROPERTY(EditDefaultsOnly, Category = "Gamepad")
	FName InputDeviceName;

	UPROPERTY(EditDefaultsOnly, Category = "Gamepad")
	FString HardwareDeviceIdentifier;
};
  • GamepadhardwareIdMapping
    • Gamepad Hardware ID를 게임에서 사용하는 Key값과 연결
USTRUCT(Blueprintable)
struct COMMONINPUT_API FCommonInputKeyBrushConfiguration
{
	GENERATED_BODY()

public:
	FCommonInputKeyBrushConfiguration();

	const FSlateBrush& GetInputBrush() const { return KeyBrush; }

public:
	UPROPERTY(EditAnywhere, Category = "Key Brush Configuration")
	FKey Key;

	UPROPERTY(EditAnywhere, Category = "Key Brush Configuration")
	FSlateBrush KeyBrush;
};
  • InputBrushDataMap
    • UI Element 및 Icon에 대한 Key Mapping
USTRUCT(Blueprintable)
struct COMMONINPUT_API FCommonInputKeySetBrushConfiguration
{
	GENERATED_BODY()

public:
	FCommonInputKeySetBrushConfiguration();

	const FSlateBrush& GetInputBrush() const { return KeyBrush; }

public:
	UPROPERTY(EditAnywhere, Category = "Key Brush Configuration", Meta = (TitleProperty = "KeyName"))
	TArray<FKey> Keys;

	UPROPERTY(EditAnywhere, Category = "Key Brush Configuration")
	FSlateBrush KeyBrush;
};
  • InputBrushKeySets
    • 단일 UI Element에 대한 다수의 Key Mapping
    • D-Pad 및 기타 여러 Axis에 Mapping 될 가능성이 있는 Input에 유용

Common UI widget

  • Common UI Plugin에서 제공하는 Widget
  • 기존에 자주 사용하는 Widget의 기능을 거의 그대로 제공
    • 다만 Base UMG Widget Style 기능은 제공하지 않는다.
    • 대신 Common Style Asset을 참조해 다수의 Menu와 HUD에 일관된 Style을 적용할 수 있다.
    • Styple Asset을 변경하면 모든 Common UI Widget에 효과가 나타난다.
  • 자세한 지원 Widget 항목에 대해서는 아래 개별 포스트 참고

Common Style Asset

  • Create New Blueprint Class를 통해 사진과 같이 Common Style BP를 생성한다.

  • 생성한 Common Style BP의 Detail 항목에 필요한 정보를 채워놓는다.

  • 생성한 Common Style BP는 이를 필요로 하는 다른 CommonUI에 연결하여 적용한다.
    • 위 사진의 경우, Common Button의 Widget Element인 Common Text에 CommonTextStyle을 적용하였다.

  • 생성된 Common Style BP는 Project Settings -> Plugins -> Common UI Editor의 Template Styles에 할당할 수 있다.
    • 그럼 수동으로 설정되지 않은 Common BP에서 Template Style을 자동으로 사용하게 된다.

  • 이와 같은 맥락으로, Project Settings -> Plugins -> Common UI Framework에서
    몇 가지 Global Assset을 추가로 지원한다.
    • Loading 화면에서 쓰는 Default Throbber Material
    • Load되지 않은 UI Asset에 표시되는 Default Image Resource Object 등

Technical Guide

FAQ

 

[UI] Common UI FAQ

Common UI의 사용 여부 판단주로 다음 상황에서 Common UI 사용이 권장된다.복잡한 Multiple Layer UI를 제공해야 하는 경우Cross-Platform을 지원하는 경우반대로 이 두 케이스에 모두 해당되지 않으면 Common U

redchiken.tistory.com

 

'UE5 > UI' 카테고리의 다른 글

[UI] Common UI FAQ  (0) 2024.07.10
[UI] CommonUI Technical Guide  (0) 2024.07.10
[UI] Common UI Widget  (0) 2024.07.10
[UI] UMG ViewModel  (0) 2024.07.08
[UI] Optimization  (0) 2024.07.01

+ Recent posts