MSW DefaultPlayer
DefaultPlayer 모델 파일 직접 조회/수정, 컴포넌트 관리, 이동/물리/HP/카메라 설정.
코스튬/아바타 장비는 msw-costume 스킬을 참조. 코스튬은 DefaultPlayer뿐 아니라 모든 엔티티에 적용 가능하므로 별도 스킬로 분리되어 있다.DefaultPlayer 개요
DefaultPlayer란?
메이플스토리 월드 메이커(Maker)의 워크스페이스에 기본 제공되는 플레이어 캐릭터 모델이다.
- 모든 유저가 월드에 접속하면 이 모델을 기반으로 플레이어 엔티티가 생성된다.
DefaultUserEnterLeaveLogic의PlayerUri프로퍼티에 사용할 모델 ID가 지정된다.
파일 위치 및 구조
DefaultPlayer는 두 개의.model 파일로 구성된다:
| 파일 | 경로 | 역할 |
|---|---|---|
| Player.model | ./Global/Player.model | 베이스 모델. Components 목록과 Properties 링크를 정의 |
| DefaultPlayer.model | ./Global/DefaultPlayer.model | Player를 상속(BaseModelId: "player"). Values를 오버라이드 |
중요: 두 파일 모두./Global/폴더에 위치한다. 커스텀 스크립트 파일은./RootDesk/MyDesk/에 생성한다.
DefaultPlayer는.model 파일로 직접 편집한다
DefaultPlayer는 ./Global/DefaultPlayer.model 파일을 직접 읽고 수정하여 관리한다.
- 속성값 변경:
DefaultPlayer.model의Values배열에서 해당 항목의Value를 수정 - 컴포넌트 추가/제거:
DefaultPlayer.model의Components배열을 수정 - 베이스 컴포넌트 목록 확인:
Player.model의Components배열 참조
파일 구조 상세
Player.model (베이스)
경로: ./Global/Player.model
EntryKey: model://playerComponents: 플레이어의 기본 컴포넌트 전체 목록 (MOD.Core.* 네이티브 컴포넌트)Properties: 모델 프로퍼티 → 컴포넌트 프로퍼티 링크 정의 (인스펙터에서 편집 가능한 프로퍼티)Values: 비어 있음 (기본값은 엔진이 제공)
DefaultPlayer.model (오버라이드)
경로: ./Global/DefaultPlayer.model
EntryKey: model://defaultplayer
BaseModelId: "player"Components: DefaultPlayer에 추가된 컴포넌트만 (예:script.PlayerHit,script.PlayerAttack)Values: 오버라이드할 설정값 배열
DefaultPlayer 기본 컴포넌트 목록
Player.model로부터 상속되는 네이티브 컴포넌트:
| 컴포넌트 | 역할 |
|---|---|
| TransformComponent | 위치, 회전, 크기 |
| MovementComponent | 이동 속도, 점프력 제어 |
| RigidbodyComponent | 물리(중력, 발판), 메이플스토리 이동 |
| KinematicbodyComponent | RectTileMap 상하좌우 이동 |
| SideviewbodyComponent | SideViewRectTileMap 횡스크롤 이동 |
| StateComponent | 상태 머신 (Walk, Jump, Dead 등) |
| AvatarRendererComponent | 아바타 렌더링, 색상, 감정표현 |
| AvatarStateAnimationComponent | 상태 → 아바타 애니메이션 연결 |
| CostumeManagerComponent | 장비/코스튬 관리 → 상세는 msw-costume 스킬 참조 |
| CameraComponent | 카메라 추적 설정 |
| PlayerControllerComponent | 입력-액션 매핑, 조건 처리 |
| PlayerComponent | HP, 사망/부활, PVP, 맵 이동 |
| ChatBalloonComponent | 채팅 풍선 |
| NameTagComponent | 이름표 |
| DamageSkinSettingComponent | 데미지 스킨 |
| DamageSkinSpawnerComponent | 데미지 스킨 스폰 |
| HitEffectSpawnerComponent | 히트 이펙트 스폰 |
| TriggerComponent | 충돌 감지 |
| InventoryComponent | 인벤토리 |
DefaultPlayer.model에서 추가된 스크립트 컴포넌트:
| 컴포넌트 | 역할 |
|---|---|
| script.PlayerHit | 플레이어 피격 로직 |
| script.PlayerAttack | 플레이어 공격 로직 |
핵심 컴포넌트 빠른 참조
| 컴포넌트 | 역할 | 핵심 프로퍼티/메서드 |
|---|---|---|
| PlayerComponent | HP, 사망/부활, PVP, 맵 이동 | Hp, MaxHp, PVPMode, RespawnDuration, RespawnPosition, UserId, IsDead(), ProcessDead(), ProcessRevive(), MoveToMapPosition() |
| PlayerControllerComponent | 입력→액션 매핑, 조건 제어 | SetActionKey(key, actionName), ActionAttack(), ActionJump(), LookDirectionX |
| MovementComponent | 이동 속도/점프 상위 인터페이스 | InputSpeed(기본 1.0), JumpForce(기본 1), Jump(), Stop() |
| RigidbodyComponent | 메이플 사이드뷰 물리 (중력/발판) | Gravity, WalkAcceleration, WalkSpeed, AddForce(), IsOnGround() |
| KinematicbodyComponent | RectTile 탑뷰 상하좌우 이동 | (RectTile 맵 모드 전용) |
| SideviewbodyComponent | SideViewRectTile 사이드뷰 | (SideViewRectTile 맵 모드 전용) |
| AvatarRendererComponent | 아바타 렌더링/색상/감정표현 | SetColor(), SetAlpha(), PlayEmotion(), PlayRate |
| StateComponent | 상태 머신 (Walk/Jump/Dead) | CurrentStateName, ChangeState(), DeadEvent/ReviveEvent |
| NameTagComponent | 이름표 | Name, FontSize, FontColor, NameTagRUID |
| ChatBalloonComponent | 채팅 풍선 | Message, ChatModeEnabled, ShowDuration |
| CameraComponent | 카메라 추적 | DeadZone, SoftZone, Damping, ScreenOffset |
| TriggerComponent | 충돌 감지 | BoxSize, Offset, CollisionGroup |
DefaultPlayer Values 구조
DefaultPlayer.model의 Values 배열 항목 형식:
{
"TargetType": "컴포넌트명 또는 null",
"Name": "프로퍼티명",
"ValueType": {
"$type": "MODNativeType",
"type": "타입 정보"
},
"Value": 값
}TargetType 규칙
null: Player.model의 Properties에 정의된 모델 프로퍼티 (Properties 링크를 통해 실제 컴포넌트 프로퍼티로 연결됨)"MOD.Core.컴포넌트명": 특정 네이티브 컴포넌트의 프로퍼티를 직접 오버라이드"script.스크립트명": 커스텀 스크립트 컴포넌트의 프로퍼티
모델 프로퍼티 (TargetType: null)
Player.model의 Properties에서 정의된 링크를 통해 실제 컴포넌트 프로퍼티로 매핑된다.
| 모델 프로퍼티명 | 원본 컴포넌트.프로퍼티 | 설명 | 기본값 |
|---|---|---|---|
| speed | MovementComponent.InputSpeed | 이동 속도 | 1.0 |
| jumpForce | MovementComponent.JumpForce | 점프 높이 | 1.0 |
| walkAcceleration | RigidbodyComponent.WalkAcceleration | 가속/감속 | 1.0 |
| gravity | RigidbodyComponent.Gravity | 중력 | 1.0 |
| cameraDeadZone | CameraComponent.DeadZone | 카메라 데드존 | {x: 0.052, y: 0.08} |
| cameraSoftZone | CameraComponent.SoftZone | 카메라 소프트존 | {x: 0.268, y: 0.7} |
| cameraDamping | CameraComponent.Damping | 카메라 부드러운 추적 | {x: 2.5, y: 3.9} |
| cameraScreen | CameraComponent.ScreenOffset | 데드존 중심점 | {x: 0.5, y: 0.655} |
| cameraDutch | CameraComponent.DutchAngle | 카메라 회전 | 0.0 |
| cameraOffset | CameraComponent.CameraOffset | 카메라 위치 오프셋 | {x: 0.0, y: 0.0} |
| nameTag | NameTagComponent.Name | 이름표 | "" |
| damageSkinId | DamageSkinSettingComponent.DamageSkinId | 데미지 스킨 타입 | DataRef |
| damageDelayPerAttack | DamageSkinSettingComponent.DelayPerAttack | 데미지 딜레이 | 0.05 |
| triggerBodyBoxSize | TriggerComponent.BoxSize | 충돌 감지 영역 크기 | {x: 0.66, y: 0.7} |
| triggerBodyBoxOffset | TriggerComponent.BoxOffset | 충돌 감지 영역 오프셋 | {x: 0.0, y: 0.35} |
| triggerBodyColliderOffset | TriggerComponent.ColliderOffset | 충돌체 오프셋 | {x: 0.0, y: 0.35} |
| maxHp | PlayerComponent.MaxHp | 최대 HP | 1000 |
컴포넌트 직접 오버라이드 (TargetType: 특정 컴포넌트)
모델 프로퍼티 링크가 아닌, 컴포넌트 프로퍼티를 직접 오버라이드하는 값:
| TargetType | Name | 설명 | 기본값 |
|---|---|---|---|
| MOD.Core.CameraComponent | ZoomRatioMax | 카메라 최대 줌 비율 | 500.0 |
| MOD.Core.MovementComponent | JumpForce | 점프력 (직접 오버라이드) | 1.0 |
| MOD.Core.MovementComponent | InputSpeed | 이동 속도 (직접 오버라이드) | 1.0 |
| script.PlayerHit | CollisionGroup | 피격 충돌 그룹 | CollisionGroup ID |
| script.PlayerHit | BoxSize | 피격 충돌 영역 크기 | {x: 0.45, y: 0.7} |
| script.PlayerHit | ColliderOffset | 피격 충돌 오프셋 | {x: 0.0, y: 0.35} |
맵 모드별 이동 컴포넌트
TileMapMode↔Body 매핑 테이블은 msw-general/references/platform.md §4 참조. 맵 모드에 따라 RigidbodyComponent / KinematicbodyComponent / SideviewbodyComponent 중 하나가 활성화된다.플레이어 식별 방법 (스크립트 참조)
entity.PlayerComponent ~= nil→ 해당 엔티티가 플레이어인지 확인_UserService.LocalPlayer→ 나의 플레이어 엔티티 (클라이언트 전용)_UserService:GetUserEntityByUserId(userId)→ 특정 유저의 플레이어 엔티티
주요 서비스 요약 (스크립트 참조)
| 서비스 | 역할 | 핵심 API |
|---|---|---|
| _UserService | 유저 관리, 입장/퇴장 | LocalPlayer, UserEntities, GetUserEntityByUserId(), UserEnterEvent/UserLeaveEvent |
| _TeleportService | 텔레포트/맵 이동 | TeleportToEntity(), TeleportToMapPosition(), WarpUserToWorldAsync() |
| _CameraService | 카메라 제어 | SwitchCameraTo(), ZoomTo(), ZoomReset() |
| DefaultUserEnterLeaveLogic | 유저 입장/퇴장 로직 | PlayerUri(플레이어 모델 ID), StartPoint(시작 맵) |
DefaultPlayer 수정 방법
속성값(Values) 수정
./Global/DefaultPlayer.model 파일을 열어 ContentProto.Json.Values 배열에서 해당 항목의 Value를 수정한다.
예: 이동 속도를 2.0으로 변경
Values 배열에서 Name이 "speed"인 항목을 찾아 Value를 수정:
{
"TargetType": null,
"Name": "speed",
"ValueType": { ... },
"Value": 2.0
}또는 컴포넌트 직접 오버라이드 항목에서 MovementComponent의 InputSpeed:
{
"TargetType": "MOD.Core.MovementComponent",
"Name": "InputSpeed",
"ValueType": { ... },
"Value": 2.0
}참고: 모델 프로퍼티(TargetType: null,Name: "speed")와 컴포넌트 직접 오버라이드(TargetType: "MOD.Core.MovementComponent",Name: "InputSpeed")가 모두 존재할 수 있다. 양쪽을 일관되게 수정해야 한다.
예: 점프력 1.5 + HP 2000으로 변경
Values 배열에서 각각의 항목을 찾아 수정:
// jumpForce 모델 프로퍼티
{ "TargetType": null, "Name": "jumpForce", "Value": 1.5 }
// MovementComponent 직접 오버라이드
{ "TargetType": "MOD.Core.MovementComponent", "Name": "JumpForce", "Value": 1.5 }
// maxHp 모델 프로퍼티
{ "TargetType": null, "Name": "maxHp", "Value": 2000 }새 Values 항목 추가
Values 배열에 새 항목을 추가하여 기본값을 오버라이드할 수 있다. ValueType 형식을 정확히 맞춰야 한다.
주요 ValueType 패턴:
// float (System.Single)
"ValueType": {
"$type": "MODNativeType",
"type": "System.Single, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
}
// int (System.Int64)
"ValueType": {
"$type": "MODNativeType",
"type": "System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
}
// string
"ValueType": {
"$type": "MODNativeType",
"type": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
}
// Vector2 (MODVector2)
"ValueType": {
"$type": "MODNativeType",
"type": "MOD.Core.MODVector2, MOD.Core, Version=1.11.0.0, Culture=neutral, PublicKeyToken=null"
}
// Value 형식: { "$type": "MOD.Core.MODVector2, MOD.Core", "x": 0.0, "y": 0.0 }
// DataRef (MODDataRef)
"ValueType": {
"$type": "MODNativeType",
"type": "MOD.Core.MODDataRef, MOD.Core, Version=1.11.0.0, Culture=neutral, PublicKeyToken=null"
}
// Value 형식: { "$type": "MOD.Core.MODDataRef, MOD.Core", "DataId": "hex..." }
// CollisionGroup
"ValueType": {
"$type": "MODNativeType",
"type": "MOD.Core.Physics.CollisionGroup, MOD.Core, Version=1.11.0.0, Culture=neutral, PublicKeyToken=null"
}
// Value 형식: { "$type": "MOD.Core.Physics.CollisionGroup, MOD.Core", "Id": "hex..." }
// boolean (System.Boolean) — Enable=false/true에 사용
"ValueType": {
"$type": "MODNativeType",
"type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
}
// Value 형식: true 또는 false컴포넌트 추가
./Global/DefaultPlayer.model의 ContentProto.Json.Components 배열에 항목 추가.
커스텀 스크립트 컴포넌트 추가:
"Components": [
"script.PlayerHit",
"script.PlayerAttack",
"script.MyCustomComponent"
]커스텀 스크립트(.mlua)는 반드시./RootDesk/MyDesk/에 생성해야 한다. 스크립트를 먼저 작성한 후 Components 배열에"script.스크립트명"으로 추가한다.
네이티브 컴포넌트 추가 (예: SpriteRendererComponent):
"Components": [
"script.PlayerHit",
"script.PlayerAttack",
"MOD.Core.SpriteRendererComponent"
]컴포넌트 제거
DefaultPlayer.model의 Components 배열에서 해당 항목을 제거한다. 관련 Values 항목도 함께 제거해야 한다.
주의: Player.model(베이스)에서 상속된 컴포넌트는 DefaultPlayer.model의 Components에 없으므로, 베이스 컴포넌트를 제거하려면 Player.model 자체를 수정해야 한다. 일반적으로 베이스 컴포넌트 제거는 권장하지 않는다.
DefaultPlayer 숨기기
DefaultPlayer는 base model 상속 컴포넌트이므로 삭제 불가. Enable=false로 비활성화하는 것이 유일한 방법이다.
컴포넌트 유지/비활성화 분류
| 컴포넌트 | 완전 숨기기 | 아바타만 숨기기 | 비고 |
|---|---|---|---|
| TransformComponent | 유지 | 유지 | 필수 |
| PlayerComponent | 유지 | 유지 | 필수 — 비활성화 시 입장 실패 |
| StateComponent | 유지 | 유지 | 비활성화 시 다른 컴포넌트 에러 |
| MovementComponent | 유지 | 유지 | 이동 필요 시 유지 |
| CameraComponent | 유지 | 유지 | 카메라 필요 시 유지 |
| AvatarRendererComponent | 비활성화 | 비활성화 | 핵심 — 이것만 꺼도 안 보임 |
| AvatarStateAnimationComponent | 비활성화 | 비활성화 | |
| CostumeManagerComponent | 비활성화 | 비활성화 | |
| PlayerControllerComponent | 비활성화 | 유지 | 이동 차단 여부에 따라 |
| ChatBalloonComponent | 비활성화 | 비활성화 | |
| NameTagComponent | 비활성화 | 비활성화 | |
| DamageSkinSettingComponent | 비활성화 | 비활성화 | |
| DamageSkinSpawnerComponent | 비활성화 | 비활성화 | |
| HitComponent | 비활성화 | 비활성화 | |
| HitEffectSpawnerComponent | 비활성화 | 비활성화 | |
| TriggerComponent | 비활성화 | 비활성화 | |
| InventoryComponent | 비활성화 | 비활성화 | |
| RigidbodyComponent | 비활성화 | 맵 모드 유지 | MapleTile 맵일 때 |
| SideviewbodyComponent | 비활성화 | 맵 모드 유지 | SideViewRectTile 맵일 때 |
| KinematicbodyComponent | EnableShadow=false | EnableShadow=false | 그림자만 제거 |
파일 편집 — Values에 Enable=false 추가
./Global/DefaultPlayer.model의 ContentProto.Json.Values 배열에 항목 추가. 기존에 없는 컴포넌트 Enable 항목은 새로 추가한다.
{
"TargetType": "MOD.Core.AvatarRendererComponent",
"Name": "Enable",
"ValueType": {
"$type": "MODNativeType",
"type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
},
"Value": false
}동일 패턴으로 비활성화할 컴포넌트마다 항목 추가. 그림자 제거는:
{
"TargetType": "MOD.Core.KinematicbodyComponent",
"Name": "EnableShadow",
"ValueType": {
"$type": "MODNativeType",
"type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
},
"Value": false
}파일 저장 후 Maker Refresh 필수.
DefaultPlayer 컴포넌트 확장 패턴
- 비아바타 플레이어: AvatarRendererComponent 비활성화 → SpriteRendererComponent 추가 → SpriteRUID 설정.
- 충돌 설정: TriggerComponent의 Values에서 ColliderType, CollisionGroup 조정.
- SpawnLocation: 맵(.map) 파일에서 Special → SpawnLocation 배치 (부활 위치).
워크플로우
플레이어 기본 속성 수정 (이동 속도, 점프력, HP 등)
1. ./Global/DefaultPlayer.model 파일 읽기 → Values 배열 확인
2. 수정할 프로퍼티 항목을 찾아 Value 변경
3. 모델 프로퍼티(TargetType: null)와 컴포넌트 직접 오버라이드가 모두 있는 경우 양쪽 일관 수정
4. 파일 저장플레이어에 커스텀 스크립트 추가
1. ./RootDesk/MyDesk/ 에 새 .mlua 스크립트 작성 (msw-scripting 스킬 참조)
2. ./Global/DefaultPlayer.model 의 Components 배열에 "script.스크립트명" 추가
3. 필요 시 Values 배열에 스크립트 프로퍼티 기본값 추가
4. Maker Refresh 요청 (.codeblock 자동 생성)카메라 설정 변경
1. ./Global/DefaultPlayer.model 읽기
2. Values에서 cameraDeadZone, cameraSoftZone, cameraDamping, cameraScreen, cameraDutch, cameraOffset 수정
3. 파일 저장경계 및 주의사항
담당 영역
- DefaultPlayer/Player 모델 파일(.model) 조회/수정
- 컴포넌트 추가/제거 (Components 배열)
- 이동/물리/HP/카메라 설정 (Values 배열)
비담당 영역
- 코스튬/아바타 장비 →
msw-costume스킬 - UI 에디터 →
./ui/폴더의.ui 파일 (전용 스킬) - 맵 편집 →
./map/폴더의.map 파일 (전용 스킬, NPC/몬스터 스폰 포함) - 일반 스크립트/리소스 → 각 전용 스킬
제약
- Global/ 폴더 주의: DefaultPlayer.model과 Player.model은
./Global/에 있다. 이 폴더는 엔진 기본 템플릿 전용이므로 신규 파일 생성은 권장하지 않는다. - 커스텀 스크립트 위치: 새 스크립트 파일은 반드시
./RootDesk/MyDesk/에 생성한다. - 맵 모드 주의: 맵 모드(MapleTile/RectTile/SideViewRectTile)에 따라 활성 이동 컴포넌트가 다르다.
- ValueType 정확성: Values 항목 추가 시
ValueType형식(특히 어셈블리 버전)을 기존 항목과 일치시켜야 한다. - Maker Refresh: 스크립트 추가/수정 후에는 Maker Refresh가 필요하다 (.codeblock 자동 생성).