스튜디오에서 디자인 구현

*이 콘텐츠는 AI(베타)를 사용해 번역되었으며, 오류가 있을 수 있습니다. 이 페이지를 영어로 보려면 여기를 클릭하세요.

디자인 구현하기는 스크립트를 사용하여 UI 요소를 상황에 맞게 트리거하여 내장 및 사용자 정의 UI 요소로 스튜디오에서 와이어프레임을 만드는 프로세스입니다. 이 튜토리얼의 흥미로운 단계에서는 모든 디자인과 노력이 하나의 응집력 있는 워크플로 세트로 결합되어 플레이어 상호작용을 준비하는 것을 볼 수 있습니다.

샘플 레이저 태그 경험 .rbxl 파일을 참조하여, 이 UI 디자인 교육 과정의 이 섹션에서는 UI 계획을 실현하는 방법과 관련된 지침을 보여줍니다:

  • 샘플 레이저 태그 경험의 UI 구성 요소를 재현할 수 있도록 UI 자산 라이브러리에서 자산 ID를 검색합니다.
  • 스튜디오에서 다양한 장치를 에뮬레이션하여 UI가 서로 다른 화면 및 종횡비에서 어떻게 표시되는지 확인합니다.
  • 플레이어 화면, 파트 표면 및 3D 공간 내에서 UI를 표시하기 위해 각각 ScreenGui, SurfaceGui, BillboardGui 객체를 생성합니다.

이 섹션에서 기술을 검토한 후, 자체 프로젝트에 적용하여 플레이어가 자신의 경험 내에서 무엇을 할 수 있는지 탐색하는 데 도움이 되는 흥미로운 UI 구성 요소를 만들 수 있습니다.

자산 라이브러리 가져오기

자산 라이브러리는 귀하의 인벤토리에 추가하여 쉽게 접근하고 재사용할 수 있는 자산의 모음입니다. Creator Store에서 귀하가 프로젝트에 사용할 자산 라이브러리에는 9개의 2D 개별 UI 요소 자산과 튜토리얼 이 섹션에서 생성하고 있는 목표, 블래스터 선택기 및 플레이어 정보 구성 요소의 최종 버전이 포함되어 있습니다.

멀티 블래스터 아이콘
rbxassetid://14309094777
싱글 블래스터 아이콘
rbxassetid://14309094641
핑크 팀 아이콘
rbxassetid://14309678581
사다리꼴
rbxassetid://14304828203
거꾸로 된 사다리꼴
rbxassetid://14304827304
그린 팀 아이콘
rbxassetid://14309678701
페이드
rbxassetid://14304826876
다방향 페이드
rbxassetid://14304827147
폭발 버튼 아이콘 - 기본
rbxassetid://18308375067
폭발 버튼 아이콘 - 눌림
rbxassetid://18308372597
조준대 아이콘
rbxassetid://14400935532
힛 마커 아이콘
rbxassetid://14401148777
육각형
rbxassetid://14462567943
선택 화살표 아이콘
rbxassetid://14309187282
경계 페이드
rbxassetid://14309518632

인벤토리에서 자산 라이브러리를 귀하의 경험으로 가져오려면:

  1. 인벤토리에 자산 라이브러리를 추가합니다.

    1. Creator Store에서 자산 라이브러리의 상세 페이지로 이동합니다.
    2. 오른쪽 상단 모서리에서 모델 가져오기 버튼을 클릭합니다. 자산 라이브러리가 이제 인벤토리에 추가되었으며, 플랫폼의 모든 프로젝트에서 이 자산을 재사용할 수 있습니다.
  2. 스튜디오에서 탭으로 이동한 다음 툴박스 버튼을 클릭합니다. 툴박스 창이 열립니다.

    스튜디오 툴바에서 강조된 툴박스.
  3. 툴박스 창에서 인벤토리 탭을 클릭합니다. 내 모델 정렬이 표시됩니다.

  4. 드롭다운 메뉴를 클릭한 다음 내 패키지 정렬을 선택합니다.

  5. 최종 화면 UI 구성 요소 타일을 클릭한 다음 탐색기 창에서 완료된 구성 요소를 선택한 후 이를 시작 GUI 서비스로 끌어옵니다. 이제 최종 구성 요소를 활성화하여 해당 디자인을 참조할 수 있습니다.

장치 에뮬레이션

스튜디오의 장치 에뮬레이터는 다양한 장치에서 플레이어가 UI를 어떻게 보고 상호 작용할지 테스트할 수 있게 해줍니다. 이 도구는 구현 과정에서 중요한 부분으로, 스튜디오의 뷰포트 비율이 플레이어가 귀하의 경험에 접근하는 데 사용하는 화면의 비율을 반드시 반영하지는 않으며, 모든 장치에서 UI가 가독성이 높고 접근 가능해야 합니다.

예를 들어, 다양한 화면 크기에서 UI를 테스트하지 않으면, 큰 화면을 가진 플레이어는 텍스트를 읽거나 아이콘을 해석할 수 없으며, 작은 화면을 가진 플레이어는 UI 요소가 디스플레이에서 너무 많은 공간을 차지하기 때문에 3D 공간을 볼 수 없습니다.

여러 화면 크기에서 UI를 에뮬레이트하려면:

  1. 스튜디오의 테스트 메뉴에서 장치 에뮬레이터를 활성화합니다.

  2. 해상도 드롭다운에서 실제 해상도를 선택합니다. 이는 에뮬레이션하는 장치에서 UI 요소의 실제 해상도를 보기 위해 허용합니다.

    뷰포트 창 상단에 표시된 장치 에뮬레이터 설정 옵션.
  3. 장치 드롭다운에서 전화, 태블릿, 데스크탑, 콘솔 섹션 내의 최소한 하나의 장치를 선택합니다.

ScreenGui 객체 만들기

모든 플레이어 화면에 UI 요소를 표시하려면 ScreenGui 객체를 StarterGui 서비스에 생성할 수 있습니다. ScreenGui 객체는 화면 UI의 기본 컨테이너이며, StarterGui 서비스는 해당 콘텐츠를 플레이어가 경험에 들어갈 때마다 각 플레이어의 PlayerGui 컨테이너로 복사합니다.

각각의 UI 요소 그룹을 게임 플레이 내에서 문맥적으로 구성하고 표시하기 위해 여러 개의 ScreenGui 객체를 생성할 수 있습니다. 예를 들어, 샘플 레이저 태그 경험에는 플레이어가 주요 사용자 흐름에서 다양한 조건을 충족할 때까지 초기에는 비활성 상태인 5개의 개별 ScreenGui 객체가 포함되어 있습니다:

  • HUDGui - 플레이어가 라운드에서 활성화되었을 때 경험 게임 플레이에 대한 주요 정보를 표시하며, 목표 및 각 팀의 총 점수 등을 포함합니다.
  • PickABlasterGui - 플레이어가 라운드를 시작하거나 재가입할 때 모든 블래스터 선택 사항을 표시합니다.
  • ForceFieldGui - 플레이어가 블래스터를 선택하고 있을 때 헥사곤 그리드를 표시하며, 잠깐 동안 무적 상태일 때도 표시됩니다.
  • OutStateGui - 플레이어가 태그당했을 때 화면 주위에 어두운 경계선을 표시합니다.
  • RoundResultsGui - 화면 상단에 어두운 오버레이를 표시하여 어느 팀이 라운드에서 승리했는지에 대한 정보를 제공합니다.

ScreenGui 객체를 생성한 후, 각 컨테이너의 목적에 따라 자식 GuiObjects를 생성하고 사용자 설정할 수 있습니다. 이를 통해 다음 섹션에서는 플레이어가 샘플 레이저 태그 경험에서 성공하기 위해 알아야 할 세 가지 정보 범주를 위한 UI 요소를 구현하는 방법을 배우게 됩니다. 프로세스의 어떤 부분이든 자신의 경험의 사양에 맞게 조정할 수 있습니다.

ScreenGui 객체를 생성하려면:

  1. 탐색기 창에서 StarterGui 서비스 위에 커서를 놓고, 아이콘을 클릭합니다. 문맥 메뉴가 표시됩니다.

  2. ScreenGui를 삽입합니다.

  3. 자식 UI 요소의 문맥에 따라 ScreenGui의 이름을 변경합니다.

  4. 표시해야 하는 각 UI 요소 그룹에 대해 이 프로세스를 반복합니다.

목표 UI

와이어프레임 레이아웃의 시각적 계층 구조 모범 사례를 따르고 이 섹션에서는 경험의 목표와 관련된 모든 화면 UI 요소를 구현하는 방법을 가르칩니다. UI 요소 그룹은 화면 상단에 가깝게 배치되어 있으며 목표와 각 팀의 점수가 게임에서 이기는 방법에 가장 큰 중요성을 가지기 때문입니다.

예를 들어, 샘플은 플레이어가 라운드에서 성공하기 위해 무엇을 해야 하는지를 알기 위해 참조하는 목표 UI 구성 요소를 제공합니다. 플레이어가 적 팀원을 태그하고 점수를 얻으면서, 이 구성 요소는 헤더의 프롬프트 내에서 전체 목표에 대한 각 팀의 점수를 추적합니다. 포인트를 추적하는 데 서로 협력하는 모든 클라이언트 및 서버 스크립트를 고수준으로 검토하려면, 게임 플레이 스크립팅 교육 과정의 포인트 추적을 참조하십시오.

샘플 레이저 태그 경험 내 목표 UI를 정확하게 재현하려면:

  1. 전체 구성 요소에 대한 컨테이너를 생성합니다.

    1. HUDGui ScreenGui 객체에 프레임을 삽입합니다.

      1. 탐색기 창에서 StarterGui 서비스로 이동합니다.
      2. 자식 HUDGui 객체 위에 커서를 놓고 ⊕ 아이콘을 클릭합니다. 문맥 메뉴가 표시됩니다.
      3. 문맥 메뉴에서 프레임을 삽입합니다.
    2. 프레임을 선택한 다음 속성 창에서,

      1. AnchorPoint0.5, 0으로 설정하여 프레임의 원점이 가장 위 가운데에 있도록 합니다(프레임의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 0%).
      2. BackgroundTransparency1로 설정하여 프레임의 배경을 완전히 투명하게 만듭니다.
      3. Position{0.5, 0},{0.03, 0}으로 설정하여 프레임이 화면 가장 위 가운데에 위치하게 합니다(화면 좌측에서 우측까지 50%, 위에서 아래까지 3%).
      4. Size{0.5, 0},{0.13, 0}으로 설정하여 프레임의 요소들이 화면 상단의 큰 부분을 차지하도록 하여 플레이어의 주목을 끌 수 있게 합니다(수평으로 50%, 수직으로 13%).
      5. NameObjective로 설정합니다.
    3. (선택 사항) 목표UIAspectRatioConstraint를 삽입하여 레이블의 종횡비가 플레이어의 화면 크기에 관계없이 유지되도록 합니다. 샘플은 UIAspectRatioConstraint.AspectRatio 속성을 7로 설정합니다.

  2. 목표의 프롬프트 개체에 대한 컨테이너를 생성합니다.

    1. 목표프레임을 삽입합니다.

    2. 프레임을 선택한 다음 속성 창에서,

      1. AnchorPoint0.5, 0으로 설정하여 프레임의 원점이 가장 위 가운데에 있도록 합니다(프레임의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 0%).
      2. BackgroundTransparency1로 설정하여 프레임의 배경을 완전히 투명하게 만듭니다.
      3. Position{0.5, 0},{0, 0}으로 설정하여 프레임을 컨테이너 중간에 배치합니다(부모 프레임에서 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 0%).
      4. Size{1, 0},{0.67, 0}으로 설정하여 선택 UI 구성 요소가 컨테이너의 위에서 아래까지 약 반 이상 차지하게 합니다(부모 프레임의 100% 수평 및 67% 수직).
      5. NameObjectiveDisplay로 설정합니다.
  3. 제목 요소를 생성합니다.

    1. ObjectiveDisplayImageLabel을 삽입합니다.

    2. ImageLabel을 선택한 다음 속성 창에서,

      1. AnchorPoint0.5, 1로 설정하여 레이블의 원점이 가장 아래 가운데에 있도록 합니다(레이블의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 100%).
      2. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
      3. LayoutOrder-1로 설정합니다.
      4. Position{0.5, 0},{0.34, 0}으로 설정하여 레이블을 프레임의 가장 위쪽 가운데에 위치하게 합니다(부모 프레임에서 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 34%).
      5. Size{0.46, 0},{0.34, 0}으로 설정하여 프롬프트 영역을 프레임의 거의 반으로 넓히십시오(부모 프레임의 46% 수평 및 34% 수직).
      6. NameHeader로 설정합니다.
      7. Imagerbxassetid://14304828123로 설정하여 사다리꼴을 표시합니다.
      8. ImageTransparency0.15로 설정하여 헤더를 반투명하게 만듭니다.
    3. (선택 사항) ImageLabelUIAspectRatioConstraint를 삽입하여 레이블의 종횡비가 플레이어의 화면 크기와 관계없이 유지되도록 합니다. 샘플은 UIAspectRatioConstraint.AspectRatio 속성을 13.781로 설정합니다.

    4. HeaderTextLabel을 삽입하여 제목을 표시합니다.

    5. 새 레이블을 선택한 다음 속성 창에서,

      1. AnchorPoint0.5, 0.5로 설정하여 새 레이블의 원점이 레이블의 중앙에 있도록 합니다(레이블의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 50%).
      2. BackgroundTransparency1로 설정하여 레이블의 배경이 완전히 투명하게 합니다.
      3. Position{0.5, 0},{0.5, 0}으로 설정하여 레이블을 부모 레이블의 중앙으로 이동합니다(레이블의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 50%).
      4. Size{0.62, 0},{0.55, 0}로 설정하여 텍스트 공간을 부모 레이블의 절반 이상으로 넓힙니다(부모 레이블의 62% 수평 및 55% 수직).
      5. NameHeaderTextLabel로 설정합니다.
      6. FontFaceMontserrat로 설정하여 미래적인 미학에 맞춥니다.
      7. WeightMedium으로 설정하여 글꼴을 두껍게 만듭니다.
      8. Text목표로 설정합니다.
      9. TextScaled을 활성화합니다.
  4. 프롬프트 요소를 생성합니다.

    1. ObjectiveDisplayImageLabel을 삽입합니다.

    2. ImageLabel을 선택한 다음 속성 창에서,

      1. AnchorPoint0.5, 1로 설정하여 레이블의 원점이 하단 중앙에 있도록 합니다(레이블의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 100%).
      2. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
      3. Position{0.5, 0},{1, 0}으로 설정하여 레이블을 부모 프레임의 하단 중앙에 위치하게 합니다(부모 프레임 좌측에서 우측까지 50%, 위에서 아래까지 100%).
      4. Size{0.89, 0},{0.66, 0}으로 설정하여 텍스트 공간을 부모 프레임의 거의 전체 너비로 넓힙니다(부모 프레임의 89% 수평 및 66% 수직).
      5. NameBody로 설정합니다.
      6. Imagerbxassetid://14304827265로 설정하여 거꾸로 된 사다리꼴을 표시합니다.
      7. ImageColor30, 0, 0으로 설정하여 이미지를 검정색으로 톤 조정합니다.
      8. ImageTransparency0.3으로 설정하여 헤더를 반투명하게 만듭니다.
    3. (선택 사항) ImageLabelUIAspectRatioConstraint를 삽입하여 레이블의 종횡비가 플레이어의 화면 크기와 관계없이 유지되도록 합니다. 샘플은 UIAspectRatioConstraint.AspectRatio 속성을 13.781로 설정합니다.

    4. BodyTextLabel을 삽입하여 프롬프트를 표시합니다.

    5. 새 레이블을 선택한 다음 속성 창에서,

      1. AnchorPoint0.5, 0.5로 설정하여 새 레이블의 원점이 레이블의 동일한 위치에 있도록 합니다(레이블의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 50%).
      2. BackgroundTransparency1로 설정하여 레이블의 배경이 완전히 투명하게 합니다.
      3. Position{0.5, 0},{0.5, 0}으로 설정하여 레이블을 부모 레이블의 중앙으로 이동합니다(레이블의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 50%).
      4. Size{0.85, 0},{0.39, 0}으로 설정하여 텍스트 공간을 부모 레이블의 절반 이상으로 넓힙니다(부모 레이블의 85% 수평 및 39% 수직).
      5. NameBodyTextLabel로 설정합니다.
      6. FontFaceMontserrat로 설정하여 미래적인 미학에 맞춥니다.
      7. WeightMedium으로 설정하여 글꼴을 두껍게 만듭니다.
      8. TextColor3255, 255, 255로 설정하여 어두운 배경에 대비하여 텍스트를 흰색으로 만듭니다.
      9. Text를 **상대 플레이어를 태그하여 점수를 얻으세요! 첫 번째 팀이 %d 점을 얻으면 승리합니다.**로 설정합니다.
      10. TextScaled을 활성화합니다.
  5. 목표 팀 카운터의 컨테이너를 생성합니다.

    1. Objective프레임을 삽입합니다.

    2. 프레임을 선택한 다음 속성 창에서,

      1. AnchorPoint0.5, 1로 설정하여 프레임의 원점이 가장 위 가운데에 있도록 합니다(50%에서 50%, 상단에서 하단까지 100%).
      2. BackgroundTransparency1로 설정하여 프레임의 배경을 완전히 투명하게 만듭니다.
      3. Position{0.5, 0},{1, 0}으로 설정하여 프레임이 컨테이너의 하단 가운데에 위치하도록 합니다(50%에서 50%, 상단에서 하단까지 100%).
      4. Size{0.44, 0},{0.27, 0}으로 설정하여 선택 UI 구성 요소가 컨테이너의 왼쪽에서 오른쪽까지 약 절반 이하를 차지하게 합니다(부모 프레임의 44% 수평 및 27% 수직).
      5. NameTeamPointCounter로 설정합니다.
  6. 팀 카운터에 패딩을 생성합니다.

    1. 단계 5의 프레임에 UIListLayout 객체를 삽입합니다.
    2. UIListLayout 객체를 선택한 다음 속성 창에서,
      1. Padding0.025, 0로 설정하여 향후 팀 카운터 간의 간격을 제공합니다.
      2. FillDirectionHorizontal로 설정하여 각 팀 카운터가 나란히 표시되도록 합니다.
      3. HorizontalAlignmentCenter로 설정하여 각 팀 카운터가 서로 중앙에 정렬되도록 합니다.
  7. 그린 팀 카운터 요소를 생성합니다.

    1. TeamPointCounterImageLabel을 삽입합니다.

    2. ImageLabel을 선택한 다음 속성 창에서,

      1. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
      2. Position{0.5, 0},{1, 0}으로 설정하여 레이블을 부모 프레임의 하단 중앙에 위치하게 합니다(왼쪽에서 오른쪽까지 50%, 위에서 아래까지 100%).
      3. Size{0.5, 0},{1, 0}으로 설정하여 레이블을 부모 프레임의 절반 너비로 넓힙니다(부모 프레임의 50% 수평 및 100% 수직).
      4. NameTeamACounter로 설정합니다.
      5. Imagerbxassetid://14304826831로 설정하여 방향 페이드를 표시합니다.
      6. ImageColor388, 218, 171로 설정하여 이미지를 민트 초록색으로 톤 조정합니다.
    3. 이 레이블이 그린 팀을 위한 것임을 추적하기 위해 사용자 정의 속성을 구성합니다.

      1. 속성 창에서 속성 섹션으로 이동한 다음 플러스 아이콘을 클릭합니다. 팝업 대화 상자가 표시됩니다.
      2. 이름 필드에 teamColor를 입력합니다.
      3. 유형 드롭다운 메뉴에서 BrickColor를 선택합니다.
      4. 저장 버튼을 클릭합니다.
      5. teamColor 속성을 Mint로 설정합니다.
    4. TeamACounterTextLabel을 삽입하여 프롬프트를 표시합니다.

    5. 새 레이블을 선택한 다음 속성 창에서,

      1. AnchorPoint1, 0.5로 설정하여 새 레이블의 원점이 가장 오른쪽 중앙에 있도록 합니다(100%에서 50%, 위에서 아래까지 50%).
      2. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
      3. Position{0.95, 0},{0.5, 0}으로 설정하여 레이블을 부모 레이블의 오른쪽에 위치하게 합니다(부모 레이블의 왼쪽에서 오른쪽까지 95%, 위에서 아래까지 50%).
      4. Size{0.85, 0},{0.39, 0}으로 설정하여 텍스트 공간을 부모 레이블의 절반 이상으로 넓힙니다(부모 레이블의 85% 수평 및 39% 수직).
      5. FontFaceMontserrat로 설정하여 미래적인 미학에 맞춥니다.
      6. WeightBold로 설정하여 글꼴을 두껍게 만듭니다.
      7. TextColor3255, 255, 255로 설정하여 어두운 배경에서 텍스트를 흰색으로 만듭니다.
      8. Text를 **-**로 설정합니다.
      9. TextScaled을 활성화합니다.
      10. TextXAlignmentRight로 설정합니다.
    6. TextLabelUIStroke 객체를 삽입한 다음 속성 창에서 Color8, 78, 52로 설정하여 대시 외곽선을 어두운 초록색으로 만듭니다.

  8. 핑크 팀 카운터 요소를 생성합니다.

    1. TeamAICounter와 그 자식들을 복제합니다.

    2. 복제된 TeamACounter를 선택한 다음 속성 창에서,

      1. NameTeamBCounter로 설정합니다.
      2. Imagerbxassetid://14305849451로 설정하여 반대 방향의 방향 페이드를 표시합니다.
      3. ImageColor3255, 170, 255로 설정하여 이미지를 카네이션 핑크로 톤 조정합니다.
      4. teamColor 속성을 카네이션 핑크로 설정합니다.
    3. 복제된 TeamBCounterTextLabel 자식을 선택한 다음 속성 창에서,

      1. AnchorPoint0, 0.5로 설정하여 새 레이블의 원점이 왼쪽 중앙에 있도록 합니다(0%에서 0%, 위에서 아래까지 50%).
      2. Position{0.05, 0},{0.5, 0}으로 설정하여 레이블을 부모 레이블의 왼쪽으로 이동합니다(부모 레이블의 5%에서 오른쪽까지 0%, 위에서 아래까지 50%).
      3. TextXAlignmentLeft로 설정합니다.
    4. 복제된 TeamBCounterUIStroke 자식을 선택한 다음 속성 창에서 Color158, 18, 94로 설정하여 대시 외곽선을 어두운 핑크색으로 만듭니다.

  9. 샘플 레이저 태그 장소 파일 내에서 목표 프롬프트를 프로그래밍적으로 업데이트하고 팀 포인트를 추적하는 다음 ReplicatedStorage 스크립트를 참조하십시오.

다음 스크립트는 setObjectivestartSyncingTeamPoints를 포함하여 주요 Heads Up Display (HUD)를 설정하기 위해 함께 작동하는 모듈 스크립트 세트를 필요로 합니다. 플레이어가 라운드에 참가하고 자신의 블래스터를 선택한 후, 이 스크립트는 모든 HUD UI 요소가 플레이어의 상태, 장치 및 팀 상태에 적절하게 표시되도록 합니다.


local Players = game:GetService("Players")
local setPlayerPortrait = require(script.setPlayerPortrait)
local setPlayerName = require(script.setPlayerName)
local startSyncingTeamColor = require(script.startSyncingTeamColor)
local setObjective = require(script.setObjective)
local setupTouchButtonAsync = require(script.setupTouchButtonAsync)
local startSyncingTeamPoints = require(script.startSyncingTeamPoints)
local disableMouseWhileGuiEnabled = require(script.disableMouseWhileGuiEnabled)
local setupHitmarker = require(script.setupHitmarker)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("HUDGui")
setPlayerPortrait(gui)
setPlayerName(gui)
startSyncingTeamColor(gui)
setObjective(gui)
startSyncingTeamPoints(gui)
disableMouseWhileGuiEnabled(gui)
setupHitmarker(gui)
setupTouchButtonAsync(gui)

블래스터 UI

와이어프레임 레이아웃의 시각적 계층 구조 모범 사례를 따르면서, 이 섹션에서는 플레이어의 블래스터와 관련된 모든 화면 UI 요소를 구현하는 방법을 가르칩니다. 이 UI 요소의 그룹은 화면 중앙 근처의 대부분 공간을 차지하기 때문에 3D 공간에서의 행동에 플레이어의 주의를 끌어모으는 중심점 역할을 하며, 게임 플레이 중 가장 큰 중요성을 갖습니다.

조준대

조준대는 플레이어에게 무기를 발사할 때 충돌할 위치를 알려주는 UI 요소입니다. 이 UI 요소는 1인칭 슈팅 경험을 위해 필수적인 게임 플레이 요구 사항으로, 플레이어가 자신의 블래스터를 정확하게 조준하고 적 팀원을 태그할 수 있도록 해야 합니다.

대부분의 1인칭 슈팅 장르의 경험과 마찬가지로, 샘플 레이저 태그 경험은 플레이어가 3D 공간을 이동하는 동안 정적 기준으로 삼을 수 있도록 조준대를 화면 중앙에 배치합니다. 이를 통해 동요를 줄일 수 있을 뿐 아니라 환경에 자연스럽게 녹아들도록 합니다.

샘플 레이저 태그 경험 내에서 조준대를 정확하게 재현하려면:

  1. HUDGui ScreenGui 객체에 ImageLabel을 삽입합니다.

    1. 탐색기 창에서 StarterGui 서비스로 이동합니다.

    2. 자식 HUDGui 객체 위에 커서를 놓고 아이콘을 클릭합니다. 문맥 메뉴가 표시됩니다.

    3. 문맥 메뉴에서 ImageLabel을 삽입합니다.

  2. ImageLabel을 선택한 다음 속성 창에서,

    1. Imagerbxassetid://14400935446로 설정합니다.
    2. AnchorPoint0.5, 0.5로 설정하여 레이블의 원점이 레이블의 가운데에 있도록 합니다(50%에서 레이블의 왼쪽에서 오른쪽으로, 50%에서 위에서 아래로).
    3. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 합니다.
    4. NameCrosshair로 설정합니다.
    5. Position{0.5,0},{0.5,0}으로 설정하여 레이블을 화면의 가운데에 위치하게 합니다.
    6. ScaleTypeFit으로 설정하여 이미지가 컨테이너에 맞고 다양한 화면 크기에서 늘어나지 않도록 합니다.
  3. (선택 사항) CrosshairUIAspectRatioConstraint를 삽입하여 레이블의 종횡비가 플레이어의 화면 크기와 관계없이 유지되도록 합니다. 샘플은 UIAspectRatioConstraint.AspectRatio 속성을 0.895로 설정합니다.

히트 마커

히트 마커는 발사가 적 팀의 다른 플레이어와 충돌할 때만 표시되는 UI 요소입니다. 조준대와 마찬가지로, 이 UI 요소는 1인칭 슈팅 경험을 위한 필수적인 게임 플레이 요구 사항으로, 플레이어가 상대를 태그할 때 성공을 시각적으로 피드백을 제공합니다.

샘플 레이저 태그 경험 내에서 히트 마커를 정확하게 재현하려면:

  1. Crosshair ImageLabel 객체에 ImageLabel을 삽입합니다.

    1. 탐색기 창에서 StarterGui 서비스로 이동합니다.

    2. 자식 Crosshair 객체 위에 커서를 놓고 아이콘을 클릭합니다. 문맥 메뉴가 표시됩니다.

    3. 문맥 메뉴에서 ImageLabel을 삽입합니다.

  2. ImageLabel을 선택한 다음 속성 창에서,

    1. Imagerbxassetid://14401148736으로 설정하여 직사각형 히트 마커 아이콘을 표시합니다.
    2. AnchorPoint0.5, 0.5로 설정하여 레이블의 원점이 레이블의 중앙에 있도록 합니다.
    3. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 합니다.
    4. Position{0.5,0},{0.5,0}으로 설정하여 레이블을 화면의 중앙에 위치하게 합니다.
    5. NameHitmarker로 설정합니다.
    6. Size{0.6, 0},{0.06, 0}으로 설정하여 조준대 중앙 주변의 직사각형 크기를 줄입니다.
    7. ImageTransparency1로 설정하여 히트 마커를 완전히 투명하게 만듭니다. 다음 단계의 스크립트는 적 팀의 다른 플레이어와 충돌할 때마다 투명도를 다시 0으로 설정합니다.
  3. 샘플 레이저 태그 장소 파일 내에서 다른 플레이어와의 충돌 시 히트 마커를 프로그래밍적으로 표시하는 다음 ReplicatedStorage 스크립트를 참조하십시오.

다음 스크립트는 setupHitmarker를 포함하여 주요 Heads Up Display (HUD)를 설정하기 위해 함께 작동하는 모듈 스크립트 세트를 필요로 합니다. 플레이어가 라운드에 참가하고 자신의 블래스터를 선택한 후, 이 스크립트는 모든 HUD UI 요소가 플레이어의 상태, 장치 및 팀 상태에 적절하게 표시되도록 합니다.


local Players = game:GetService("Players")
local setPlayerPortrait = require(script.setPlayerPortrait)
local setPlayerName = require(script.setPlayerName)
local startSyncingTeamColor = require(script.startSyncingTeamColor)
local setObjective = require(script.setObjective)
local setupTouchButtonAsync = require(script.setupTouchButtonAsync)
local startSyncingTeamPoints = require(script.startSyncingTeamPoints)
local disableMouseWhileGuiEnabled = require(script.disableMouseWhileGuiEnabled)
local setupHitmarker = require(script.setupHitmarker)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("HUDGui")
setPlayerPortrait(gui)
setPlayerName(gui)
startSyncingTeamColor(gui)
setObjective(gui)
startSyncingTeamPoints(gui)
disableMouseWhileGuiEnabled(gui)
setupHitmarker(gui)
setupTouchButtonAsync(gui)

블래스터 선택기

블래스터 선택기는 플레이어가 라운드에 참가하거나 재가입하기 전에 블래스터 유형을 선택하는 데 사용하는 UI 구성 요소입니다. 샘플 레이저 태그 경험은 수평적으로 넓게 퍼진 여러 빔을 생성하는 블래스터와 단일 빔을 생성하는 블래스터의 두 가지 유형을 제공합니다. 플레이어가 선택하는 블래스터 유형은 라운드 중 전략에 영향을 미치므로, 이 UI 구성 요소는 전체 경험을 위한 필수적인 워크플로입니다.

다음 단계는 다양한 UI 요소 그룹을 위한 여러 컨테이너, 프롬프트가 있는 헤더, 탐색 및 선택 버튼, 블래스터 버튼 프리팩을 만드는 방법을 자세히 설명합니다. 전체 구성 요소에 대한 스크립팅 논리는 각 블래스터 유형을 나타내는 Configuration 인스턴스에 따라 블래스터 버튼 프리팩의 다양한 시각적 특성을 채웁니다.

이 설정을 통해 Configuration 인스턴스를 추가하여 더 많은 블래스터 유형을 생성할 수 있으며, 이를 통해 선택기 내에서 개별 버튼을 생성할 필요 없이 자동으로 올바르게 표시됩니다.

샘플 레이저 태그 경험 내에서 블래스터 선택기를 정확하게 재현하려면:

  1. 전체 구성 요소에 대한 컨테이너를 생성합니다.

    1. PickABlaster ScreenGui 객체에 프레임을 삽입합니다.

      1. 탐색기 창에서 StarterGui 서비스로 이동합니다.
      2. 자식 PickABlaster 객체 위에 커서를 놓고 ⊕ 아이콘을 클릭합니다. 문맥 메뉴가 표시됩니다.
      3. 문맥 메뉴에서 프레임을 삽입합니다.
    2. 새 프레임을 선택한 다음 속성 창에서,

      1. AnchorPoint0.5, 1로 설정하여 프레임의 원점이 하단 가운데에 있도록 합니다(프레임의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 100%).
      2. BackgroundTransparency1로 설정하여 프레임의 배경을 완전히 투명하게 만듭니다.
      3. Position{0.5, 0},{0.9, 0}으로 설정하여 프레임이 화면의 하단 가운데에 가까이 위치하게 합니다(50%에서 왼쪽에서 오른쪽까지 0, 위에서 아래까지 92.4%).
      4. Size{0.8, 0},{0.25, 0}으로 설정하여 블래스터 선택기의 UI 구성 요소가 화면에서 큰 부분을 차지하여 플레이어의 주의를 끌도록 합니다(수평으로 80%, 수직으로 25%).
      5. NameComponent로 설정합니다.
    3. (선택 사항) ComponentUIAspectRatioConstraint를 삽입하여 프레임과 그 자식 UI 요소의 종횡비가 플레이어의 화면 크기에 관계없이 유지되도록 합니다. 샘플은 UIAspectRatioConstraint.AspectRatio 속성을 5로 설정합니다.

  2. UI 요소 그룹을 보유할 컨테이너를 생성합니다.

    1. Component프레임을 삽입합니다.

    2. 새 프레임을 선택한 다음 속성 창에서,

      1. AnchorPoint0.5, 0.5로 설정하여 프레임의 원점이 프레임의 한가운데에 있도록 합니다(프레임의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 50%).
      2. BackgroundTransparency1로 설정하여 프레임의 배경을 완전히 투명하게 만듭니다.
      3. Position{0.5, 0},{0.375, 0}으로 설정하여 프레임을 컨테이너의 최상단 가운데에 위치하게 합니다(부모 프레임의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 37.5%).
      4. Size{1, 0},{0.75, 0}으로 설정하여 선택 UI 구성 요소가 컨테이너의 3/4를 차지하게 합니다(부모 프레임의 100% 수평 및 75% 수직).
      5. NameSelectionFrame으로 설정합니다.
  3. 블래스터 선택기의 프롬프트를 생성합니다.

    1. SelectionFrameImageLabel을 삽입합니다.

    2. 새 레이블을 선택한 다음 속성 창에서,

      1. AnchorPoint0.5, 1으로 설정하여 레이블의 원점이 가장 아래 가운데에 있도록 합니다(50%에서 방향의 왼쪽에서 오른쪽, 100%에서 위에서 아래로).
      2. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
      3. LayoutOrder-1로 설정합니다.
      4. Position{0.5, 0},{0.22, 0}으로 설정하여 레이블을 프레임의 가장 위쪽 가운데에 위치하게 합니다(부모 프레임에서 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 22%).
      5. Size{0.45, 0},{0.22, 0}으로 설정하여 프롬프트 영역을 프레임의 거의 반으로 넓힙니다(부모 프레임의 45% 수평 및 22% 수직).
      6. NameHeader로 설정합니다.
      7. Imagerbxassetid://14304828123로 설정하여 사다리꼴을 표시합니다.
      8. ImageTransparency0.15로 설정하여 헤더를 반투명하게 만듭니다.
    3. (선택 사항) 레이블에 UIAspectRatioConstraint를 삽입하여 레이블의 종횡비가 플레이어의 화면 크기에 관계없이 유지되도록 합니다. 샘플은 UIAspectRatioConstraint.AspectRatio 속성을 13.78로 설정합니다.

    4. HeaderTextLabel을 삽입하여 프롬프트를 표시합니다.

    5. 새 레이블을 선택한 다음 속성 창에서,

      1. AnchorPoint0.5, 0.5로 설정하여 새 레이블의 원점이 가운데에 있도록 합니다(레이블의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 50%).
      2. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
      3. Position{0.5, 0},{0.5, 0}으로 설정하여 레이블을 부모 레이블 중앙으로 이동합니다(레이블의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 50%).
      4. Size{0.6, 0},{0.55, 0}으로 설정하여 텍스트 공간을 부모 레이블의 절반 이상으로 넓힙니다(부모 레이블의 60% 수평 및 55% 수직).
      5. NameHeaderTextLabel로 설정합니다.
      6. FontFaceMontserrat로 설정하여 미래적인 미학에 맞춥니다.
      7. WeightMedium으로 설정하여 글꼴을 두껍게 만듭니다.
      8. Text블래스터 선택으로 설정합니다.
      9. TextScaled을 활성화합니다.
  4. 블래스터 버튼 컨테이너 및 선택 화살표에 대한 컨테이너를 생성합니다.

    1. SelectionFrameImageLabel을 삽입합니다.

    2. 새 레이블을 선택한 다음 속성 창에서,

      1. 기본 Image 값을 제거합니다.
      2. AnchorPoint0.5, 1로 설정하여 레이블의 원점이 가장 아래 가운데에 있도록 합니다(레이블의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 100%).
      3. BackgroundColor0, 0, 0으로 설정하여 레이블을 검정색으로 만듭니다.
      4. BackgroundTransparency0.3으로 설정하여 레이블의 불투명도를 30% 줄여 경험의 다른 검은색 UI 요소와 일치시킵니다.
      5. Position{0.5, 0},{1, 0}으로 설정하여 레이블을 프레임의 하단 중앙에 위치하게 합니다(부모 프레임에서 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 100%).
      6. Size{1, 0},{0.77, 0}으로 설정하여 텍스트 공간 그 이외의 공간을 확보합니다(부모 프레임의 100% 수평 및 77% 수직).
    3. 컨테이너의 모서리를 둥글게 만듭니다.

      1. 레이블에 UICorner 객체를 삽입합니다.
      2. 새 모서리 객체를 선택한 다음 속성 창에서 CornerRadius0.075, 0으로 설정하여 모서리를 둥글게 만듭니다.
  5. 블래스터 버튼의 컨테이너를 생성합니다.

    1. 레이블에 이전 단계의 프레임을 삽입합니다.

    2. 새 프레임을 선택한 다음 속성 창에서,

      1. AnchorPoint0.5, 0.5로 설정하여 새 프레임의 원점이 가운데에 있도록 합니다(프레임의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 50%).
      2. BackgroundTransparency1로 설정하여 프레임의 배경을 완전히 투명하게 만듭니다.1. 위치{0.5, 0},{0.5, 0}로 설정하여 프레임을 부모 레이블의 가운데에 배치합니다 (부모 프레임의 왼쪽에서 오른쪽까지 50%, 위에서 아래까지 50%).
  6. 크기{0.85, 0},{0.77, 0}로 설정하여 프레임 영역을 레이블의 대부분으로 넓힙니다 (부모 레이블의 수평으로 85%, 수직으로 77%).

  7. 이름Container로 설정합니다.

  1. 모든 미래 블래스터 버튼을 위한 패딩을 만듭니다.

    1. 5단계에서 프레임에 UIListLayout 객체를 삽입합니다.
    2. 새 레이아웃 객체를 선택한 후, 속성 창에서,
      1. **패딩(Padding)**을 0.035, 0으로 설정하여 모든 미래 버튼 사이에 공간을 제공합니다.
      2. **채우기 방향(FillDirection)**을 **수평(Horizontal)**로 설정하여 각 버튼이 서로 옆에 표시되도록 합니다.
      3. 수평 정렬(HorizontalAlignment) 및 **수직 정렬(VerticalAlignment)**을 모두 **중앙(Center)**로 설정하여 각 버튼이 서로의 가운데에 정렬되도록 합니다.
  2. 왼쪽 탐색 버튼을 만듭니다.

    1. 4단계의 ImageLabelImageButton 객체를 삽입합니다.

    2. 새 버튼을 선택한 후, 속성 창에서,

      1. 기본 이미지 값을 제거합니다.
      2. AnchorPoint0, 0.5로 설정하여 새 버튼의 원점을 버튼의 왼쪽 가운데에 설정합니다 (버튼의 왼쪽에서 오른쪽으로 0%, 위에서 아래로 50%).
      3. **배경 투명도(BackgroundTransparency)**를 0.15로 설정하여 버튼이 선택 가능하다는 시각적 피드백을 제공합니다.
      4. **위치(Position)**를 {0.02, 0},{0.5, 0}로 설정하여 부모 컨테이너의 왼쪽에 버튼 패딩을 제공합니다 (부모 레이블의 왼쪽에서 오른쪽으로 2%, 위에서 아래로 50%).
      5. **크기(Size)**를 {0.04, 0},{0.33, 0}로 설정하여 선택 버튼이 블래스터 버튼보다 훨씬 작게 만듭니다 (부모 프레임의 수평으로 4%, 수직으로 33%).
      6. 이름NavigationButtonLeft로 설정합니다.
    3. 버튼 모서리를 둥글게 만듭니다.

      1. 버튼에 UICorner 객체를 삽입합니다.
      2. 새 모서리 객체를 선택한 후, 속성 창에서 CornerRadius0.1, 0로 설정하여 모서리를 둥글게 만듭니다.
    4. 버튼에 ImageLabel 객체를 삽입합니다.

    5. 새 레이블을 선택한 후, 속성 창에서,

      1. AnchorPoint0.5, 0.5로 설정하여 새 레이블의 원점을 레이블의 가운데에 설정합니다 (레이블의 왼쪽에서 오른쪽으로 50%, 위에서 아래로 50%).
      2. **위치(Position)**를 {0.45, 0},{0.5, 0}로 설정하여 레이블을 부모 버튼의 가운데 근처에 설정합니다 (부모 버튼의 왼쪽에서 오른쪽으로 45%, 위에서 아래로 50%). 이 값은 중간에 위치하지 않는데, 화살표가 {0.5, 0},{0.5, 0}에서 버튼의 중간에 시각적으로 보이지 않기 때문입니다.
      3. **크기(Size)**를 {0.8, 0},{0.8, 0}로 설정하여 텍스트 공간을 프롬프트 아래쪽으로 넓힙니다 (부모 프레임의 수평으로 80%, 수직으로 80%).
      4. **배경 투명도(BackgroundTransparency)**를 1로 설정하여 이미지의 배경을 완전히 투명하게 만듭니다.
      5. 이미지rbxassetid://14309187238로 설정합니다.
      6. ScaleTypeFit으로 설정합니다.
  3. 오른쪽 탐색 버튼을 만듭니다.

    1. NavigationButtonLeft를 복제합니다.

    2. 복제된 버튼을 선택한 후, 속성 창에서,

      1. AnchorPoint1, 0.5로 설정하여 새 버튼의 원점을 버튼의 오른쪽 가운데에 설정합니다 (버튼의 왼쪽에서 오른쪽으로 100%, 위에서 아래로 50%).
      2. **위치(Position)**를 {0.98, 0},{0.5, 0}로 설정하여 부모 컨테이너의 오른쪽에 버튼 패딩을 제공합니다 (부모 레이블의 왼쪽에서 오른쪽으로 98%, 위에서 아래로 50%).
      3. 이름NavigationButtonRight로 설정합니다.
    3. ImageLabel 자식 객체를 선택합니다.

      1. **회전(Rotation)**을 180으로 설정하여 이미지를 뒤집습니다.
      2. **위치(Position)**를 {0.55, 0},{0.5, 0}로 설정하여 레이블을 부모 버튼의 가운데 근처에 설정합니다 (부모 버튼의 왼쪽에서 오른쪽으로 55%, 위에서 아래로 50%). 이 값은 중간에 위치하지 않는데, 화살표가 {0.5, 0},{0.5, 0}에서 버튼의 중간에 시각적으로 보이지 않기 때문입니다.
  4. 선택(SELECT) 버튼을 만듭니다.

    1. ComponentImageButton을 삽입합니다. 이 과정은 선택 버튼을 SelectionFrame과 분리하여 주 구성 요소와 선택 버튼 사이에 패딩을 추가할 수 있도록 합니다.

    2. 새 버튼을 선택한 후, 속성 창에서,

      1. 기본 이미지 값을 제거합니다.
      2. AnchorPoint0.5, 1로 설정하여 새 버튼의 원점을 아래쪽 가운데에 설정합니다 (버튼의 왼쪽에서 오른쪽으로 50%, 위에서 아래로 100%).
      3. **배경 투명도(BackgroundTransparency)**를 0.15로 설정하여 버튼이 선택 가능하다는 시각적 피드백을 제공합니다.
      4. **위치(Position)**를 {0.5, 0},{0.99, 0}로 설정하여 버튼을 부모 컨테이너의 하단 중앙 근처에 설정합니다 (부모 프레임의 왼쪽에서 오른쪽으로 50%, 위에서 아래로 99%).
      5. **크기(Size)**를 {0.17, 0},{0.18, 0}로 설정하여 블래스터 버튼 아래쪽에 버튼 길이를 만듭니다 (부모 프레임의 수평으로 17%, 수직으로 18%).
      6. 이름SelectButton으로 설정합니다.
    3. 버튼 모서리를 둥글게 만듭니다.

      1. 버튼에 UICorner 객체를 삽입합니다.
      2. 새 모서리 객체를 선택한 후, 속성 창에서 CornerRadius0.2, 0로 설정하여 모서리를 둥글게 만듭니다.
    4. 버튼에 TextLabel 객체를 삽입하여 호출하기 위한 작업을 표시합니다.

    5. 새 레이블을 선택한 후, 속성 창에서,

      1. AnchorPoint0.5, 0.5로 설정하여 새 레이블의 원점을 레이블의 가운데에 설정합니다 (레이블의 왼쪽에서 오른쪽으로 50%, 위에서 아래로 50%).
      2. **배경 투명도(BackgroundTransparency)**를 1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
      3. **위치(Position)**를 {0.5, 0},{0.5, 0}로 설정하여 레이블을 버튼의 중간으로 이동시킵니다 (부모 버튼의 왼쪽에서 오른쪽으로 50%, 위에서 아래로 50%).
      4. **크기(Size)**를 {0.9, 0},{0.55, 0}로 설정하여 텍스트 공간을 대부분의 부모 레이블 너비로 넓힙니다 (부모 레이블의 수평으로 90%, 수직으로 55%).
      5. 이름SelectTextLabel로 설정합니다.
      6. FontFaceMontserrat로 설정하여 미래적 미학에 맞춥니다.
      7. WeightMedium으로 설정하여 글꼴을 두껍게 합니다.
      8. **텍스트(Text)**를 SELECT로 설정합니다.
      9. TextScaled를 활성화합니다.
  5. 블래스터 버튼 프리팹을 만듭니다.

    1. ReplicatedStorage 서비스에서 UI 객체를 정리하기 위한 폴더 구조를 만듭니다. 샘플은 자식 Guis 폴더와 함께 Instances 폴더를 사용합니다.
    2. Guis 폴더에 ImageButton 객체를 삽입합니다.
    3. 새 버튼을 선택한 후, 속성 창에서,
      1. 기본 이미지 값을 제거합니다.
      2. AnchorPoint0.5, 0.5로 설정하여 새 버튼의 원점을 가운데에 설정합니다 (버튼의 왼쪽에서 오른쪽으로 50%, 위에서 아래로 50%).
      3. **배경 투명도(BackgroundTransparency)**를 0.65로 설정하여 버튼이 포커스되지 않았다는 시각적 피드백을 제공합니다. 12단계의 스크립트는 버튼이 포커스될 때 프로그래밍 방식으로 시각적 피드백을 제공합니다.
      4. **레이아웃 순서(LayoutOrder)**를 2로 설정합니다.
      5. 이름BlasterButtonPrefab으로 설정합니다.
      6. **크기(Size)**를 {0.8, 0},{0.8, 0}로 설정합니다.
      7. **이미지 투명도(ImageTransparency)**를 1로 설정하여 이미지를 완전히 투명하게 만듭니다.
    4. BlasterButtonPrefabUIAspectRatioConstraint을 삽입하여 버튼의 종횡비가 플레이어의 화면 크기와 관계없이 같은 상태를 유지하도록 합니다.
    5. 버튼 모서리를 둥글게 만듭니다.
      1. BlasterButtonPrefabUICorner 객체를 삽입합니다.
      2. UICorner를 선택한 후, 속성 창에서 CornerRadius0.05, 0로 설정하여 모서리를 둥글게 만듭니다.
    6. BlasterButtonPrefabImageLabel을 삽입합니다.
    7. 새 레이블을 선택한 후, 속성 창에서,
      1. 기본 이미지 값을 제거합니다.
      2. AnchorPoint0.5, 0.5로 설정하여 새 레이블의 원점을 가운데에 설정합니다 (레이블의 왼쪽에서 오른쪽으로 50%, 위에서 아래로 50%).
      3. **배경 투명도(BackgroundTransparency)**를 1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
      4. **위치(Position)**를 {0.52, 0},{0.497, 0}로 설정하여 레이블을 부모 버튼의 가운데 근처에 설정합니다 (부모 버튼의 왼쪽에서 오른쪽으로 52%, 위에서 아래로 49.7%). 이 값은 중간에 위치하지 않는데, 블래스터가 {0.5, 0},{0.5, 0}에서 버튼의 중간에 시각적으로 보이지 않기 때문입니다.
      5. **크기(Size)**를 {1.20, 0},{0.9, 0}로 설정하여 레이블 영역을 버튼 밖으로 넓힙니다 (부모 버튼의 수평으로 120%, 수직으로 90%).
      6. ScaleTypeFit으로 설정합니다.
  6. 샘플 레이저 태그 장소 파일 내에서 다음 ReplicatedStorage 스크립트를 참조하여 각 블래스터에 대한 버튼을 프로그래밍 방식으로 표시하고, 포커스되지 않은 버튼을 선택할 때 버튼 크기를 조정하며, 플레이어의 블래스터 선택을 아바타에 연결합니다.

다음 스크립트는 블래스터 선택기를 생성하기 위해 함께 작동하는 스크립트를 필요로 합니다. 플레이어가 경험에 참여하거나 건강이 0에 도달한 후 라운드에 다시 소환되면, 이 스크립트는 플레이어가 선택할 때까지 블래스터 선택기의 모든 UI 요소를 활성화합니다.


local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local GuiAttribute = require(ReplicatedStorage.GuiAttribute)
local setupBlasterButtons = require(script.setupBlasterButtons)
local connectResetSelectionOnEnabled = require(script.connectResetSelectionOnEnabled)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("PickABlasterGui")
setupBlasterButtons(gui)
connectResetSelectionOnEnabled(gui)
gui:SetAttribute(GuiAttribute.selectedIndex, 1)

블래스터 버튼

블래스터 버튼은 플레이어가 모바일 또는 태블릿 장치를 통해 경험에 접속할 때 블래스터를 발사하는 데 사용하는 UI 구성 요소입니다. 샘플 레이저 태그 경험은 텍스트 없이 버튼 기능을 전달하기 위해 조준선과 발사를 모두 묘사하는 아이콘이 포함된 블래스터 버튼을 사용합니다.

샘플 레이저 태그 경험 내에서 블래스터 버튼을 정확하게 재현하려면:

  1. HUDGui ScreenGui 객체에 ImageButton을 삽입합니다.

    1. 탐색기 창에서 StarterGui 서비스로 이동합니다.

    2. 해당 자식 HUDGui 객체 위에 마우스를 올린 다음 아이콘을 클릭합니다. 컨텍스트 메뉴가 표시됩니다.

    3. 컨텍스트 메뉴에서 ImageButton을 삽입합니다.

  2. 뷰포트에서 버튼이 플레이어의 엄지손가락이 자연스럽게 놓이는 곳으로 이동하여 해당 버튼이 플레이어의 장치에서 어떻게 보일지 시각적으로 감지한 후, 속성 창에서,

    1. **이미지(Image)**를 rbxassetid://18308375035로 설정하여 블래스터 버튼 아이콘을 표시합니다.
    2. PressedImagerbxassetid://18308372558로 설정하여 플레이어가 버튼을 누를 때 블래스터 버튼 아이콘의 반전 버전을 표시합니다.
    3. **배경 투명도(BackgroundTransparency)**를 1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
    4. 이름BlastButton으로 설정합니다.
    5. ScaleTypeFit으로 설정하여 이미지가 컨테이너에 맞아 여러 화면 크기에서 늘어나지 않도록 합니다.
    6. **이미지 투명도(ImageTransparency)**를 0.3으로 설정하여 레이블의 불투명도를 줄여서 경험 내 모든 검정색 UI 요소와 일치시킵니다.
  3. BlastButtonUIAspectRatioConstraint을 삽입하여 버튼의 종횡비가 플레이어의 화면 크기에 관계없이 같은 상태로 유지되도록 합니다.

  4. 샘플 레이저 태그 장소 파일 내에서 다음 ReplicatedStorage 스크립트를 참조하여 플레이어가 터치 입력을 사용하는 장치에서 블래스터 버튼이 프로그래밍 방식으로 표시되도록 합니다.

다음 스크립트는 setupTouchButtonAsync를 포함하여 주요 Heads Up Display (HUD)를 설정하기 위해 함께 작동하는 모듈 스크립트 집합을 필요로 합니다. 플레이어가 라운드에 참여하고 블래스터를 선택하면, 이 스크립트는 모든 HUD UI 요소가 플레이어의 상태, 장치 및 팀 상태에 적절하게 표시되도록 합니다.


local Players = game:GetService("Players")
local setPlayerPortrait = require(script.setPlayerPortrait)
local setPlayerName = require(script.setPlayerName)
local startSyncingTeamColor = require(script.startSyncingTeamColor)
local setObjective = require(script.setObjective)
local setupTouchButtonAsync = require(script.setupTouchButtonAsync)
local startSyncingTeamPoints = require(script.startSyncingTeamPoints)
local disableMouseWhileGuiEnabled = require(script.disableMouseWhileGuiEnabled)
local setupHitmarker = require(script.setupHitmarker)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("HUDGui")
setPlayerPortrait(gui)
setPlayerName(gui)
startSyncingTeamColor(gui)
setObjective(gui)
startSyncingTeamPoints(gui)
disableMouseWhileGuiEnabled(gui)
setupHitmarker(gui)
setupTouchButtonAsync(gui)

플레이어 UI

레이아웃의 와이어프레임에서 시각적 계층 구조 최선 사례를 따르면서, 이 섹션에서는 플레이어 상태와 관련된 모든 화면 UI 요소를 구현하는 방법을 설명합니다. 이 UI 요소 그룹은 화면의 측면 근처에 위치하여 플레이어가 게임 플레이에서 눈을 뗄 필요 없이 주변 정보를 신속하게 파악할 수 있습니다.

플레이어 표시기

플레이어 표시기는 플레이어가 팀의 스폰 존에 등장할 때 자신이 속한 팀을 신속하게 해독할 수 있도록 하는 UI 구성 요소입니다. 샘플 레이저 태그 경험은 플레이어가 녹색 또는 분홍색 팀인지에 따라 두 가지 버전의 플레이어 표시기를 제공합니다.

녹색 팀
분홍색 팀

색상 테마 선택에서의 지침에 따라, 두 가지 버전의 플레이어 표시기는 팀 색상을 간단한 아이콘과 조합하여 작은 화면에서도 가독성을 유지할 수 있도록 최소한의 세부 사항으로 디자인되었습니다. 두 개의 시각적 피드백 형식을 제공하는 것은 색맹인 플레이어를 위해 디자인 접근성을 유지하는 데 중요합니다.

샘플 레이저 태그 경험 내에서 플레이어 표시기 구성 요소를 정확하게 재현하려면:

  1. HUDGui ScreenGui 객체에 Frame을 삽입합니다.

    1. 탐색기 창에서 StarterGui 서비스로 이동합니다.
    2. 해당 자식 HUDGui 객체 위에 마우스를 올린 다음 아이콘을 클릭합니다. 컨텍스트 메뉴가 표시됩니다.
    3. 컨텍스트 메뉴에서 Frame을 삽입합니다.
  2. Frame을 선택한 후, 속성 창에서,

    1. AnchorPoint0, 1로 설정하여 프레임의 원점을 아래 가운데에 설정합니다 (프레임의 왼쪽에서 오른쪽으로 0%, 위에서 아래로 100%).

    2. **배경 투명도(BackgroundTransparency)**를 1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.

    3. 이름PlayerDisplay로 설정합니다.

    4. **위치(Position)**를 {0.02, 0},{0.97, 0}로 설정하여 프레임을 화면의 왼쪽 하단 근처에 배치합니다.

    5. **크기(Size)**를 {0.23, 0},{0.08, 0}로 설정하여 프레임을 짧고 넓게 만듭니다.

    6. ClipsDescendants를 활성화하여 프레임을 넘어서는 자식 GuiObjects를 잘라냅니다.

  3. 다각형 모양을 만듭니다.

    1. PlayerDisplayImageLabel을 삽입합니다.

    2. 새 레이블을 선택한 후, 속성 창에서,

      1. **이미지(Image)**를 rbxassetid://14304828123로 설정하여 트랩조이드 아이콘을 표시합니다.
      2. AnchorPoint1, 1로 설정하여 레이블의 원점을 아래 오른쪽에 설정합니다 (레이블의 왼쪽에서 오른쪽으로 100%, 위에서 아래로 100%).
      3. **배경 투명도(BackgroundTransparency)**를 1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
      4. 이름Block으로 설정합니다.
      5. **위치(Position)**를 {1,0},{1,0}로 설정하여 레이블을 프레임 오른쪽에 배치합니다.
      6. **크기(Size)**를 {1.858, 0},{0.581, 0}로 설정하여 레이블을 프레임 밖으로 넓히고, 프레임의 절반 길이보다 조금 더 짧게 설정합니다.
      7. **이미지 투명도(ImageTransparency)**를 0.15로 설정하여 레이블을 약간 투명하게 만듭니다.
      8. ScaleTypeFit으로 설정하여 이미지가 컨테이너 내에 맞도록 하여 다양한 화면 크기에서 늘어나지 않도록 합니다.
      1. BlockUIAspectRatioConstraint를 삽입하여 레이블과 그 자식 UI 요소의 종횡비가 플레이어의 화면 크기와 관계없이 동일하게 유지되도록 합니다.
      2. 새 제약 조건을 선택한 후, 속성 창에서 AspectRatio13.78로 설정합니다.
  4. 플레이어 초상화를 위한 박스를 생성합니다.

    1. PlayerDisplayImageLabel을 삽입합니다.

    2. 새 레이블을 선택한 후, 속성 창에서,

      1. 이미지(Image) 속성에서 자리 표시자 자산 ID를 제거합니다. 7단계의 스크립트가 프로그래밍 방식으로 플레이어의 초상화를 이미지 레이블에 삽입합니다.
      2. AnchorPoint0, 1로 설정하여 레이블의 원점을 왼쪽 아래에 설정합니다 (레이블의 왼쪽에서 오른쪽으로 0%, 위에서 아래로 100%).
      3. BackgroundColor30, 0, 0으로 설정하여 레이블의 배경 색상을 검정색으로 설정합니다.
      4. **배경 투명도(BackgroundTransparency)**를 0.3으로 설정하여 레이블의 투명도를 30% 감소시키고, 경험 내 모든 검정색 UI 요소와 일치시킵니다.
      5. 이름PlayerPortrait로 설정합니다.
      6. **위치(Position)**를 {0.11, 0},{1, 0}로 설정하여 레이블을 다각형 모양의 왼쪽에 배치합니다.
      7. **크기(Size)**를 {0.23, 0},{1, 0}로 설정하여 레이블을 작게 만듭니다.
      8. **이미지 투명도(ImageTransparency)**를 0.15로 설정하여 레이블을 약간 투명하게 만듭니다.
      9. ScaleTypeFit으로 설정하여 이미지가 컨테이너 내에 맞도록 하여 다양한 화면 크기에서 늘어나지 않도록 합니다.
      1. PlayerPortraitUIAspectRatioConstraint를 삽입하여 레이블과 그 자식 UI 요소의 종횡비가 플레이어의 화면 크기와 관계없이 동일하게 유지되도록 합니다.
      2. PlayerPortraitUICorner를 삽입한 다음, 속성 창에서 CornerRadius0.05, 0으로 설정하여 모서리를 약간 둥글게 만듭니다.
  5. 플레이어 이름을 위한 텍스트 레이블을 생성합니다.

    1. PlayerDisplayTextLabel 객체를 삽입합니다.

    2. 새 레이블을 선택한 후, 속성 창에서,

      1. AnchorPoint0, 0.5로 설정하여 새로운 버튼의 원점을 왼쪽 가운데에 설정합니다 (버튼의 왼쪽에서 오른쪽으로 0%, 위에서 아래로 50%).
      2. **배경 투명도(BackgroundTransparency)**를 1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
      3. 이름PlayerNameTextLabel로 설정합니다.
      4. **위치(Position)**를 {0.35, 0},{0.72, 0}로 설정하여 레이블을 컨테이너의 오른쪽에 배치합니다 (부모 레이블의 왼쪽에서 오른쪽으로 35%, 위에서 아래로 72%).
      5. **크기(Size)**를 {0.52, 0},{0.3, 0}로 설정하여 텍스트가 다각형 모양의 대부분을 차지하게 합니다 (부모 프레임의 수평으로 52%와 수직으로 30%).
      6. FontFaceMontserrat로 설정하여 미래적 미학에 맞춥니다.
      7. WeightBold로 설정하여 글꼴을 두껍게 합니다.
      8. 텍스트(Text) 속성 내 자리 표시자 텍스트를 제거합니다. 7단계의 스크립트가 프로그래밍 방식으로 플레이어 이름을 텍스트 레이블에 삽입합니다.
      9. TextScaled를 활성화합니다.
      10. TextXAlignmentLeft로 설정합니다.
  6. 플레이어 초상화 왼쪽에 표시되는 팀 아이콘 및 색상을 생성합니다.

    1. PlayerDisplay폴더를 삽입한 다음 이름을 TeamIcons로 변경합니다.

    2. 녹색 팀 아이콘 및 색상을 만듭니다.

      1. TeamIconsImageLabel을 삽입합니다.
      2. 새 레이블을 선택한 후, 속성 창에서,
        1. AnchorPoint0, 1로 설정하여 레이블의 원점을 왼쪽 아래에 설정합니다 (레이블의 왼쪽에서 오른쪽으로 0%, 위에서 아래로 100%).
        2. BackgroundColor388, 218, 171로 설정하여 레이블의 배경 색상을 민트 그린으로 설정합니다.
        3. 이름TeamAIcon으로 설정합니다.
        4. **위치(Position)**를 {0, 0},{1, 0}로 설정하여 레이블을 프레임 왼쪽에 배치합니다.
        5. **크기(Size)**를 {0.135, 0},{0.58, 0}로 설정하여 레이블을 플레이어 초상화 왼쪽으로 작게 만듭니다.
        6. **이미지 투명도(ImageTransparency)**를 1로 설정하여 레이블을 투명하게 만듭니다.
      1. 이 레이블이 녹색 팀을 위한 것임을 추적하기 위해 사용자 정의 속성을 설정합니다. 이 단계는 7단계의 스크립트에 매우 중요합니다.
        1. 속성 창에서 속성 섹션으로 이동한 후 플러스 아이콘을 클릭합니다. 팝업 대화 상자가 표시됩니다.
        2. 이름 필드에 teamColor를 입력합니다.
        3. 유형 드롭다운 메뉴에서 BrickColor를 선택합니다.
        4. 저장 버튼을 클릭합니다.
        5. 새로운 teamColor 속성을 Mint로 설정합니다.
      2. TeamAIconUIAspectRatioConstraint를 삽입하여 레이블과 자식 UI 요소의 종횡비가 플레이어의 화면 크기와 관계없이 동일하게 유지되도록 합니다.
      3. 아이콘을 생성합니다.
        1. TeamAIconImageLabel을 삽입합니다.
        2. 새 레이블을 선택한 후, 속성 창에서,
          1. **이미지(Image)**를 rbxassetid://14309678670로 설정하여 녹색 팀 아이콘을 표시합니다.
          2. AnchorPoint0.5, 0.5로 설정하여 레이블의 원점을 가운데에 설정합니다 (레이블의 왼쪽에서 오른쪽으로 50%, 위에서 아래로 50%).
          3. **배경 투명도(BackgroundTransparency)**를 1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
          4. 이름Icon으로 설정합니다.
          5. **위치(Position)**를 {0.5, 0},{0.5, 0}로 설정하여 레이블을 부모 레이블의 가운데에 배치합니다.
          6. **크기(Size)**를 {0.7, 0},{0.6, 0}로 설정하여 레이블을 작게 만듭니다.
          7. ScaleTypeFit으로 설정하여 이미지가 컨테이너 내에 맞도록 하여 다양한 화면 크기에서 늘어나지 않도록 합니다.
    3. 분홍색 팀 아이콘 및 색상을 생성합니다.

      1. TeamAIcon 및 그 자식들을 복제합니다.
      2. 복제된 TeamAIcon을 선택한 후, 속성 창에서,
        1. BackgroundColor3255, 170, 255로 설정하여 레이블의 배경 색상을 카네이션 분홍색으로 설정합니다.
        2. 이름TeamBIcon으로 설정합니다.
        3. teamColor 속성을 Carnation Pink로 설정합니다.
        4. TeamBIconIcon 자식 객체를 선택한 후, 속성 창에서 이미지rbxassetid://14309678549로 설정하여 분홍색 팀 아이콘을 표시합니다.
  7. 샘플 레이저 태그 장소 파일 내에서 다음 ReplicatedStorage 스크립트를 참조하여 플레이어가 라운드에ACTIVE할 때 적절한 팀 색상 및 아이콘과 함께 플레이어 표시기를 프로그래밍 방식으로 표시합니다.

다음 스크립트는 startSyncingTeamColor, setPlayerNamesetPlayerPortrait를 포함하여 주요 Heads Up Display (HUD)를 설정하기 위해 함께 작동하는 모듈 스크립트 집합을 필요로 합니다. 플레이어가 라운드에 참여하고 블래스터를 선택하면, 이 스크립트는 모든 HUD UI 요소가 플레이어의 상태, 장치 및 팀 상태에 적절하게 표시되도록 합니다.


local Players = game:GetService("Players")
local setPlayerPortrait = require(script.setPlayerPortrait)
local setPlayerName = require(script.setPlayerName)
local startSyncingTeamColor = require(script.startSyncingTeamColor)
local setObjective = require(script.setObjective)
local setupTouchButtonAsync = require(script.setupTouchButtonAsync)
local startSyncingTeamPoints = require(script.startSyncingTeamPoints)
local disableMouseWhileGuiEnabled = require(script.disableMouseWhileGuiEnabled)
local setupHitmarker = require(script.setupHitmarker)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("HUDGui")
setPlayerPortrait(gui)
setPlayerName(gui)
startSyncingTeamColor(gui)
setObjective(gui)
startSyncingTeamPoints(gui)
disableMouseWhileGuiEnabled(gui)
setupHitmarker(gui)
setupTouchButtonAsync(gui)

포스 필드 화면

포스 필드 화면은 UI 요소로, 플레이어가 라운드에 참여하거나 재참여하는 동안 적 팀의 공격으로부터 안전하다는 것을 알려줍니다. 아트 스타일 선택에서 아이콘에 대한 미적 지침을 따르면서, 샘플 레이저 태그 경험에서는 포스 필드를 상징하는 반투명 육각형 패턴을 사용합니다. 이 디자인 결정은 경험 내 모든 UI에 대한 전반적인 미래적 아트 스타일을 강화할 뿐만 아니라, 플레이어의 상태를 텍스트나 추가 안내 없이 전달합니다.

샘플 레이저 태그 경험 내에서 포스 필드 화면을 정확하게 재현하려면:

  1. ForceFieldGui ScreenGui 객체에 ImageLabel을 삽입합니다.

    1. 탐색기 창에서 StarterGui 서비스로 이동합니다.

    2. 해당 자식 ForceFieldGui 객체 위에 마우스를 올린 다음 아이콘을 클릭합니다. 컨텍스트 메뉴가 표시됩니다.

    3. 컨텍스트 메뉴에서 ImageLabel을 삽입합니다.

  2. 새 레이블을 선택한 후, 속성 창에서,

    1. **이미지(Image)**를 rbxassetid://14462567888로 설정합니다.

    2. **배경 투명도(BackgroundTransparency)**를 0.8로 설정하여 포스 필드를 반투명하게 만듭니다.

    3. **크기(Size)**를 {1, 0},{1, 0}으로 설정하여 이미지를 전체 화면에 채웁니다 (부모 ScreenGui의 100% 수평 및 100% 수직).

    4. ScaleTypeTile로 설정하여 육각형이 전체 화면에 타일링되도록 합니다.

    5. **타일 크기(TileSize)**를 {0, 104},{0, 180}으로 설정합니다.

  3. 레이블에 UIGradient 객체를 삽입합니다.

  4. 새 그라디언트 객체를 선택한 후, 속성 창에서,

    1. 색상 시퀀스를 파란색에서 흰색으로, 그리고 다시 파란색으로 설정합니다.

      1. **색상(Color)**을 120, 192, 250으로 설정하여 모든 육각형에 연한 파란색 음영을 적용합니다.

      2. 색상(Color) 속성을 클릭한 후, 버튼을 클릭합니다. 색상 시퀀스 팝업이 표시됩니다.

        색상 시퀀스의 아래 축에 있는 각 삼각형은 이미지의 좌측에서 우측으로 색상 값의 속성을 결정하는 키포인트입니다.

      3. 색상 시퀀스를 끌어 시간(Time) 값이 0.05에 도달할 때까지 드래그한 후, 색상(Color) 옆의 작은 정사각형을 클릭하여 색상(Color) 팝업 창을 엽니다.

      4. 밝은 흰색을 선택한 다음, 팝업 창을 닫습니다.

      5. 색상 시퀀스를 끌어 시간(Time) 값이 0.95에 도달할 때까지 드래그한 후, 다시 색상(Color) 팝업 창을 열고, 이전과 동일한 하얀색을 선택합니다.

    2. **회전(Rotation)**을 225로 설정하여 색상 시퀀스의 파란색 부분이 좌측 상단 및 우측 하단 모서리에 표시되도록 합니다.

    3. 포스 필드가 깜빡이도록 보이도록 하려면, **투명도(Transparency)**에 숫자 시퀀스를 설정합니다.

      1. 투명도(Transparency) 속성을 클릭한 후, 버튼을 클릭합니다. 숫자 시퀀스 팝업이 표시됩니다. 시퀀스의 시작과 끝에 있는 각 사각형은 이미지의 좌측에서 우측으로 속성의 투명도 값을 결정하는 키포인트입니다.

      2. 숫자 시퀀스를 따라 다음 시간 및 값 속성을 설정합니다:

      • 시간(Time) = 0, 값(Value) = 0.25
      • 시간(Time) = .101, 값(Value) = 0.875
      • 시간(Time) = .183, 값(Value) = 0
      • 시간(Time) = .3, 값(Value) = 1
      • 시간(Time) = .7, 값(Value) = 1
      • 시간(Time) = 1, 값(Value) = 0.9
  5. 2단계에서 ImageLabel을 복제합니다.

  6. 복제된 레이블 내의 UIGradient 객체를 선택한 후, 속성 창에서,

    1. **회전(Rotation)**을 -45로 설정하여 이미지를 반사하여 Y축을 따라 거의 서로를 반사합니다.

    2. 투명도를 수정하여 섬광 효과가 더 자연스럽게 보이도록 합니다.

      1. 투명도 속성을 클릭한 후 버튼을 클릭합니다. 숫자 시퀀스 팝업이 표시됩니다.
      2. 세 번째 키프레임을 선택한 다음 삭제 버튼을 클릭합니다.
  7. 샘플 레이저 태그 장소 파일 내의 ReplicatedStorage 스크립트를 참조하여 플레이어가 라운드에 참여하거나 다시 참여하는 동안 강체 화면을 프로그래밍 방식으로 표시합니다.

다음 ReplicatedStorage.ForceFieldClientVisuals 클라이언트 스크립트는 기본 ForceField 비주얼을 StarterGui.ForceFieldGui로 대체합니다. 플레이어가 경험에 로드되고 0보다 큰 Duration 속성이 있는 SpawnLocation에서 스폰할 때 각 경험에서 기본 동작은 플레이어의 아바타에 보호 청색 구체를 제공하여 순간적으로 체력을 잃지 않도록 합니다.

이 스크립트는 ForceField가 캐릭터에 추가될 때를 듣기 시작하고, 기본 1인칭 강체 비주얼을 비활성화한 후 ForceFieldGui ScreenGui 객체를 활성화합니다. 이 작업은 플레이어가 다른 플레이어가 다시 스폰하는 모습을 볼 때 3인칭 비주얼에는 영향을 미치지 않습니다.

First-person force field visuals include a futuristic hexagonal grid on the perimeter of the screen.
1인칭 강체 비주얼
Third-person force field visuals include a blue sparkling orb around the player spawning into the experience.
3인칭 강체 비주얼

local Players = game:GetService("Players")
local localPlayer = Players.LocalPlayer
local function onCharacterAddedAsync(character: Model)
local forceField = character:WaitForChild("ForceField", 3)
if not forceField then
-- 플레이어가 강체가 비활성화된 스폰 포인트에 스폰된 경우
return
end
forceField.Visible = false
localPlayer.PlayerGui:WaitForChild("ForceFieldGui").Enabled = true
forceField.Destroying:Wait()
localPlayer.PlayerGui.ForceFieldGui.Enabled = false
end
if localPlayer.Character then
onCharacterAddedAsync(localPlayer.Character)
end
localPlayer.CharacterAdded:Connect(onCharacterAddedAsync)

리스폰 화면

리스폰 화면은 플레이어가 태그된 상태임을 알리고 서버가 그들을 스폰 지역으로 리스폰하는 중임을 알리기 위해 뷰포트를 어둡게 하는 UI 요소입니다. 이 UI 요소는 플레이어가 태그된 상황을 처리하고 활성 라운드에 다시 참여하기 전에 다음 행동을 전략적으로 구상할 시간을 제공합니다.

샘플 레이저 태그 경험에서 사용자 정의 리스폰 동작에 대한 자세한 내용은 Gameplay Scripting 커리큘럼의 리스폰 캐릭터를 참조하십시오.

샘플 레이저 태그 경험 내에서 리스폰 화면을 정확하게 재현하려면:

  1. 중앙 정보 배너를 생성합니다.

    1. OutStateGui ScreenGui 객체에 ImageLabel을 삽입합니다.

      1. Explorer 창에서 StarterGui 서비스를 탐색합니다.

      2. 자식 OutStateGui 객체 위에 마우스를 올리고 아이콘을 클릭합니다. 컨텍스트 메뉴가 표시됩니다.

      3. 컨텍스트 메뉴에서 ImageLabel을 삽입합니다.

    2. 새 레이블을 선택하고 속성 창에서,

      1. AnchorPoint0.5, 0.5로 설정하여 레이블의 중앙에 원점을 설정합니다 (레이블의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).

      2. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.

      3. Position{0.5, 0},{0.5, 0}로 설정하여 자식의 중앙에 레이블을 설정합니다 (부모 ScreenGui의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).

      4. Size{0.48, 0},{0.06, 0}로 설정하여 레이블을 넓힙니다 (부모 ScreenGui의 48% 가로, 6% 세로).

      5. NameBlock으로 설정합니다.

      6. Imagerbxassetid://14304827265로 설정하여 이미지를 사다리꼴로 만듭니다.

      7. ImageColor0,0,0으로 설정하여 사다리꼴을 검정색으로 만듭니다.

      8. ImageTransparency0.3으로 설정하여 레이블의 불투명도를 30% 줄이고 경험 내 모든 검정색 UI 요소와 일치시킵니다.

    3. BlockUIAspectRatioConstraint를 삽입하여 레이블과 자식 UI 요소의 종횡비가 플레이어의 화면 크기와 상관없이 동일하게 유지되도록 합니다.

    4. 새 제약 조건을 선택한 후 속성 창에서 AspectRatio13.78로 설정합니다.

    5. Block 안에 정보 텍스트용 TextLabel을 삽입합니다.

    6. 새 레이블을 선택한 후 속성 창에서,

      1. AnchorPoint0.5, 0.5로 설정하여 레이블의 중앙에 원점을 설정합니다 (레이블의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).

      2. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.

      3. Position{0.5, 0},{0.5, 0}로 설정하여 자식의 중앙에 레이블을 설정합니다 (부모 레이블의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).

      4. Size{.85, 0},{0.55, 0}로 설정하여 텍스트가 사다리꼴 영역의 대부분을 차지할 수 있도록 합니다 (부모 레이블의 85% 가로, 55% 세로).

      5. NameBodyTextLabel로 설정합니다.

      6. FontFaceMontserrat로 설정하여 미래적인 미감을 맞춥니다.

      7. WeightBold로 설정하여 글꼴을 두껍게 만듭니다.

      8. Text를 **리스폰 중...**으로 설정합니다.

      9. TextColor3255, 255, 255로 설정하여 텍스트를 흰색으로 만듭니다.

      10. TextScaled를 활성화합니다.

  2. 헤더를 생성합니다.

    1. BlockImageLabel을 삽입합니다.

    2. 새 레이블을 선택한 후 속성 창에서,

      1. AnchorPoint0.5, 1로 설정하여 레이블의 중앙 하단에 원점을 설정합니다 (레이블의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 100%).

      2. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.

      3. Position{0.5, 0},{0, 0}로 설정하여 부모 레이블의 중앙 상단에 레이블을 설정합니다 (부모 레이블의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 0%).

      4. Size{0.46, 0},{0.56, 0}로 설정하여 레이블을 넓힙니다 (부모 레이블의 46% 가로, 56% 세로).

      5. NameHeader로 설정합니다.

      6. Imagerbxassetid://14304826985로 설정하여 이미지를 다방향 페이드로 만듭니다.

      7. ImageColor245, 46, 46으로 설정하여 페이드 색을 빨간색으로 지정하여 플레이어가 라운드에서 태그된 동안 일시적으로 비활성화를 알립니다.

    3. Header에 정보 텍스트용 TextLabel을 삽입합니다.

    4. 새 레이블을 선택한 후 속성 창에서,

      1. AnchorPoint0.5, 0.5로 설정하여 레이블의 중앙에 원점을 설정합니다 (레이블의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).

      2. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.

      3. Position{0.5, 0},{0.5, 0}로 설정하여 자식의 중앙에 레이블을 설정합니다 (부모 레이블의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).

      4. Size{.85, 0},{0.55, 0}로 설정하여 텍스트가 페이드 영역의 대부분을 차지할 수 있도록 합니다 (부모 레이블의 85% 가로, 55% 세로).

      5. NameHeaderTextLabel로 설정합니다.

      6. FontFaceMontserrat로 설정하여 미래적인 미감을 맞춥니다.

      7. WeightBlack로 설정하여 글꼴을 두껍게 만듭니다.

      8. Text를 **태그됨 - 나가셨습니다!**로 설정합니다.

      9. TextColor3255, 255, 255로 설정하여 텍스트를 흰색으로 만듭니다.

      10. TextScaled를 활성화합니다.

  3. 화면 가장자리를 둘러싸는 페이드를 생성합니다.

    1. OutStateGuiImageLabel을 삽입합니다.
    2. 새 레이블을 선택한 후 속성 창에서,
      1. AnchorPoint0.5, 0.5로 설정하여 레이블의 중앙에 원점을 설정합니다 (레이블의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).
      2. BackgroundColor30,0,0으로 설정하여 레이블의 배경 색상을 검정색으로 설정합니다.
      3. BackgroundTransparency0.5로 설정하여 레이블의 배경을 반투명하게 만듭니다.
      4. Position{0.5, 0},{0.5, 0}로 설정하여 컨테이너의 중앙에 레이블을 설정합니다 (부모 ScreenGui의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).
      5. Size{1, 0},{1, 0}로 설정하여 레이블을 전체 화면으로 확장합니다 (부모 ScreenGui의 100% 가로, 100% 세로).
      6. ZIndex-1로 설정하여 다른 UI 요소 뒤에 페이드를 표시할 수 있습니다.
      7. NameHeader로 설정합니다.
      8. Imagerbxassetid://14309518613로 설정하여 이미지를 테두리 페이드로 만듭니다.
      9. ImageTransparency0.1로 설정하여 페이드가 약간 반투명합니다.
  4. 플레이어의 체력이 0에 도달하고 팀의 스폰 지역으로 리스폰되는 동안 리스폰 화면을 프로그래밍적으로 표시하는 샘플 레이저 태그 장소 파일 내의 ReplicatedStorage 스크립트를 참조합니다.

다음 ReplicatedStorage.PlayerStateHandler 클라이언트 스크립트는 playerState 속성에 따라 다양한 유형의 동작을 유발하는 함수를 포함합니다. 모든 이벤트 응답은 플레이어의 제어 활성화 또는 비활성화, 카메라 이동, 어떤 UI 레이어가 보이는지와 같은 유사한 동작을 요구하기 때문에 이 스크립트에 논리적으로 그룹화되어 있습니다.

플레이어의 체력이 0에 도달하면, 그들의 playerStateTaggedOut이 되고, 이는 onTaggedOut() 함수를 트리거합니다. onTaggedOut()는 다음과 같은 동작을 즉시 시작합니다:

  • 플레이어는 아레나에서 움직일 수 없습니다.
  • 플레이어는 카메라를 움직일 수 없습니다.
  • 플레이어는 블래스터를 사용할 수 없습니다.
  • StarterGui.OutStateGui가 독점적으로 활성화됩니다.

플레이어가 리스폰할 때, 그들의 playerStateSelectingBlaster로 바뀌며 이는 onSelectingBlaster() 함수를 트리거합니다. onSelectingBlaster()는 그 다음으로 StarterGui.PickABlasterGui만을 독점적으로 활성화하여 리스폰 화면을 자동으로 비활성화합니다. 이러한 조건에 대한 자세한 내용은 Gameplay Scripting 커리큘럼의 클라이언트 상태 처리를 참조하십시오.


local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local PlayerState = require(ReplicatedStorage.PlayerState)
local PlayerAttribute = require(ReplicatedStorage.PlayerAttribute)
local BlasterState = require(ReplicatedStorage.Blaster.BlasterState)
local togglePlayerMovement = require(script.togglePlayerMovement)
local togglePlayerCamera = require(script.togglePlayerCamera)
local scheduleDestroyForceField = require(ReplicatedStorage.scheduleDestroyForceField)
local localPlayer = Players.LocalPlayer
local playerGui = localPlayer.PlayerGui
local guiLayers = {
playerGui:WaitForChild("HUDGui"),
playerGui:WaitForChild("OutStateGui"),
playerGui:WaitForChild("PickABlasterGui"),
}
-- 주어진 예외를 제외한 모든 UI 레이어 비활성화
local function setGuiExclusivelyEnabled(enabledGui: ScreenGui?)
-- guiLayers에는 독점적으로 설정되어야 할 gui 목록이 포함됩니다.
for _, screenGui in guiLayers do
screenGui.Enabled = screenGui == enabledGui
end
end
local function onSelectingBlaster()
-- 블래스터를 선택하는 동안 플레이어가 둘러볼 수 있도록 카메라를 활성화합니다.
togglePlayerCamera(true)
togglePlayerMovement(false)
setGuiExclusivelyEnabled(playerGui.PickABlasterGui)
-- 블래스터를 선택하는 동안 블래스터를 비활성화합니다.
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
local function onPlaying()
-- 블래스터를 선택한 후 플레이어의 이동을 활성화합니다.
togglePlayerMovement(true)
setGuiExclusivelyEnabled(playerGui.HUDGui)
-- 게임 중에 블래스터를 사용할 수 있도록 활성화합니다.
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Ready)
-- 플레이어가 게임을 시작할 때 강체 파괴 논리를 예약합니다.
scheduleDestroyForceField()
end
local function onTaggedOut()
-- 태그 상태에서 제어를 비활성화합니다.
togglePlayerMovement(false)
togglePlayerCamera(false)
setGuiExclusivelyEnabled(playerGui.OutStateGui)
-- 태그 상태에서 블래스터를 비활성화합니다.
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
local function onInLobby()
-- 로비에 있을 때 제어를 활성화합니다.
togglePlayerMovement(true)
togglePlayerCamera(true)
-- 로비에 있을 때 HUD를 모두 숨깁니다.
setGuiExclusivelyEnabled(nil)
-- 로비에 있을 때 블래스터를 비활성화합니다.
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
local function onPlayerStateChanged(newPlayerState: string)
if newPlayerState == PlayerState.SelectingBlaster then
onSelectingBlaster()
elseif newPlayerState == PlayerState.Playing then
onPlaying()
elseif newPlayerState == PlayerState.TaggedOut then
onTaggedOut()
elseif newPlayerState == PlayerState.InLobby then
onInLobby()
else
warn(`유효하지 않은 플레이어 상태 ({newPlayerState})`)
end
end
-- 초기 플레이어 상태가 설정되어 있는 경우 처리합니다.
local initialPlayerState = localPlayer:GetAttribute(PlayerAttribute.playerState)
onPlayerStateChanged(initialPlayerState)
local function updateFromPlayerState()
onPlayerStateChanged(localPlayer:GetAttribute(PlayerAttribute.playerState))
end
-- 이후 플레이어 상태 업데이트를 처리합니다.
localPlayer:GetAttributeChangedSignal(PlayerAttribute.playerState):Connect(updateFromPlayerState)
-- 리스폰 후에도 변화가 반영되도록 합니다.
localPlayer.CharacterAdded:Connect(updateFromPlayerState)

SurfaceGui 객체 만들기

3D 공간 내에서 각 플레이어에 대해 스크립팅 논리에 반응하는 UI를 표시하기 위해 생성할 수 있는 SurfaceGui 객체를, 표시하려는 부분에 부모로 할당합니다. 이 기술은 UI와 스크립트 논리가 서버와 각 플레이어의 클라이언트에서 모두 사용 가능하다는 것을 보장합니다.

SurfaceGui 객체는 3D 공간 내의 부분 표면에 표시되는 모든 GuiObjects를 포함합니다. 샘플 레이저 태그 경험에는 SurfaceGui 객체의 인스턴스가 하나 포함되어 있습니다: 각 플레이어의 블래스터 위에 표시되는 쿨다운 미터. 이 객체는 각 플레이어의 입력에 반응하여 스크립팅 논리가 필요하며, 재사용할 수 없도록 하는 시각적 피드백을 제공합니다.

SurfaceGui 객체를 생성하려면:

  1. Explorer 창에서 ReplicatedStorage 서비스 위에 마우스를 두고 아이콘을 클릭합니다. 컨텍스트 메뉴가 표시됩니다.
  2. 컨텍스트 메뉴에서 Part 객체를 삽입합니다.
  3. 해당 부품에 ScreenGui 객체를 삽입합니다.
  4. 자식 UI 요소의 컨텍스트에 따라 SurfaceGui의 이름을 변경합니다.
  5. 3D 공간 내의 부분 표면에 표시해야 할 모든 UI 요소에 대해 이 과정을 반복합니다.

쿨다운 미터

쿨다운 미터는 플레이어가 블래스터를 다시 발사할 수 있기까지 기다려야 하는 시간을 알리는 UI 구성 요소입니다. 이 짧은 지연은 플레이어가 클릭하거나 버튼을 누른 속도만큼 빠르게 발사할 수 없도록 하여 레이저 태그 게임 플레이의 비현실성을 방지합니다.

샘플 레이저 태그 경험 내에서 쿨다운 미터를 정확하게 재현하려면:

  1. SurfaceGui 객체를 보유할 부품을 생성합니다.

    1. Explorer 창에서 Workspace에 마우스를 두고 아이콘을 클릭합니다. 컨텍스트 메뉴가 표시됩니다.
    2. 컨텍스트 메뉴에서 블록 부분을 삽입합니다. 이 부분은 진행 중인 각 단계의 변화를 시각화할 임시 위치입니다.
  2. 부품을 플레이어의 캐릭터가 블래스터를 잡고 있을 위치에 위치시키고 방향을 조정한 후 속성 창에서,

    1. Transparency를 1로 설정하여 부품을 완전히 투명하게 만듭니다.

    2. NameCooldownBarPrefab으로 설정합니다.

    3. Size0.169, 0.027, 2.537로 설정하여 부품의 길이를 블래스터의 길이 정도로 조정합니다.

    4. CanCollideCanQuery를 비활성화합니다.

  3. CooldownBarPrefabSurfaceGui를 삽입합니다.

  4. SurfaceGui를 선택한 후 속성 창에서,

    1. FaceTop으로 설정하여 UI가 위쪽을 바라보게 합니다.

    2. LightInfluenceMaxDistance를 0으로 설정합니다.

    3. PixelsPerStud를 200으로 설정합니다.

  5. 검정색 바를 생성합니다.

    1. SurfaceGui 안에 ImageLabel을 삽입합니다.

    2. 새 레이블을 선택한 후 속성 창에서,

      1. 기본 Image 값을 제거합니다.
      2. AnchorPoint0.5, 0.5로 설정하여 레이블의 가운데에 원점을 설정합니다 (레이블의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).
      3. BackgroundColor30,0,0으로 설정하여 레이블의 배경색을 검정색으로 설정합니다.
      4. BackgroundTransparency0.4로 설정하여 레이블의 배경을 반투명하게 만듭니다.
      5. Position{0.5, 0},{0.5, 0}으로 설정하여 자식의 중앙에 레이블을 설정합니다 (부모 SurfaceGui의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).
      6. Size{1, 0},{1, 0}으로 설정하여 레이블을 전체 부품으로 넓힙니다 (부모 SurfaceGui의 100% 가로, 100% 세로).
      7. NameContainer로 설정합니다.
  6. 컨테이너 모서리를 둥글게 만듭니다.

    1. Container 안에 UICorner 객체를 삽입합니다.

    2. UICorner를 선택한 후 속성 창에서 CornerRadius0.15, 0로 설정하여 모서리를 약간 둥글게 만듭니다.

  7. 빨간색 바를 생성합니다.

    1. Container 안에 ImageLabel을 삽입합니다.
    2. 새 레이블을 선택한 후 속성 창에서,
      1. 기본 Image 값을 제거합니다.
      2. AnchorPoint1, 0.5로 설정하여 레이블의 오른쪽 중간에 원점을 설정합니다 (레이블의 왼쪽에서 오른쪽으로 100%, 위쪽에서 아래쪽으로 50%).
      3. BackgroundColor3172, 13, 13으로 설정하여 레이블의 배경색을 어두운 빨간색으로 설정합니다.
      4. BackgroundTransparency0.2로 설정하여 레이블의 배경을 약간 반투명하게 만듭니다.
      5. NameBar로 설정합니다.
      6. Position{1, 0},{0.5, 0}으로 설정하여 레이블을 자식의 오른쪽 가운데에 설정합니다 (부모 레이블의 왼쪽에서 오른쪽으로 100%, 위쪽에서 아래쪽으로 50%).
      7. Size{0, 0},{1, 0}으로 설정하여 레이블을 부모 레이블의 위로 길게 만듭니다 (부모 레이블의 0% 가로, 100% 세로). 이 단계는 스크립트의 Tweening 동작에도 도움이 됩니다.
  8. 레이블의 모서리를 둥글게 만듭니다.

    1. Bar 안에 UICorner 객체를 삽입합니다.
    2. UICorner를 선택한 후 속성 창에서 CornerRadius0.15, 0로 설정하여 모서리를 약간 둥글게 만듭니다.
  9. CooldownBarPrefabReplicatedStorage로 이동합니다.

    1. UI 객체를 조직하기 위한 폴더 구조를 만듭니다. 샘플에서는 Instances 폴더 안에 Guis 폴더를 사용합니다.

    2. CooldownBarPrefabGuis로 이동합니다.

  10. 샘플 레이저 태그 장소 파일 내의 ReplicatedStorage 스크립트를 참조하여 플레이어의 블래스터에 쿨다운 미터를 프로그래밍 방식으로 부착한 후, 플레이어가 블래스터를 발사하면 빨간색 바를 애니메이션합니다.

다음 ReplicatedStorage.FirstPersonBlasterVisuals 클라이언트 스크립트는 플레이어의 1인칭 블래스터에 대한 모든 비주얼 논리를 처리합니다. 이는 블래스터 비주얼을 보다 사실감 있게 설정하기 위해 함께 작동하는 모듈 스크립트 세트를 필요로 합니다. 여기에는 FirstPersonBlasterVisuals.addCooldownBarFirstPersonBlasterVisuals.runCooldownBarEffect가 포함됩니다.


local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local RunService = game:GetService("RunService")
local BlastData = require(ReplicatedStorage.Blaster.BlastData)
local PlayerAttribute = require(ReplicatedStorage.PlayerAttribute)
local PlayerState = require(ReplicatedStorage.PlayerState)
local getBlasterConfig = require(ReplicatedStorage.Blaster.getBlasterConfig)
local runBlastVisuals = require(script.runBlastVisuals)
local setupAnimations = require(script.setupAnimations)
local addCooldownBar = require(script.addCooldownBar)
local runCooldownBarEffect = require(script.runCooldownBarEffect)
local laserBlastedBindableEvent = ReplicatedStorage.Instances.LaserBlastedBindableEvent
local RIG_OFFSET_FROM_CAMERA = CFrame.new(2, -2, -3) * CFrame.Angles(math.rad(0.25), math.rad(95.25), 0)
local localPlayer = Players.LocalPlayer
local currentCamera = Workspace.CurrentCamera
local rigModel = nil
local cooldownBar = nil
local animations = {}
local function addFirstPersonVisuals()
local blasterConfig = getBlasterConfig()
-- 1인칭 다리 추가
rigModel = blasterConfig.RigModel:Clone()
rigModel.Parent = Workspace
-- 쿨다운 바 추가
cooldownBar = addCooldownBar(rigModel.PrimaryPart.CooldownBarAttachment)
animations = setupAnimations(blasterConfig, rigModel)
end
local function removeFirstPersonVisuals()
for _, animation in animations do
animation:Stop()
animation:Destroy()
animation = nil
end
if rigModel then
-- 쿨다운 바도 파괴하면서 강체 모델을 파괴합니다.
rigModel:Destroy()
rigModel = nil
end
end
-- 발사가 일어날 때 1인칭 비주얼 효과 실행
laserBlastedBindableEvent.Event:Connect(function(blastData: BlastData.Type)
runBlastVisuals(rigModel.PrimaryPart.TipAttachment, blastData, animations.blastAnimation)
runCooldownBarEffect(cooldownBar)
end)
-- 카메라가 존재하는 경우 강체를 카메라에 바인딩합니다.
RunService.RenderStepped:Connect(function()
if rigModel then
-- 카메라의 위치와 RIG_OFFSET_FROM_CAMERA에 상대적으로 강체의 CFrame을 업데이트합니다.
rigModel:PivotTo(currentCamera.CFrame * RIG_OFFSET_FROM_CAMERA)
end
end)
-- 게임 중 블래스터 유형이 변경될 때 비주얼 변경을 처리합니다.
localPlayer:GetAttributeChangedSignal(PlayerAttribute.blasterType):Connect(function()
local playerState = localPlayer:GetAttribute(PlayerAttribute.playerState)
if playerState == PlayerState.Playing then
removeFirstPersonVisuals()
addFirstPersonVisuals()
end
end)
-- 플레이어 상태가 변경될 때 비주얼 변경을 처리합니다.
localPlayer:GetAttributeChangedSignal(PlayerAttribute.playerState):Connect(function()
local newPlayerState = localPlayer:GetAttribute(PlayerAttribute.playerState)
-- 플레이어가 블래스터를 선택하거나 로비에 있을 때 비주얼을 제거합니다.
if newPlayerState == PlayerState.SelectingBlaster or newPlayerState == PlayerState.InLobby then
removeFirstPersonVisuals()
-- 플레이어가 블래스터 선택을 끝내면 비주얼을 다시 추가합니다.
elseif newPlayerState == PlayerState.Playing then
addFirstPersonVisuals()
end
end)

BillboardGui 객체 만들기

3D 공간 내에 UI 요소를 표시하여 스크립팅 논리에 반응하고 각 플레이어의 카메라를 항상 향하게 하고 싶다면 (예: 플레이어 이름 또는 맵 마커) BillboardGui 객체를 BasePart 또는 3D 공간에 존재하는 Attachment의 자식으로 생성할 수 있습니다.

샘플 레이저 태그 경험에는 ReplicatedStorage 서비스 내에 두 개의 별도의 BillboardGui 객체가 포함되어 있습니다:

  • OtherPlayerIndicatorGuiPrefab - 각 플레이어의 머리 위에 분홍색 또는 녹색 원을 표시하여 라운드에서 활동 중임을 알립니다.
  • TaggedOutIndicatorGuiPrefab - 다른 플레이어가 라운드에서 태그되지 않았음을 표시합니다.

BillboardGui 객체를 생성한 후에는 각 용기의 목적에 따라 자식 GuiObjects를 만들고 사용자 정의할 수 있습니다. 이와 관련하여 다음 섹션에서, 샘플 레이저 태그 경험 내 두 가지 표시기 유형을 구현하는 방법을 배웁니다. 프로세스의 어떤 부분도 본인의 경험의 사양에 맞게 조정할 수 있습니다.

BillboardGui 객체를 생성하려면:

  1. Explorer 창에서 BasePart 또는 Attachment 위에 마우스를 두고 아이콘을 클릭합니다. 컨텍스트 메뉴가 표시됩니다.
  2. 컨텍스트 메뉴에서 BillboardGui 객체를 삽입합니다.
  3. 자식 UI 요소의 맥락에 따라 BillboardGui의 이름을 변경합니다.
  4. 플레이어 머리 위에 표시해야 할 모든 UI 요소에 대해 이 과정을 반복합니다.

팀 표시기

팀 표시기는 라운드에서 다른 플레이어가 속하는 팀을 플레이어에게 알리는 UI 요소로, 플레이어가 자신의 동료와 적 팀원을 쉽게 구분할 수 있도록 도와줍니다. 이 정보는 1인칭 슈팅 게임 플레이에서 매우 중요합니다. 적의 팀이 아닌 플레이어를 태그한 후 각 플레이어는 진안 전투 지역에서 쉽게 다음 목표를 찾기 위해 재빠른 전략적 결정을 내려야 합니다.

샘플 레이저 태그 경험의 팀 표시기를 정확하게 재현하려면:

  1. 임시 강체에 BillboardGui 객체를 삽입합니다.

    1. 툴바의 또는 아바타 탭에서 Character를 클릭합니다.

    2. 사용 가능한 옵션 중에서 선택합니다. 샘플에서는 R15 강체 유형, 여성 신체 형태 및 Rthro 아바타를 사용합니다. 이 강체는 3D 뷰포트와 Explorer 창 모두에 Rig라는 이름으로 표시됩니다.

    3. Explorer 창에서 강체의 자식 Head 메쉬로 이동하여 아이콘을 클릭합니다. 컨텍스트 메뉴가 표시됩니다.

    4. 컨텍스트 메뉴에서 BillboardGui를 삽입합니다.

  2. BillboardGui를 선택한 후 속성 창에서,

    1. LightInfluence0으로 설정하여 환경 조명이 표시기의 색상에 영향을 미치지 않도록 합니다.

    2. NameOtherPlayerIndicatorPrefab으로 설정합니다.

    3. Size{0, 10},{0, 10}으로 설정하여 레이블을 상당히 작게 만듭니다.

    4. StudsOffsetWorldSpace0, 4, 0으로 설정하여 강체의 머리 위로 위치시킵니다.

  3. OtherPlayerIndicatorPrefab 안에 Frame 객체를 삽입합니다.

  4. 새 프레임을 선택한 후 속성 창에서,

    1. AnchorPoint0.5, 0.5로 설정하여 프레임의 중앙에 원점을 설정합니다 (프레임의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).

    2. BackgroundColor3255, 3, 0으로 설정하여 프레임의 배경색을 빨간색으로 설정합니다 (플레이스홀더 색상).

    3. Position{0.5, 0},{0.5, 0}으로 설정하여 프레임을 자식의 중앙에 설정합니다 (부모 BillboardGui의 중앙).

    4. Size{1, -2},{1, -2}로 설정하여 프레임을 BillboardGui의 표면 영역에 맞춥니다.

  5. Frame 안에 UICorner 객체를 삽입하여 모서리를 둥글게 만듭니다.

  6. Frame 안에 UIStroke 객체를 삽입하여 표시기의 원 테두리를 만듭니다.

  7. OtherPlayerIndicatorPrefabReplicatedStorage로 이동합니다.

  8. 샘플 레이저 태그 1A 장소 파일 내의 ReplicatedStorage 스크립트를 참조하여 활성 라운드의 각 플레이어에 대한 팀 표시기를 프로그래밍 방식으로 표시합니다. 적 팀은 포함하지 않습니다.

다음 ReplicatedStorage.OtherPlayerIndicatorGuiSetup 스크립트는 플레이어가 활성 라운드의 아레나로 스폰될 때 실행됩니다. 이 스크립트는 라운드에 참여하는 각 플레이어 캐릭터의 Head 객체를 찾고, 팀 표시기를 클론 및 추가하는 addIndicatorToCharacter() 함수를 호출하여 팀 표시기를 부착합니다. 다른 플레이어가 같은 팀일 경우, 팀 표시기는 3D 공간의 객체 뒤에 숨어 있지 않더라도 항상 표시됩니다. 다른 플레이어가 적 팀일 경우, 팀 표시기는 그들이 가려지지 않도록 3D 공간에 객체가 없다면 표시됩니다.


local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local localPlayer = Players.LocalPlayer
local otherPlayerIndicatorPrefab = ReplicatedStorage.Instances.Guis.OtherPlayerIndicatorPrefab
local characterSpawnConnectionsByPlayer: { [Player]: RBXScriptConnection } = {}
local playerAddedConnection: RBXScriptConnection?
local function removeIndicatorFromPlayer(player: Player)
if not player.Character then
return
end
local head = player.Character:WaitForChild("Head", 3)
if not head then
return
end
local gui = head:FindFirstChild(otherPlayerIndicatorPrefab.Name)
if gui then
gui:Destroy()
end
end
local function addIndicatorToCharacter(otherCharacter: Model?)
local otherPlayer = Players:GetPlayerFromCharacter(otherCharacter)
if not otherPlayer then
return
end
task.spawn(function()
local otherHead = otherCharacter:WaitForChild("Head", 3)
if not otherHead then
return
end
-- 라운드에 참여하는 플레이어에게만 표시기를 추가합니다.
if not otherPlayer.Team then
return
end
-- 중복 표시기를 방지합니다. 표시기가 존재하지 않으면 새로 생성합니다.
local gui = otherHead:FindFirstChild(otherPlayerIndicatorPrefab.Name)
if not gui then
gui = otherPlayerIndicatorPrefab:Clone()
gui.Frame.BackgroundColor3 = otherPlayer.TeamColor.Color
gui.Parent = otherHead
end
-- 팀 표시기는 항상 플레이어가 우호적일 경우에만 위에 표시됩니다.
local isFriendly = otherPlayer.Team == localPlayer.Team
gui.AlwaysOnTop = isFriendly
end)
end
local function addIndicatorWhenCharacterSpawns(player: Player)
if characterSpawnConnectionsByPlayer[player] then
return
end
local connection = player.CharacterAdded:Connect(addIndicatorToCharacter)
characterSpawnConnectionsByPlayer[player] = connection
end
local function stopSyncingIndicators()
for _, connection in characterSpawnConnectionsByPlayer do
connection:Disconnect()
end
table.clear(characterSpawnConnectionsByPlayer)
if playerAddedConnection then
playerAddedConnection:Disconnect()
playerAddedConnection = nil
end
for _, player in Players:GetPlayers() do
removeIndicatorFromPlayer(player)
end
end
local function addIndicatorToPlayer(player: Player)
if player == localPlayer then
return
end
addIndicatorToCharacter(player.Character)
addIndicatorWhenCharacterSpawns(player)
end
local function startSyncingIndicators()
for _, player in Players:GetPlayers() do
addIndicatorToPlayer(player)
end
if not playerAddedConnection then
playerAddedConnection = Players.PlayerAdded:Connect(addIndicatorToPlayer)
end
end
local function onLocalTeamChanged()
local localTeam = localPlayer.Team
if localTeam then
startSyncingIndicators()
else
stopSyncingIndicators()
end
end
localPlayer:GetPropertyChangedSignal("Team"):Connect(onLocalTeamChanged)
onLocalTeamChanged()

태그된 표시기

태그된 표시기는 다른 플레이어가 라운드에서 더 이상 활동하지 않을 때를 알리는 UI 요소로, 스폰 지역으로 다시 리스폰되고 있음을 알려줍니다. 이 정보는 1인칭 슈팅 게임 플레이에서 매우 중요합니다. 플레이어는 다른 플레이어를 태그한 후 즉시 다음 목표로 이동해야 하며, 같은 장소에 너무 오래 머물러 있는 동안 취약해지지 않도록 해야 합니다.

샘플 레이저 태그 경험 내에서 태그 표시기를 정확하게 재현하려면:

  1. 각 과정의 변경을 시각화할 수 있도록 임시 강체에 BillboardGui 객체를 삽입합니다.

    1. 툴바의 또는 아바타 탭에서 Character를 클릭합니다.

    2. 사용 가능한 옵션 중에서 선택합니다. 샘플에서는 R15 강체 유형, 남성 신체 형태, Rthro 아바타를 사용합니다. 이 강체는 3D 뷰포트와 Explorer 창 모두에 Rig라는 이름으로 표시됩니다.

    3. Explorer 창에서 강체의 자식 Head 메쉬로 이동하여 아이콘을 클릭합니다. 컨텍스트 메뉴가 표시됩니다.

    4. 컨텍스트 메뉴에서 BillboardGui를 삽입합니다.

  2. BillboardGui를 선택한 후 속성 창에서,

    1. LightInfluence0으로 설정하여 환경 조명이 표시기의 색상에 영향을 미치지 않도록 합니다.

    2. NameTaggedOutIndicatorGuiPrefab로 설정합니다.

    3. Size{3, 0},{0.5, 0}으로 설정하여 레이블을 넓힙니다.

    4. StudsOffset0, 3.25, 0으로 설정하여 머리 위로 위치시킵니다.

  3. TaggedOutIndicatorGuiPrefab 안에 ImageLabel 객체를 삽입합니다.

  4. 새 레이블을 선택한 후 속성 창에서,

    1. AnchorPoint0.5, 0.5로 설정하여 레이블의 중앙에 원점을 설정합니다 (레이블의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).
    2. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.
    3. NameFrame으로 설정합니다.
    4. Position{0.5, 0},{0.5, 0}으로 설정하여 레이블을 자식의 중앙에 설정합니다 (부모 BillboardGui의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).
    5. Size{1, 0},{1, 0}으로 설정하여 레이블을 전체 BillboardGui로 확장합니다 (부모 BillboardGui의 100% 가로, 100% 세로).
    6. Imagerbxassetid://14304826985로 설정하여 이미지를 다방향 페이드로 만듭니다.
    7. ImageColor245, 46, 46으로 설정하여 레이블을 붉은색으로 반짝이게 합니다.
  5. Frame 안에 TextLabel 객체를 삽입합니다.

  6. 새 레이블을 선택한 후 속성 창에서,

    1. AnchorPoint0.5, 0.5로 설정하여 레이블의 중앙에 원점을 설정합니다 (레이블의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).

    2. BackgroundTransparency1로 설정하여 레이블의 배경을 완전히 투명하게 만듭니다.

    3. NameBodyTextLabel로 설정합니다.

    4. Position{0.5, 0},{0.5, 0}으로 설정하여 자식의 중앙에 레이블을 설정합니다 (부모 레이블의 왼쪽에서 오른쪽으로 50%, 위쪽에서 아래쪽으로 50%).

    5. Size{0.85, 0},{0.7, 0}로 설정하여 텍스트가 이미지 레이블의 대부분을 차지하도록 합니다 (부모 레이블의 85% 가로, 70% 세로).

    6. FontFaceMontserrat로 설정하여 미래적인 미감을 맞춥니다.

    7. WeightBold로 설정하여 글꼴을 두껍게 만듭니다.

    8. Text태그됨으로 설정합니다.

    9. TextColor3255, 255, 255로 설정하여 텍스트를 흰색으로 만듭니다.

    10. TextScaled를 활성화합니다.

  7. TaggedOutIndicatorGuiPrefabReplicatedStorage로 이동합니다.

  8. 샘플 레이저 태그 1A 장소 파일 내의 ServerScriptService 스크립트를 참조하여 플레이어가 팀의 스폰 지역으로 리스폰되고 있을 때 태그된 표시기를 프로그래밍식으로 표시합니다.

다음 ServerScriptService.SetupHumanoid 서버 스크립트는 플레이어가 경험을 로드하자마자 실행됩니다. 이 스크립트는 플레이어의 캐릭터가 데이터 모델에 추가될 때마다 setupHumanoidAsync가 그들의 Humanoid로 호출되도록 보장합니다.


local Players = game:GetService("Players")
local setupHumanoidAsync = require(script.setupHumanoidAsync)
local function onCharacterAdded(player: Player, character: Model)
local humanoid = character:WaitForChild("Humanoid")
setupHumanoidAsync(player, humanoid)
end
local function onPlayerAdded(player: Player)
-- 플레이어가 이미 캐릭터를 가지고 있다면 onCharacterAdded 호출
if player.Character then
onCharacterAdded(player, player.Character)
end
-- 이 플레이어의 모든 앞으로의 캐릭터 스폰에 대해 onCharacterAdded 호출
player.CharacterAdded:Connect(function(character: Model)
onCharacterAdded(player, character)
end)
end
-- 게임에 이미 있는 모든 플레이어에 대해 onPlayerAdded 호출
for _, player in Players:GetPlayers() do
onPlayerAdded(player)
end
-- 모든 미래의 플레이어에 대해 onPlayerAdded 호출
Players.PlayerAdded:Connect(onPlayerAdded)

사용자 인터페이스 디자인 커리큘럼을 완료하신 것을 축하합니다! 이제 아트 스타일을 만들고, 레이아웃을 와이어프레임하며, 디자인을 스튜디오에서 처음부터 끝까지 구현한 경험이 있으므로, 새 UI와 기능으로 프로젝트를 확장하거나 Gameplay Scripting Curriculum와 같은 추가 튜토리얼 커리큘럼을 따라 할 수 있습니다. 이 커리큘럼은 샘플 레이저 태그 경험의 일반적인 조직 및 주요 구현 세부 사항에 대해 배웁니다. 행복한 창작 되세요!

©2026 Roblox Corporation. Roblox 및 Roblox 로고, 'Powering Imagination'은 미국 및 기타 국가 내 당사의 등록 및 미등록 상표입니다.