Pool 적용 버그 잡는 중
This commit is contained in:
@@ -10,9 +10,6 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 302300799186228596}
|
||||
- component: {fileID: 8488195170614820883}
|
||||
- component: {fileID: 3820258601269832329}
|
||||
- component: {fileID: 363746616583149630}
|
||||
- component: {fileID: 5360656424770899642}
|
||||
m_Layer: 0
|
||||
m_Name: AGV
|
||||
m_TagString: Untagged
|
||||
@@ -32,7 +29,8 @@ Transform:
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Children:
|
||||
- {fileID: 8708419218786706813}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &8488195170614820883
|
||||
@@ -47,24 +45,72 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: bc083cb3e97c87446bc1a7db7b4ef9e4, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
moveSpeed: 1
|
||||
rotationSpeed: 1
|
||||
modelObject: {fileID: 7493524444357289953}
|
||||
moveSpeed: 0.5
|
||||
rotationSpeed: 0.5
|
||||
teleportDistanceThreshold: 5
|
||||
--- !u!33 &3820258601269832329
|
||||
--- !u!1 &6358428858938227828
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8708419218786706813}
|
||||
- component: {fileID: 7493524444357289953}
|
||||
- component: {fileID: 6887510220552103127}
|
||||
- component: {fileID: 9132754914965147154}
|
||||
- component: {fileID: 6486094733119401088}
|
||||
m_Layer: 0
|
||||
m_Name: Cube
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &8708419218786706813
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6358428858938227828}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0.5, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 302300799186228596}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &7493524444357289953
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6358428858938227828}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 369f10656ae555b4983fa3147fc56818, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!33 &6887510220552103127
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1373625414374435398}
|
||||
m_GameObject: {fileID: 6358428858938227828}
|
||||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!23 &363746616583149630
|
||||
--- !u!23 &9132754914965147154
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1373625414374435398}
|
||||
m_GameObject: {fileID: 6358428858938227828}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
@@ -103,13 +149,13 @@ MeshRenderer:
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!65 &5360656424770899642
|
||||
--- !u!65 &6486094733119401088
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1373625414374435398}
|
||||
m_GameObject: {fileID: 6358428858938227828}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
@@ -118,7 +164,7 @@ BoxCollider:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 1
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
|
||||
415
Assets/Resources/Prefabs/SampleProject/Factory/Alarm.prefab
Normal file
415
Assets/Resources/Prefabs/SampleProject/Factory/Alarm.prefab
Normal file
@@ -0,0 +1,415 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &494093931030574861
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5765213305061083199}
|
||||
- component: {fileID: 4826901156942800586}
|
||||
- component: {fileID: 8650239058674280921}
|
||||
m_Layer: 5
|
||||
m_Name: Text (TMP)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &5765213305061083199
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 494093931030574861}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 2463437008278947656}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &4826901156942800586
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 494093931030574861}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &8650239058674280921
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 494093931030574861}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: 0
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 08cebd004d97ca742ac80400f37f4eed, type: 2}
|
||||
m_sharedMaterial: {fileID: 4860575619018115804, guid: 08cebd004d97ca742ac80400f37f4eed, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4278190080
|
||||
m_fontColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 36
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!1 &952545100964675415
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8574585598928791195}
|
||||
m_Layer: 5
|
||||
m_Name: expandedView
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &8574585598928791195
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 952545100964675415}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 2463437008278947656}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!1 &1828762385695490929
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2463437008278947656}
|
||||
- component: {fileID: 5380681345511526047}
|
||||
m_Layer: 5
|
||||
m_Name: Alarm
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2463437008278947656
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1828762385695490929}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 5007029136827874888}
|
||||
- {fileID: 5765213305061083199}
|
||||
- {fileID: 8574585598928791195}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 100, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &5380681345511526047
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1828762385695490929}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 773fa02b59601044b8be752f78f63e55, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
clusterView: {fileID: 4918696741701580718}
|
||||
alarmCountText: {fileID: 8650239058674280921}
|
||||
expandedView: {fileID: 952545100964675415}
|
||||
singleAlarmIconPrefab: {fileID: 7314511769243682470, guid: e9acc8c9a93a2b5409fc01661660b217, type: 3}
|
||||
--- !u!1 &4918696741701580718
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5007029136827874888}
|
||||
m_Layer: 5
|
||||
m_Name: clusterView
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &5007029136827874888
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4918696741701580718}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 7229327262419467602}
|
||||
- {fileID: 1591538567731418999}
|
||||
m_Father: {fileID: 2463437008278947656}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!1 &7297564150823027611
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 7229327262419467602}
|
||||
- component: {fileID: 7287393582081843390}
|
||||
- component: {fileID: 4544043674251718843}
|
||||
m_Layer: 5
|
||||
m_Name: shadow
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &7229327262419467602
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7297564150823027611}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 5007029136827874888}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 5, y: -5}
|
||||
m_SizeDelta: {x: 10, y: 10}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &7287393582081843390
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7297564150823027611}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &4544043674251718843
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7297564150823027611}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 887145076, guid: 4cf3568ca3f55f64cb11447d139d7a3d, type: 3}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &7656214594090597472
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1591538567731418999}
|
||||
- component: {fileID: 8641121927952400765}
|
||||
- component: {fileID: 4970931623191621822}
|
||||
m_Layer: 5
|
||||
m_Name: bg
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1591538567731418999
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7656214594090597472}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 5007029136827874888}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &8641121927952400765
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7656214594090597472}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &4970931623191621822
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7656214594090597472}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: -895992892, guid: 73d757b5d1b754245969af12daf01e78, type: 3}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8b88e69e607ee448806427e91440a8e
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
340
Assets/Resources/Prefabs/SampleProject/Factory/AlarmIcon.prefab
Normal file
340
Assets/Resources/Prefabs/SampleProject/Factory/AlarmIcon.prefab
Normal file
@@ -0,0 +1,340 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &1326045257776503954
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8602533637707951236}
|
||||
- component: {fileID: 5770335694761070239}
|
||||
- component: {fileID: 2018211268787215362}
|
||||
m_Layer: 5
|
||||
m_Name: Text (TMP)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &8602533637707951236
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1326045257776503954}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 3374630250525829090}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: -20, y: -20}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &5770335694761070239
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1326045257776503954}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &2018211268787215362
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1326045257776503954}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: TR
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 08cebd004d97ca742ac80400f37f4eed, type: 2}
|
||||
m_sharedMaterial: {fileID: 4860575619018115804, guid: 08cebd004d97ca742ac80400f37f4eed, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4278190080
|
||||
m_fontColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 12
|
||||
m_fontSizeBase: 12
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 1
|
||||
m_VerticalAlignment: 256
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!1 &3798696889335606665
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6765948511015989509}
|
||||
- component: {fileID: 2825211744860677609}
|
||||
- component: {fileID: 7215137539608397115}
|
||||
m_Layer: 5
|
||||
m_Name: shadow
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &6765948511015989509
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3798696889335606665}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 3374630250525829090}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 5, y: -5}
|
||||
m_SizeDelta: {x: 10, y: 10}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &2825211744860677609
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3798696889335606665}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &7215137539608397115
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3798696889335606665}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 887145076, guid: 4cf3568ca3f55f64cb11447d139d7a3d, type: 3}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &7314511769243682470
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3374630250525829090}
|
||||
- component: {fileID: 5545478218830425297}
|
||||
m_Layer: 5
|
||||
m_Name: AlarmIcon
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &3374630250525829090
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7314511769243682470}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 6765948511015989509}
|
||||
- {fileID: 5399931818953919527}
|
||||
- {fileID: 8602533637707951236}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 100, y: 150}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &5545478218830425297
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7314511769243682470}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: cd395cde180b3094a91d87699139bbcf, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
text: {fileID: 2018211268787215362}
|
||||
--- !u!1 &8817008079317718099
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5399931818953919527}
|
||||
- component: {fileID: 1290445261252787132}
|
||||
- component: {fileID: 2283905710529375295}
|
||||
m_Layer: 5
|
||||
m_Name: bg
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &5399931818953919527
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8817008079317718099}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 3374630250525829090}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &1290445261252787132
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8817008079317718099}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &2283905710529375295
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8817008079317718099}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: -895992892, guid: 73d757b5d1b754245969af12daf01e78, type: 3}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9acc8c9a93a2b5409fc01661660b217
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -208,6 +208,127 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &1844102171940980497
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1010396666164740167}
|
||||
- component: {fileID: 380188952969839968}
|
||||
- component: {fileID: 170663812404971233}
|
||||
- component: {fileID: 8791400826399403740}
|
||||
m_Layer: 5
|
||||
m_Name: CopyButton
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1010396666164740167
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1844102171940980497}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 5059140281209684741}
|
||||
m_Father: {fileID: 4802890858156259540}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 1, y: 1}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: -20, y: -2}
|
||||
m_SizeDelta: {x: 30, y: 15}
|
||||
m_Pivot: {x: 1, y: 1}
|
||||
--- !u!222 &380188952969839968
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1844102171940980497}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &170663812404971233
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1844102171940980497}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0.26415092, g: 0.26415092, b: 0.26415092, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: -27720893, guid: e5829cbc100001646956a9c3ed4e33c5, type: 3}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &8791400826399403740
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1844102171940980497}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_WrapAround: 0
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 170663812404971233}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &4884066667293879814
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -316,6 +437,7 @@ RectTransform:
|
||||
- {fileID: 7383335062191980062}
|
||||
- {fileID: 2993317773174661490}
|
||||
- {fileID: 6308980257678838100}
|
||||
- {fileID: 1010396666164740167}
|
||||
- {fileID: 6685372230643413407}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
@@ -346,6 +468,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
text: {fileID: 4202672738064507978}
|
||||
closeButton: {fileID: 5925304901667948221}
|
||||
copyButton: {fileID: 8791400826399403740}
|
||||
screenOffset: {x: 10, y: 10}
|
||||
menuBarHeight: 70
|
||||
--- !u!1 &7346391167643616437
|
||||
@@ -484,3 +607,139 @@ MonoBehaviour:
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!1 &7999202329282239406
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5059140281209684741}
|
||||
- component: {fileID: 8801292156144245076}
|
||||
- component: {fileID: 6403130881974049321}
|
||||
m_Layer: 5
|
||||
m_Name: Text (TMP)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &5059140281209684741
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7999202329282239406}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1010396666164740167}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &8801292156144245076
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7999202329282239406}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &6403130881974049321
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7999202329282239406}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: Copy
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 08cebd004d97ca742ac80400f37f4eed, type: 2}
|
||||
m_sharedMaterial: {fileID: 4860575619018115804, guid: 08cebd004d97ca742ac80400f37f4eed, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 8
|
||||
m_fontSizeBase: 8
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
|
||||
@@ -926,6 +926,51 @@ RectTransform:
|
||||
m_CorrespondingSourceObject: {fileID: 8849628700159893901, guid: 5a23b2bd2bd04c045878e1a06b3b9aa2, type: 3}
|
||||
m_PrefabInstance: {fileID: 769109585}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1 &784978156
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 784978157}
|
||||
- component: {fileID: 784978158}
|
||||
m_Layer: 0
|
||||
m_Name: AlarmManager
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &784978157
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 784978156}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 429.2735, y: 488.27496, z: 49.768143}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &784978158
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 784978156}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 6765c5d969530e44cbe4fc91d5e52ca1, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
alarmUIPrefab: {fileID: 1828762385695490929, guid: e8b88e69e607ee448806427e91440a8e, type: 3}
|
||||
--- !u!1 &832575517
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -980,6 +1025,115 @@ RectTransform:
|
||||
m_CorrespondingSourceObject: {fileID: 5064510836022735693, guid: 27ddee6261f49584c8634ba7c5f4ae46, type: 3}
|
||||
m_PrefabInstance: {fileID: 8261569461642068635}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1 &1091201604
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1091201608}
|
||||
- component: {fileID: 1091201607}
|
||||
- component: {fileID: 1091201606}
|
||||
- component: {fileID: 1091201605}
|
||||
m_Layer: 0
|
||||
m_Name: Plane
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!64 &1091201605
|
||||
MeshCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1091201604}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 5
|
||||
m_Convex: 0
|
||||
m_CookingOptions: 30
|
||||
m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!23 &1091201606
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1091201604}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!33 &1091201607
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1091201604}
|
||||
m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!4 &1091201608
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1091201604}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 1000, y: 0, z: 1000}
|
||||
m_LocalScale: {x: 300, y: 1, z: 300}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1101428664
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -2069,8 +2223,10 @@ SceneRoots:
|
||||
- {fileID: 832575519}
|
||||
- {fileID: 632541407}
|
||||
- {fileID: 27812499}
|
||||
- {fileID: 784978157}
|
||||
- {fileID: 2030316712}
|
||||
- {fileID: 483439351}
|
||||
- {fileID: 495653798}
|
||||
- {fileID: 88083293}
|
||||
- {fileID: 1840728471}
|
||||
- {fileID: 1091201608}
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace SampleProject
|
||||
|
||||
mqttPipeLine = new MQTTPipeLine("localhost", 1883);
|
||||
mqttPipeLine.AddTopic("AGV");
|
||||
//mqttPipeLine.AddTopic("ALARM");
|
||||
mqttPipeLine.Execute();
|
||||
|
||||
//10초 후 정지
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UVC.Core;
|
||||
using UVC.Factory.Alarm;
|
||||
using UVC.UI.Tooltip;
|
||||
|
||||
namespace SampleProject
|
||||
@@ -21,6 +22,17 @@ namespace SampleProject
|
||||
AppMain.Instance.Initialized += OnAppInitialized;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AGV 관리자가 생성될 때 발생하는 이벤트를 처리합니다.
|
||||
/// </summary>
|
||||
/// <remarks>이 메서드는 AGV 관리자 생성과 관련된 필요한 초기화 또는 설정 작업을 수행하기 위한 것입니다.
|
||||
/// 내부적으로 호출되며 외부 코드에서 직접 사용하도록 의도된 것이 아닙니다.
|
||||
///</remarks>
|
||||
internal void OnAGVManagerCreated()
|
||||
{
|
||||
AlarmManager.Instance.Run();
|
||||
}
|
||||
|
||||
private void OnAppInitialized()
|
||||
{
|
||||
if (Initialized != null)
|
||||
|
||||
@@ -3,6 +3,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UVC.Data
|
||||
{
|
||||
@@ -11,12 +12,21 @@ namespace UVC.Data
|
||||
/// </summary>
|
||||
public class DataArray : List<DataObject>, IDataObject
|
||||
{
|
||||
|
||||
private bool isInPool = false;
|
||||
/// <summary>
|
||||
/// 이 객체가 객체 풀에 있는지 여부를 나타냅니다.
|
||||
/// 중복 반환을 방지하기 위해 DataArrayPool에서 내부적으로 사용됩니다.
|
||||
/// </summary>
|
||||
internal bool IsInPool { get; set; } = false;
|
||||
internal bool IsInPool { get => isInPool;
|
||||
set
|
||||
{
|
||||
isInPool = value;
|
||||
foreach (var item in this)
|
||||
{
|
||||
item.IsInPool = value; // 내부 DataObject도 풀에 있다고 표시합니다.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 추가 된 항목 목록
|
||||
protected List<DataObject> addedList = new List<DataObject>();
|
||||
@@ -77,6 +87,26 @@ namespace UVC.Data
|
||||
}
|
||||
}
|
||||
|
||||
public DataArray(System.IO.Stream jsonStream)
|
||||
{
|
||||
if (jsonStream == null)
|
||||
throw new ArgumentNullException(nameof(jsonStream));
|
||||
|
||||
// 스트림 처리 최적화를 위해 청크 단위로 읽을 수 있지만,
|
||||
// 현재는 Newtonsoft.Json의 기본 역직렬화 사용
|
||||
using (var reader = new Newtonsoft.Json.JsonTextReader(new System.IO.StreamReader(jsonStream)))
|
||||
{
|
||||
// 청크 읽기 설정 - 메모리 사용량 최적화
|
||||
reader.SupportMultipleContent = true;
|
||||
|
||||
var serializer = new Newtonsoft.Json.JsonSerializer();
|
||||
var sourceObject = serializer.Deserialize<JArray>(reader);
|
||||
|
||||
// 수정된 코드: 생성자를 호출하는 대신 JArray 메서드를 사용
|
||||
if (sourceObject != null) FromJArray(sourceObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// JArray로부터 DataArray를 생성하는 생성자
|
||||
/// </summary>
|
||||
@@ -191,8 +221,7 @@ namespace UVC.Data
|
||||
|
||||
// 기존 변경 추적 목록을 초기화합니다.
|
||||
ClearTrackedChanges();
|
||||
|
||||
// 성능 향상을 위해 ID를 키로 사용하는 사전을 생성합니다.
|
||||
|
||||
var thisDict = this.ToDictionary(item => item.Id);
|
||||
var otherDict = otherArray.ToDictionary(item => item.Id);
|
||||
|
||||
@@ -208,7 +237,7 @@ namespace UVC.Data
|
||||
// 추가된 항목 확인 (다른 배열에는 있지만 현재 배열에는 없는 항목)
|
||||
foreach (var id in otherIds.Where(id => !thisIds.Contains(id)))
|
||||
{
|
||||
addedList.Add(otherDict[id]);
|
||||
addedList.Add(otherDict[id].Copy(fromPool: false));
|
||||
}
|
||||
|
||||
// 수정된 항목 확인 (양쪽 모두에 있지만 내용이 다른 항목)
|
||||
@@ -230,6 +259,12 @@ namespace UVC.Data
|
||||
// [성능 개선] RemoveAll과 HashSet을 사용하여 제거 작업의 효율성을 높입니다.
|
||||
if (removedList.Count > 0)
|
||||
{
|
||||
// 제거될 객체들을 먼저 풀에 반환합니다.
|
||||
foreach (var item in removedList)
|
||||
{
|
||||
if (item.IsInPool) item.ReturnToPool();
|
||||
}
|
||||
// 그 다음 리스트에서 제거합니다.
|
||||
var removedItemIds = new HashSet<string>(removedList.Select(i => i.Id));
|
||||
this.RemoveAll(item => removedItemIds.Contains(item.Id));
|
||||
}
|
||||
@@ -289,11 +324,10 @@ namespace UVC.Data
|
||||
/// </summary>
|
||||
public new void Clear()
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
ReturnToDataObjectPool();
|
||||
base.Clear();
|
||||
}
|
||||
// 내부 리스트와 변경 추적 리스트를 모두 비웁니다.
|
||||
ReturnToDataObjectPool();
|
||||
base.Clear();
|
||||
ClearTrackedChanges();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -301,16 +335,12 @@ namespace UVC.Data
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
// 포함된 DataObject들을 먼저 풀에 반환합니다.
|
||||
ReturnToDataObjectPool();
|
||||
|
||||
// 내부 리스트와 변경 추적 리스트를 모두 비웁니다.
|
||||
base.Clear();
|
||||
ClearTrackedChanges();
|
||||
Clear();
|
||||
}
|
||||
|
||||
public void ReturnToPool()
|
||||
{
|
||||
// 포함된 DataObject들을 먼저 풀에 반환합니다.
|
||||
DataArrayPool.Return(this);
|
||||
}
|
||||
|
||||
@@ -322,7 +352,7 @@ namespace UVC.Data
|
||||
{
|
||||
foreach (var item in this)
|
||||
{
|
||||
DataObjectPool.Return(item);
|
||||
item.ReturnToPool();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,37 +370,53 @@ namespace UVC.Data
|
||||
/// 동일한 상태와 값을 가진 현재 데이터 객체의 새 인스턴스를 생성합니다.
|
||||
/// </summary>
|
||||
/// <remarks>복제된 객체는 원본 객체와 독립적이므로, 한 객체를 변경해도 다른 객체에는 영향을 미치지 않습니다.
|
||||
///</remarks>
|
||||
/// </remarks>
|
||||
/// <param name="fromPool">객체 풀에서 복제할지 여부를 지정합니다. 기본값은 true입니다.</param>
|
||||
/// <returns>현재 객체의 복사본인 새 <see cref="IDataObject"/> 인스턴스를 반환합니다.</returns>
|
||||
public IDataObject Clone()
|
||||
public IDataObject Clone(bool fromPool = true)
|
||||
{
|
||||
return Copy(fromPool);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 현재 <see cref="DataArray"/> 인스턴스의 요소 및 관련 상태를 포함한 깊은 복사본을 생성합니다.
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks>이 메서드는 현재 배열에 있는 모든 <see cref="DataObject"/> 요소의 깊은 복사본을 포함하는 새로운 <see cref="DataArray"/> 인스턴스를 반환합니다.
|
||||
/// 복사된 인스턴스는 내부 목록에서 추적하는 추가, 제거 또는 수정된 요소를 포함하여 원본 인스턴스의 상태도 복제합니다.
|
||||
/// </remarks>
|
||||
/// <param name="fromPool">객체 풀에서 복제할지 여부를 지정합니다. 기본값은 true입니다.</param>
|
||||
/// <returns>현재 인스턴스의 깊은 복사본인 새로운 <see cref="DataArray"/> 인스턴스를 반환합니다.</returns>
|
||||
|
||||
public DataArray Copy(bool fromPool = true)
|
||||
{
|
||||
// 풀에서 새 DataArray 인스턴스를 가져옵니다.
|
||||
var clone = DataArrayPool.Get();
|
||||
clone.FromCapacity(this.Count);
|
||||
DataArray clone;
|
||||
if(fromPool) clone = DataArrayPool.Get();
|
||||
else clone = new DataArray();
|
||||
|
||||
// 배열의 모든 DataObject를 순회하며 각각을 복제합니다.
|
||||
foreach (var item in this)
|
||||
{
|
||||
// DataObject의 Clone 메서드를 호출하여 깊은 복사를 수행하고,
|
||||
// base.Add를 사용해 추적 로직 없이 직접 추가합니다.
|
||||
if (item.Clone() is DataObject clonedItem)
|
||||
DataObject clonedItem = item.Copy(fromPool);
|
||||
clone.Add(clonedItem);
|
||||
if (addedList.Contains(item))
|
||||
{
|
||||
clone.Add(clonedItem);
|
||||
if (addedList.Contains(item))
|
||||
{
|
||||
clone.addedList.Add(clonedItem);
|
||||
}
|
||||
else if (removedList.Contains(item))
|
||||
{
|
||||
clone.removedList.Add(clonedItem);
|
||||
}
|
||||
else if (modifiedList.Contains(item))
|
||||
{
|
||||
clone.modifiedList.Add(clonedItem);
|
||||
}
|
||||
clone.addedList.Add(clonedItem);
|
||||
}
|
||||
else if (removedList.Contains(item))
|
||||
{
|
||||
clone.removedList.Add(clonedItem);
|
||||
}
|
||||
else if (modifiedList.Contains(item))
|
||||
{
|
||||
clone.modifiedList.Add(clonedItem);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace UVC.Data
|
||||
public static class DataArrayPool
|
||||
{
|
||||
private static readonly ConcurrentQueue<DataArray> _pool = new ConcurrentQueue<DataArray>();
|
||||
private static int _maxPoolSize = 500; // DataArray는 DataObject보다 수가 적을 것이므로 기본값 조정
|
||||
private static int _maxPoolSize = 100; // DataArray는 DataObject보다 수가 적을 것이므로 기본값 조정
|
||||
|
||||
// --- 통계용 필드 ---
|
||||
private static int _inUseCount = 0;
|
||||
@@ -18,15 +18,16 @@ namespace UVC.Data
|
||||
private static int _poolMisses = 0;
|
||||
private static readonly object _statsLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// 풀의 최대 크기를 설정합니다.
|
||||
/// </summary>
|
||||
/// <param name="size">설정할 최대 크기</param>
|
||||
public static void SetMaxPoolSize(int size)
|
||||
static DataArrayPool()
|
||||
{
|
||||
_maxPoolSize = size > 0 ? size : 500;
|
||||
// maxPoolSize만큼의 DataObject 인스턴스를 미리 생성하여 풀에 추가합니다.
|
||||
for (int i = 0; i < _maxPoolSize; i++)
|
||||
{
|
||||
_pool.Enqueue(new DataArray() { IsInPool = true });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 풀에서 DataArray 객체를 가져옵니다. 풀이 비어있으면 새로 생성합니다.
|
||||
/// </summary>
|
||||
@@ -50,17 +51,16 @@ namespace UVC.Data
|
||||
{
|
||||
int oldSize = _maxPoolSize;
|
||||
_maxPoolSize += 100; // 증가량 조정
|
||||
Debug.Log($"DataArrayPool size automatically increased from {oldSize} to {_maxPoolSize}. Peak usage: {_peakUsage}");
|
||||
//Debug.Log($"DataArrayPool size automatically increased from {oldSize} to {_maxPoolSize}. Peak usage: {_peakUsage}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(_peakUsage % 100 == 0) Debug.Log($"DataArrayPool stats: {GetStats()}");
|
||||
//if(_peakUsage % 10 == 0) Debug.Log($"DataArrayPool stats: {GetStats()}");
|
||||
|
||||
if (fromPool)
|
||||
{
|
||||
array.IsInPool = false;
|
||||
array.Reset();
|
||||
}
|
||||
return fromPool ? array : new DataArray();
|
||||
}
|
||||
@@ -93,7 +93,7 @@ namespace UVC.Data
|
||||
/// <returns>풀 통계 (최대 사용량, 현재 사용량, 풀 비어있을 때 생성 횟수, 현재 풀 크기)</returns>
|
||||
public static string GetStats()
|
||||
{
|
||||
return $"Peak Usage: {_peakUsage}, In Use: {_inUseCount}, Misses: {_poolMisses}, Pooled: {_pool.Count}, Max Size: {_maxPoolSize}";
|
||||
return $"최대 사용량: {_peakUsage}, 현재 사용량: {_inUseCount}, 풀 비어있을 때 생성 횟수: {_poolMisses}, 현재 풀 크기: {_pool.Count}, Max Size: {_maxPoolSize}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -49,12 +49,30 @@ namespace UVC.Data
|
||||
/// </example>
|
||||
public class DataObject : OrderedDictionary<string, object?>, IDataObject
|
||||
{
|
||||
|
||||
private bool isInPool = false;
|
||||
/// <summary>
|
||||
/// 이 객체가 객체 풀에 있는지 여부를 나타냅니다.
|
||||
/// 중복 반환을 방지하기 위해 DataObjectPool에서 내부적으로 사용됩니다.
|
||||
/// </summary>
|
||||
internal bool IsInPool { get; set; } = false;
|
||||
internal bool IsInPool
|
||||
{
|
||||
get => isInPool;
|
||||
set
|
||||
{
|
||||
isInPool = value;
|
||||
foreach (var item in this)
|
||||
{
|
||||
if(item.Value is DataObject dataObject)
|
||||
{
|
||||
dataObject.isInPool = value; // 내부 DataObject도 풀에 있다고 표시합니다.
|
||||
}
|
||||
else if(item.Value is DataArray dataArray)
|
||||
{
|
||||
dataArray.IsInPool = value; // 내부 DataArray도 풀에 있다고 표시합니다.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 객체의 고유 식별자를 나타내는 속성입니다. DataArray에서 데이터를 식별하는 데 사용됩니다.
|
||||
@@ -104,6 +122,30 @@ namespace UVC.Data
|
||||
/// </summary>
|
||||
public DataObject() { }
|
||||
|
||||
public DataObject(string jsonString): this(JObject.Parse(jsonString))
|
||||
{
|
||||
}
|
||||
|
||||
public DataObject(System.IO.Stream jsonStream)
|
||||
{
|
||||
if (jsonStream == null)
|
||||
throw new ArgumentNullException(nameof(jsonStream));
|
||||
|
||||
// 스트림 처리 최적화를 위해 청크 단위로 읽을 수 있지만,
|
||||
// 현재는 Newtonsoft.Json의 기본 역직렬화 사용
|
||||
using (var reader = new Newtonsoft.Json.JsonTextReader(new System.IO.StreamReader(jsonStream)))
|
||||
{
|
||||
// 청크 읽기 설정 - 메모리 사용량 최적화
|
||||
reader.SupportMultipleContent = true;
|
||||
|
||||
var serializer = new Newtonsoft.Json.JsonSerializer();
|
||||
var sourceObject = serializer.Deserialize<JObject>(reader);
|
||||
|
||||
// 수정된 코드: 생성자를 호출하는 대신 FromJObject 메서드를 사용
|
||||
if(sourceObject != null) FromJObject(sourceObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// JObject로부터 데이터 객체를 생성합니다.
|
||||
/// </summary>
|
||||
@@ -270,6 +312,16 @@ namespace UVC.Data
|
||||
|
||||
if (hasChanged)
|
||||
{
|
||||
// 기존에 풀링 가능한 객체가 있었다면 풀에 반환합니다.
|
||||
if (oldValue is DataObject oldDataObject)
|
||||
{
|
||||
if(oldDataObject.IsInPool) oldDataObject.ReturnToPool();
|
||||
}
|
||||
else if (oldValue is DataArray oldDataArray)
|
||||
{
|
||||
if (oldDataArray.IsInPool) oldDataArray.ReturnToPool();
|
||||
}
|
||||
|
||||
// 기본 딕셔너리에 값을 설정합니다.
|
||||
base[key] = value;
|
||||
|
||||
@@ -289,7 +341,7 @@ namespace UVC.Data
|
||||
/// <param name="propertyName">속성 이름</param>
|
||||
/// <param name="defaultValue">속성이 없거나 변환할 수 없는 경우 반환할 기본값</param>
|
||||
/// <returns>변환된 정수 값 또는 기본값</returns>
|
||||
public int GetInt(string propertyName, int defaultValue = 0)
|
||||
public int? GetInt(string propertyName, int? defaultValue = null)
|
||||
{
|
||||
if (TryGetValue(propertyName, out object? value) && value != null)
|
||||
{
|
||||
@@ -321,7 +373,7 @@ namespace UVC.Data
|
||||
/// <param name="propertyName">속성 이름</param>
|
||||
/// <param name="defaultValue">속성이 없거나 변환할 수 없는 경우 반환할 기본값</param>
|
||||
/// <returns>변환된 불리언 값 또는 기본값</returns>
|
||||
public bool GetBool(string propertyName, bool defaultValue = false)
|
||||
public bool? GetBool(string propertyName, bool? defaultValue = false)
|
||||
{
|
||||
if (TryGetValue(propertyName, out object? value) && value != null)
|
||||
{
|
||||
@@ -338,7 +390,7 @@ namespace UVC.Data
|
||||
/// <param name="propertyName">속성 이름</param>
|
||||
/// <param name="defaultValue">속성이 없거나 변환할 수 없는 경우 반환할 기본값</param>
|
||||
/// <returns>변환된 부동 소수점 값 또는 기본값</returns>
|
||||
public float GetFloat(string propertyName, float defaultValue = 0f)
|
||||
public float? GetFloat(string propertyName, float? defaultValue = null)
|
||||
{
|
||||
if (TryGetValue(propertyName, out object? value) && value != null)
|
||||
{
|
||||
@@ -355,7 +407,7 @@ namespace UVC.Data
|
||||
/// <param name="propertyName">속성 이름</param>
|
||||
/// <param name="defaultValue">속성이 없거나 변환할 수 없는 경우 반환할 기본값</param>
|
||||
/// <returns>변환된 더블 값 또는 기본값</returns>
|
||||
public double GetDouble(string propertyName, double defaultValue = 0.0)
|
||||
public double? GetDouble(string propertyName, double? defaultValue = null)
|
||||
{
|
||||
if (TryGetValue(propertyName, out object? value) && value != null)
|
||||
{
|
||||
@@ -372,7 +424,7 @@ namespace UVC.Data
|
||||
/// <param name="propertyName">속성 이름</param>
|
||||
/// <param name="defaultValue">속성이 없거나 변환할 수 없는 경우 반환할 기본값</param>
|
||||
/// <returns>변환된 long 값 또는 기본값</returns>
|
||||
public long GetLong(string propertyName, long defaultValue = 0L)
|
||||
public long? GetLong(string propertyName, long? defaultValue = null)
|
||||
{
|
||||
if (TryGetValue(propertyName, out object? value) && value != null)
|
||||
{
|
||||
@@ -407,7 +459,7 @@ namespace UVC.Data
|
||||
/// <param name="propertyName">속성 이름</param>
|
||||
/// <param name="defaultValue">속성이 없거나 변환할 수 없는 경우 반환할 기본값</param>
|
||||
/// <returns>변환된 열거형 값 또는 기본값</returns>
|
||||
public T GetEnum<T>(string propertyName, T defaultValue = default) where T : Enum
|
||||
public T? GetEnum<T>(string propertyName, T? defaultValue = default) where T : Enum
|
||||
{
|
||||
if (TryGetValue(propertyName, out object? value) && value != null)
|
||||
{
|
||||
@@ -572,9 +624,22 @@ namespace UVC.Data
|
||||
/// <returns>제거 성공 여부</returns>
|
||||
public new bool Remove(string key)
|
||||
{
|
||||
// 제거하기 전에 이전 값을 가져옵니다.
|
||||
TryGetValue(key, out object? oldValue);
|
||||
|
||||
bool result = base.Remove(key);
|
||||
if (result)
|
||||
{
|
||||
// 제거된 객체가 풀링 가능한 경우 풀에 반환합니다.
|
||||
if (oldValue is DataObject dataObject)
|
||||
{
|
||||
if(dataObject.IsInPool) dataObject.ReturnToPool();
|
||||
}
|
||||
else if (oldValue is DataArray dataArray)
|
||||
{
|
||||
if (dataArray.IsInPool) dataArray.ReturnToPool();
|
||||
}
|
||||
|
||||
// 변경 추적 목록에서도 제거합니다.
|
||||
changedProperies.Remove(key);
|
||||
}
|
||||
@@ -586,6 +651,17 @@ namespace UVC.Data
|
||||
/// </summary>
|
||||
public void RemoveAll()
|
||||
{
|
||||
foreach (var value in Values.ToList())
|
||||
{
|
||||
if(value is DataObject dataObject)
|
||||
{
|
||||
dataObject.ReturnToPool(); // DataObject를 풀에 반환합니다.
|
||||
}
|
||||
else if (value is DataArray dataArray)
|
||||
{
|
||||
dataArray.ReturnToPool(); // DataArray를 풀에 반환합니다.
|
||||
}
|
||||
}
|
||||
base.Clear();
|
||||
changedProperies.Clear();
|
||||
}
|
||||
@@ -606,10 +682,27 @@ namespace UVC.Data
|
||||
/// </summary>
|
||||
/// <remarks>복제된 객체는 원본 객체와 독립적이므로, 한 객체를 변경해도 다른 객체에는 영향을 미치지 않습니다.
|
||||
///</remarks>
|
||||
/// <param name="fromPool">복제된 객체가 풀에 있는지 여부를 나타냅니다. 기본값은 true입니다.</param>
|
||||
/// <returns>현재 객체의 복사본인 새 <see cref="IDataObject"/> 인스턴스를 반환합니다.</returns>
|
||||
public IDataObject Clone()
|
||||
public IDataObject Clone(bool fromPool = true)
|
||||
{
|
||||
var clone = DataObjectPool.Get();
|
||||
return Copy(fromPool);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 모든 키-값 쌍을 포함하여 현재 <see cref="DataObject"/> 인스턴스의 깊은 복사본을 생성합니다.
|
||||
/// </summary>
|
||||
/// <remarks>이 메서드는 <see cref="DataObject"/>와 그 내용의 깊은 복사본을 수행합니다.
|
||||
/// 키-값 쌍의 값이 다른 <see cref="DataObject"/> 또는 <see cref="DataArray"/>인 경우,
|
||||
/// 메서드는 해당 객체를 재귀적으로 복제합니다. 기본 유형 및 기타 복제 불가능한 값은
|
||||
/// 직접 복사됩니다.</remarks>
|
||||
/// <param name="fromPool">복제된 객체가 풀에 있는지 여부를 나타냅니다. 기본값은 true입니다.</param>
|
||||
/// <returns>현재 객체의 깊은 복사본인 새로운 <see cref="DataObject"/> 인스턴스를 반환합니다.</returns>
|
||||
public DataObject Copy(bool fromPool = true)
|
||||
{
|
||||
DataObject clone = DataObjectPool.Get();
|
||||
if(fromPool) clone = DataObjectPool.Get();
|
||||
else clone = new DataObject();
|
||||
clone.Name = Name;
|
||||
clone.IdKey = IdKey;
|
||||
|
||||
@@ -619,13 +712,13 @@ namespace UVC.Data
|
||||
object? clonedValue;
|
||||
switch (pair.Value)
|
||||
{
|
||||
// 값이 DataObject인 경우, 재귀적으로 Clone을 호출합니다.
|
||||
// 값이 DataObject인 경우, 재귀적으로 Copy을 호출합니다.
|
||||
case DataObject dataObjectValue:
|
||||
clonedValue = dataObjectValue.Clone();
|
||||
clonedValue = dataObjectValue.Copy(fromPool);
|
||||
break;
|
||||
// 값이 DataArray인 경우, 재귀적으로 Clone을 호출합니다.
|
||||
case DataArray dataArrayValue:
|
||||
clonedValue = dataArrayValue.Clone();
|
||||
clonedValue = dataArrayValue.Copy(fromPool);
|
||||
break;
|
||||
// 그 외의 경우 (primitive 타입 등)는 그대로 복사합니다.
|
||||
default:
|
||||
@@ -684,7 +777,23 @@ namespace UVC.Data
|
||||
|| (this[keyValue.Key] != null && keyValue.Value == null)
|
||||
|| (this[keyValue.Key] != null && keyValue.Value != null && !this[keyValue.Key]!.Equals(keyValue.Value)))
|
||||
{
|
||||
this[keyValue.Key] = keyValue.Value;
|
||||
//참조 타입과 값 타입 구분하여 복사
|
||||
object? valueToSet;
|
||||
switch (keyValue.Value)
|
||||
{
|
||||
// DataObject나 DataArray는 풀을 사용하지 않는 깊은 복사를 수행합니다.
|
||||
case DataObject dataObjectValue:
|
||||
valueToSet = dataObjectValue.Copy(fromPool: false);
|
||||
break;
|
||||
case DataArray dataArrayValue:
|
||||
valueToSet = dataArrayValue.Copy(fromPool: false);
|
||||
break;
|
||||
// 그 외 타입은 값을 그대로 할당합니다.
|
||||
default:
|
||||
valueToSet = keyValue.Value;
|
||||
break;
|
||||
}
|
||||
this[keyValue.Key] = valueToSet;
|
||||
changedProperies.Add(keyValue.Key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace UVC.Data
|
||||
/// obj["age"] = 30;
|
||||
///
|
||||
/// // 작업 완료 후 풀에 반환
|
||||
/// DataObjectPool.Return(obj);
|
||||
/// obj.ReturnToPool();
|
||||
///
|
||||
/// // 풀 통계 확인
|
||||
/// ULog.Debug(DataObjectPool.GetStats());
|
||||
@@ -33,27 +33,26 @@ namespace UVC.Data
|
||||
/// <summary>
|
||||
/// DataObject 인스턴스를 저장하는 스레드 안전 큐입니다.
|
||||
/// </summary>
|
||||
private static ConcurrentQueue<DataObject> dataObjectPool = new ConcurrentQueue<DataObject>();
|
||||
private static ConcurrentQueue<DataObject> pool = new ConcurrentQueue<DataObject>();
|
||||
|
||||
/// <summary>
|
||||
/// 풀의 최대 크기입니다. 이 크기를 초과하는 객체는 풀에 저장되지 않습니다.
|
||||
/// </summary>
|
||||
private static int maxPoolSize = 1000;
|
||||
private static int maxPoolSize = 4000;
|
||||
|
||||
// --- 통계용 필드 ---
|
||||
private static int _inUseCount = 0;
|
||||
private static int _peakUsage = 0;
|
||||
private static int _poolMisses = 0;
|
||||
private static int _inUseCount = 0; // 현재 사용 중인 DataObject 인스턴스의 수
|
||||
private static int _peakUsage = 0; // 최대 사용량 기록
|
||||
private static int _poolMisses = 0; // 풀에서 객체를 찾지 못하고 새로 생성한 횟수
|
||||
private static readonly object _statsLock = new object();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 풀의 최대 크기를 설정합니다.
|
||||
/// </summary>
|
||||
/// <param name="size">설정할 최대 크기</param>
|
||||
public static void SetMaxPoolSize(int size)
|
||||
static DataObjectPool()
|
||||
{
|
||||
maxPoolSize = size > 0 ? size : 1000;
|
||||
// maxPoolSize만큼의 DataObject 인스턴스를 미리 생성하여 풀에 추가합니다.
|
||||
for (int i = 0; i < maxPoolSize; i++)
|
||||
{
|
||||
pool.Enqueue(new DataObject() { IsInPool = true });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -63,7 +62,7 @@ namespace UVC.Data
|
||||
/// <returns>재사용 가능한 DataObject 인스턴스</returns>
|
||||
public static DataObject Get()
|
||||
{
|
||||
bool fromPool = dataObjectPool.TryDequeue(out var obj);
|
||||
bool fromPool = pool.TryDequeue(out var obj);
|
||||
|
||||
lock (_statsLock)
|
||||
{
|
||||
@@ -82,17 +81,16 @@ namespace UVC.Data
|
||||
{
|
||||
int oldSize = maxPoolSize;
|
||||
maxPoolSize += 1000;
|
||||
Debug.Log($"DataObjectPool size automatically increased from {oldSize} to {maxPoolSize}. Peak usage: {_peakUsage}");
|
||||
//Debug.Log($"DataObjectPool size automatically increased from {oldSize} to {maxPoolSize}. Peak usage: {_peakUsage}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_peakUsage % 100 == 0) Debug.Log($"DataObjectPool stats: {GetStats()}");
|
||||
//if (_peakUsage % 100 == 0) Debug.Log($"DataObjectPool stats: {GetStats()}");
|
||||
|
||||
if (fromPool)
|
||||
{
|
||||
obj.IsInPool = false;
|
||||
obj.Reset();
|
||||
}
|
||||
return fromPool ? obj : new DataObject();
|
||||
}
|
||||
@@ -111,11 +109,11 @@ namespace UVC.Data
|
||||
_inUseCount--;
|
||||
}
|
||||
|
||||
if (dataObjectPool.Count < maxPoolSize)
|
||||
if (pool.Count < maxPoolSize)
|
||||
{
|
||||
obj.Reset(); // 재사용 전 완벽한 초기화
|
||||
obj.IsInPool = true;
|
||||
dataObjectPool.Enqueue(obj);
|
||||
pool.Enqueue(obj);
|
||||
}
|
||||
// 풀이 가득 차면 객체는 풀에 추가되지 않고 GC 대상이 됩니다.
|
||||
}
|
||||
@@ -126,7 +124,7 @@ namespace UVC.Data
|
||||
/// <returns>풀 통계 (최대 사용량, 현재 사용량, 풀 비어있을 때 생성 횟수, 현재 풀 크기)</returns>
|
||||
public static string GetStats()
|
||||
{
|
||||
return $"Peak Usage: {_peakUsage}, In Use: {_inUseCount}, Misses: {_poolMisses}, Pooled: {dataObjectPool.Count}, Max Size: {maxPoolSize}";
|
||||
return $"최대 사용량: {_peakUsage}, 현재 사용량: {_inUseCount}, 풀 비어있을 때 생성 횟수: {_poolMisses}, 현재 풀 크기: {pool.Count}, Max Size: {maxPoolSize}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -69,7 +69,8 @@ namespace UVC.Data
|
||||
{
|
||||
if (!dataObjects.ContainsKey(key))
|
||||
{
|
||||
var newData = dataObject.Clone();
|
||||
var newData = dataObject.Clone(false);
|
||||
|
||||
dataObjects.Add(key, newData);
|
||||
dataObject.MarkAllAsUpdated();
|
||||
//UniTask.Post(() => NotifyDataUpdate(key, newData));
|
||||
|
||||
@@ -327,6 +327,10 @@ namespace UVC.Data
|
||||
mappedObject = info.DataMapper.Map(source);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mappedObject = new DataObject(result);
|
||||
}
|
||||
}
|
||||
else if (result.StartsWith("["))
|
||||
{
|
||||
@@ -403,6 +407,11 @@ namespace UVC.Data
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// DataMapper가 없는 경우, JArray를 IDataObject로 변환
|
||||
mappedObject = new DataArray(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JsonException ex)
|
||||
|
||||
@@ -41,8 +41,9 @@
|
||||
/// </summary>
|
||||
/// <remarks>복제된 객체는 원본 객체와 독립적이므로, 한 객체를 변경해도 다른 객체에는 영향을 미치지 않습니다.
|
||||
///</remarks>
|
||||
/// <param name="fromPool">객체 풀에서 복제할지 여부를 지정합니다. 기본값은 true입니다.</param>
|
||||
/// <returns>현재 객체의 복사본인 새 <see cref="IDataObject"/> 인스턴스를 반환합니다.</returns>
|
||||
public IDataObject Clone();
|
||||
public IDataObject Clone(bool fromPool = true);
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -198,6 +198,7 @@ namespace UVC.Data
|
||||
// 메시지 처리를 백그라운드 스레드에서 실행하여 메인 스레드 부하를 줄입니다.
|
||||
UniTask.RunOnThreadPool(() =>
|
||||
{
|
||||
// 토픽이 infoList와 readyHandlerList에 존재하고, 준비 상태가 true인 경우에만 처리합니다.
|
||||
if (infoList.ContainsKey(topic))
|
||||
{
|
||||
MQTTPipeLineInfo info = infoList[topic];
|
||||
@@ -211,7 +212,14 @@ namespace UVC.Data
|
||||
{
|
||||
JObject source = JObject.Parse(message);
|
||||
if (info.Validator != null && !info.Validator.IsValid(source)) return;
|
||||
if (info.DataMapper != null) mappedObject = info.DataMapper.Map(source);
|
||||
if (info.DataMapper != null)
|
||||
{
|
||||
mappedObject = info.DataMapper.Map(source);
|
||||
}
|
||||
else {
|
||||
// DataMapper가 없으면 JObject를 IDataObject로 변환
|
||||
mappedObject = new DataObject(source);
|
||||
}
|
||||
}
|
||||
else if (message.StartsWith("["))
|
||||
{
|
||||
@@ -223,7 +231,15 @@ namespace UVC.Data
|
||||
if (validSource == null || validSource.Count == 0) return;
|
||||
source = validSource;
|
||||
}
|
||||
if (info.DataMapper != null) mappedObject = info.DataMapper.Map(source);
|
||||
if (info.DataMapper != null)
|
||||
{
|
||||
mappedObject = info.DataMapper.Map(source);
|
||||
}
|
||||
else
|
||||
{
|
||||
// DataMapper가 없으면 JArray를 IDataObject로 변환
|
||||
mappedObject = new DataArray(source);
|
||||
}
|
||||
}
|
||||
|
||||
if (mappedObject == null) return;
|
||||
|
||||
@@ -1,81 +1,197 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
|
||||
using SampleProject;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UVC.Factory;
|
||||
using UVC.Core;
|
||||
using UVC.Data;
|
||||
using UVC.Extention;
|
||||
using UVC.Factory.Component;
|
||||
|
||||
namespace UVC.Factory.Alarm
|
||||
{
|
||||
public class AlarmManager : MonoBehaviour
|
||||
public class AlarmManager : SingletonScene<AlarmManager>
|
||||
{
|
||||
public static AlarmManager Instance { get; private set; }
|
||||
|
||||
[Tooltip("알람 UI 프리팹입니다. 이 프리팹은 알람 정보를 표시하는 UI 요소를 포함해야 합니다.")]
|
||||
public GameObject alarmUIPrefab; // 알람 UI 프리팹 (아래에서 설명)
|
||||
private Dictionary<string, AlarmUIController> activeAlarmUIs = new Dictionary<string, AlarmUIController>();
|
||||
|
||||
// FactoryDataManager에서 찾을 수 있도록 참조를 저장
|
||||
private FactoryObjectManager dataManager;
|
||||
private FactoryObjectManager? dataManager;
|
||||
|
||||
void Awake()
|
||||
/// <summary>
|
||||
/// AlarmManager의 초기화 메서드입니다.
|
||||
/// Awake 메서드에서 호출되며, MonoBehaviour가 생성될 때 한 번만 실행됩니다.
|
||||
/// </summary>
|
||||
protected override void Init()
|
||||
{
|
||||
Instance = this;
|
||||
SceneMain.Instance.Initialized += OnSceneInitialized;
|
||||
}
|
||||
|
||||
void Start()
|
||||
private void OnSceneInitialized()
|
||||
{
|
||||
dataManager = FactoryObjectManager.Instance;
|
||||
// 예시: FactoryDataManager의 알람 이벤트에 구독
|
||||
// dataManager.OnAlarmReceived += HandleNewAlarm;
|
||||
// dataManager.OnAlarmCleared += HandleClearedAlarm;
|
||||
}
|
||||
|
||||
public void HandleNewAlarm(AlarmData data)
|
||||
/// <summary>
|
||||
/// Alarm 데이터를 수신하기 위한 MQTT 파이프라인을 설정합니다.
|
||||
/// </summary>
|
||||
public void Run()
|
||||
{
|
||||
//데이터를 어떤 형식으로 받을지 정의합니다.
|
||||
var dataMask = new DataMask();
|
||||
dataMask.ObjectName = "Alarm"; // Alarm 객체의 이름을 설정합니다.
|
||||
dataMask.ObjectIdKey = "ID"; // Alarm의 고유 식별자로 사용할 키를 설정합니다.
|
||||
dataMask["ID"] = "";
|
||||
dataMask["ALARM_TYPE"] = "";
|
||||
dataMask["LEVEL"] = "";
|
||||
dataMask["LOGISTIC"] = "";
|
||||
dataMask["STATE"] = "";
|
||||
dataMask["MESSAGE"] = "";
|
||||
dataMask["CODE"] = "";
|
||||
dataMask["ICON"] = "";
|
||||
dataMask["MACHINENAME"] = "";
|
||||
dataMask["SHOPNAME"] = "";
|
||||
dataMask["TRANSPORT_EQP_NAME"] = "";
|
||||
dataMask["TRANSPORT_UNIT_NAME"] = "";
|
||||
dataMask["TRANSPORT_EQP_ID"] = "";
|
||||
dataMask["TRANSPORT_UNIT_ID"] = "";
|
||||
dataMask["SET_TIME"] = DateTime.Now;
|
||||
dataMask["UPDATE_TIME"] = DateTime.Now;
|
||||
dataMask["TIMESTAMP"] = DateTime.Now;
|
||||
|
||||
// MQTT 파이프라인 정보를 생성합니다.
|
||||
// 'ALARM' 토픽을 구독하고, 받은 데이터는 위에서 정의한 dataMask로 매핑하며,
|
||||
// 데이터 유효성 검사를 위해 DataValidator를 설정합니다.
|
||||
// 데이터가 업데이트되면 OnUpdateData 메서드를 호출하여 처리합니다.
|
||||
|
||||
DataValidator validator = new DataValidator();
|
||||
validator.AddValidator("MACHINENAME", value => value != null);
|
||||
|
||||
var pipelineInfo = new MQTTPipeLineInfo("ALARM")
|
||||
.setDataMapper(new DataMapper(dataMask))
|
||||
.setValidator(validator)
|
||||
.setHandler(OnUpdateData);
|
||||
|
||||
// 생성한 파이프라인 정보를 전역 MQTT 파이프라인에 추가합니다.
|
||||
AppMain.Instance.MQTTPipeLine.Add(pipelineInfo);
|
||||
}
|
||||
/// <summary>
|
||||
/// 데이터 수신 시 호출되는 공개 핸들러입니다.
|
||||
/// 수신된 ALARM 데이터 배열을 비동기적으로 처리하여 씬에 반영합니다.
|
||||
/// 추가, 제거, 수정된 ALARM 데이터를 각각 구분하여 처리합니다.
|
||||
/// </summary>
|
||||
/// <param name="data">수신된 데이터 객체 (DataArray 형태)</param>
|
||||
public void OnUpdateData(IDataObject? data)
|
||||
{
|
||||
|
||||
if (data == null) return;
|
||||
|
||||
DataArray? arr = data as DataArray;
|
||||
if (arr == null) return;
|
||||
if (arr.Count == 0)
|
||||
{
|
||||
arr.ReturnToPool();
|
||||
return;
|
||||
}
|
||||
|
||||
// 데이터 배열에서 추가, 제거, 수정된 항목 리스트를 가져옵니다.
|
||||
var AddedItems = arr.AddedItems;
|
||||
var RemovedItems = arr.RemovedItems;
|
||||
var ModifiedList = arr.ModifiedList;
|
||||
|
||||
Debug.Log($"AlarmManager OnUpdateData: Added={AddedItems.Count}, Removed={RemovedItems.Count}, Modified={ModifiedList.Count}");
|
||||
|
||||
// 새로 추가된 ALARM 처리
|
||||
foreach (var item in AddedItems.ToList())
|
||||
{
|
||||
HandleNewAlarm(item.Copy());
|
||||
}
|
||||
|
||||
// 제거된 ALARM 처리
|
||||
foreach (var item in RemovedItems.ToList())
|
||||
{
|
||||
HandleClearedAlarm(item.Copy());
|
||||
}
|
||||
|
||||
// 정보가 수정된 ALARM 처리
|
||||
foreach (var item in ModifiedList.ToList())
|
||||
{
|
||||
HandleModifyAlarm(item.Copy());
|
||||
}
|
||||
|
||||
arr.ReturnToPool();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AlarmManager가 파괴될 때 호출됩니다.
|
||||
/// MQTT 파이프라인에서 'ALARM' 핸들러를 제거하여 메모리 누수를 방지합니다.
|
||||
/// </summary>
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
AppMain.Instance.MQTTPipeLine.Remove("ALARM");
|
||||
}
|
||||
|
||||
public void HandleNewAlarm(DataObject data)
|
||||
{
|
||||
if (data.Id == null)
|
||||
{
|
||||
Debug.LogError($"New Alarm Received No data. {data}");
|
||||
data.ReturnToPool();
|
||||
return;
|
||||
}
|
||||
|
||||
// 없으면 새로 생성
|
||||
FactoryObject? targetObject = dataManager!.FindById(data.GetString("MACHINENAME")!);
|
||||
if (targetObject != null)
|
||||
{
|
||||
GameObject newUIObject = Instantiate(alarmUIPrefab, transform); // 매니저 하위에 생성
|
||||
AlarmUIController newUiController = newUIObject.GetComponent<AlarmUIController>();
|
||||
newUiController.Initialize(targetObject, data);
|
||||
|
||||
activeAlarmUIs.Add(data.Id!, newUiController);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void HandleModifyAlarm(DataObject data)
|
||||
{
|
||||
if (data.Id == null)
|
||||
{
|
||||
Debug.LogError($"Modify Alarm Received No data. {data}");
|
||||
data.ReturnToPool();
|
||||
return;
|
||||
}
|
||||
// 이미 해당 설비에 알람 UI가 떠 있는지 확인
|
||||
if (activeAlarmUIs.TryGetValue(data.objectId, out AlarmUIController uiController))
|
||||
if (activeAlarmUIs.TryGetValue(data.Id!, out AlarmUIController uiController))
|
||||
{
|
||||
// 있으면 기존 UI에 알람 정보만 추가
|
||||
uiController.AddAlarm(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 없으면 새로 생성
|
||||
FactoryObject targetObject = dataManager.FindById(data.objectId);
|
||||
if (targetObject != null)
|
||||
{
|
||||
GameObject newUIObject = Instantiate(alarmUIPrefab, transform); // 매니저 하위에 생성
|
||||
AlarmUIController newUiController = newUIObject.GetComponent<AlarmUIController>();
|
||||
newUiController.Initialize(targetObject, data);
|
||||
|
||||
activeAlarmUIs.Add(data.objectId, newUiController);
|
||||
}
|
||||
uiController.UpdateAlarm(data);
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleClearedAlarm(AlarmData data)
|
||||
public void HandleClearedAlarm(DataObject data)
|
||||
{
|
||||
if (activeAlarmUIs.TryGetValue(data.objectId, out AlarmUIController uiController))
|
||||
if (data.Id.IsNullOrEmpty())
|
||||
{
|
||||
Debug.LogError($"Clear Alarm Received No data. {data}");
|
||||
data.ReturnToPool();
|
||||
return;
|
||||
}
|
||||
if (activeAlarmUIs.TryGetValue(data.Id!, out AlarmUIController uiController))
|
||||
{
|
||||
uiController.RemoveAlarm(data);
|
||||
if (uiController.GetAlarmCount() == 0)
|
||||
{
|
||||
activeAlarmUIs.Remove(data.objectId);
|
||||
activeAlarmUIs.Remove(data.Id!);
|
||||
Destroy(uiController.gameObject);
|
||||
}
|
||||
data.ReturnToPool();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 알람 데이터 전달용 클래스
|
||||
public class AlarmData
|
||||
{
|
||||
public string objectId;
|
||||
public string alarmId; // 각 알람의 고유 ID
|
||||
public string message;
|
||||
// ... 심각도, 시간 등 기타 정보
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UVC.Data;
|
||||
using UVC.Factory.Component;
|
||||
using UVC.Util;
|
||||
|
||||
namespace UVC.Factory.Alarm
|
||||
{
|
||||
public class AlarmUIController : MonoBehaviour
|
||||
public class AlarmUIController : MonoBehaviour, IPointerClickHandler
|
||||
{
|
||||
[Tooltip("알람 클러스터 뷰입니다.")]
|
||||
[SerializeField] private GameObject clusterView;
|
||||
[Tooltip("알람 개수를 표시하는 텍스트입니다.")]
|
||||
[SerializeField] private TextMeshProUGUI alarmCountText;
|
||||
[Tooltip("확장된 알람 뷰입니다. 개별 알람 아이콘을 표시합니다.")]
|
||||
[SerializeField] private GameObject expandedView;
|
||||
[Tooltip("개별 알람 아이콘 프리팹입니다. 이 프리팹은 개별 알람 정보를 표시하는 UI 요소를 포함해야 합니다.")]
|
||||
[SerializeField] private GameObject singleAlarmIconPrefab; // 개별 알람 아이콘
|
||||
|
||||
private Transform targetObject;
|
||||
private List<AlarmData> alarms = new List<AlarmData>();
|
||||
private List<DataObject> alarms = new List<DataObject>();
|
||||
private bool isExpanded = false;
|
||||
|
||||
public void Initialize(FactoryObject target, AlarmData initialAlarm)
|
||||
public void Initialize(FactoryObject target, DataObject initialAlarm)
|
||||
{
|
||||
this.targetObject = target.transform;
|
||||
AddAlarm(initialAlarm);
|
||||
@@ -30,13 +36,32 @@ namespace UVC.Factory.Alarm
|
||||
transform.rotation = Camera.main.transform.rotation;
|
||||
}
|
||||
|
||||
public void AddAlarm(AlarmData alarm)
|
||||
public void AddAlarm(DataObject alarm)
|
||||
{
|
||||
alarms.Add(alarm);
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
public void RemoveAlarm(AlarmData alarm)
|
||||
public void UpdateAlarm(DataObject alarm)
|
||||
{
|
||||
// 실제로는 alarmId로 찾아서 업데이트해야 함
|
||||
int index = alarms.FindIndex(a => a.Id == alarm.Id);
|
||||
if (index >= 0)
|
||||
{
|
||||
foreach (var key in alarm.Keys)
|
||||
{
|
||||
alarms[index][key] = alarm[key]; // 기존 알람 데이터 업데이트
|
||||
}
|
||||
alarm.ReturnToPool();
|
||||
UpdateView();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Alarm with ID {alarm.Id} not found for update.");
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAlarm(DataObject alarm)
|
||||
{
|
||||
// 실제로는 alarmId로 찾아서 지워야 함
|
||||
alarms.Remove(alarm);
|
||||
@@ -123,5 +148,10 @@ namespace UVC.Factory.Alarm
|
||||
}
|
||||
|
||||
public int GetAlarmCount() => alarms.Count;
|
||||
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
OnPointerClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,56 @@
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UVC.Data;
|
||||
using UVC.Util;
|
||||
|
||||
namespace UVC.Factory.Alarm
|
||||
{
|
||||
public class SingleAlarmIcon : MonoBehaviour
|
||||
{
|
||||
private AlarmData myAlarmData;
|
||||
|
||||
[Tooltip("알람 내용을 표시하는 텍스트입니다.")]
|
||||
[SerializeField] private TextMeshProUGUI text;
|
||||
|
||||
private DataObject data;
|
||||
private Transform equipmentTransform;
|
||||
|
||||
public void SetData(AlarmData data, Transform equipment)
|
||||
public void SetData(DataObject newData, Transform equipment)
|
||||
{
|
||||
myAlarmData = data;
|
||||
if (data == null)
|
||||
{
|
||||
data = newData;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var keyValue in newData)
|
||||
{
|
||||
if (data.ContainsKey(keyValue.Key))
|
||||
{
|
||||
data[keyValue.Key] = keyValue.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
equipmentTransform = equipment;
|
||||
// 아이콘 모양이나 색을 알람 심각도에 따라 변경 가능
|
||||
|
||||
if (text != null)
|
||||
{
|
||||
string combinedString = string.Empty;
|
||||
foreach (var kvp in data)
|
||||
{
|
||||
// <indent> 태그를 사용하여 줄바꿈 시에도 정렬이 유지되도록 합니다.
|
||||
combinedString += $"{kvp.Key}<pos=40%><indent=40%>{kvp.Value ?? "null"}</indent>\n";
|
||||
}
|
||||
combinedString = combinedString.TrimEnd('\n'); // 마지막 줄바꿈 제거
|
||||
text.text = combinedString;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerClick()
|
||||
{
|
||||
// 클릭 시 해당 설비로 카메라 포커스
|
||||
CameraController.Instance.FocusOnTarget(equipmentTransform, 3.0f);
|
||||
Debug.Log($"알람 [{myAlarmData.message}]이 발생한 설비로 이동합니다.");
|
||||
Debug.Log($"알람 [{data.GetString("MESSAGE")}]이 발생한 설비로 이동합니다.");
|
||||
// 여기서 알람 상세정보 패널을 띄워도 좋음
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,46 +104,63 @@ namespace UVC.Factory.Component
|
||||
// 처음 데이터를 받는 경우, 받은 데이터로 즉시 위치를 설정합니다.
|
||||
if (data == null)
|
||||
{
|
||||
float x = newData.GetFloat("X") * scaleFactor;
|
||||
float y = newData.GetFloat("Y") * scaleFactor;
|
||||
Quaternion rotation = Quaternion.Euler(0, newData.GetFloat("DEGREE"), 0);
|
||||
float x = newData.GetFloat("X").Value * scaleFactor;
|
||||
float y = newData.GetFloat("Y").Value * scaleFactor;
|
||||
Quaternion rotation = Quaternion.Euler(0, newData.GetFloat("DEGREE").Value, 0);
|
||||
transform.position = new Vector3(x, 0, y);
|
||||
transform.rotation = rotation;
|
||||
}
|
||||
else // 이후 업데이트의 경우
|
||||
{
|
||||
// 새 데이터로부터 목표 위치와 회전값을 계산합니다.
|
||||
float x = data.GetFloat("X") * scaleFactor;
|
||||
float y = data.GetFloat("Y") * scaleFactor;
|
||||
Quaternion rotation = Quaternion.Euler(0, data.GetFloat("DEGREE"), 0);
|
||||
bool isTeleport = false;
|
||||
|
||||
float newX = (newData.ContainsKey("X") ? newData.GetFloat("X") : data.GetFloat("X")) * scaleFactor;
|
||||
float newY = (newData.ContainsKey("Y") ? newData.GetFloat("Y") : data.GetFloat("Y")) * scaleFactor;
|
||||
float newDegree = (newData.ContainsKey("DEGREE") ? newData.GetFloat("DEGREE") : data.GetFloat("DEGREE"));
|
||||
Quaternion newRotation = Quaternion.Euler(0, newDegree, 0);
|
||||
|
||||
Vector3 newTargetPosition = new Vector3(x, transform.position.y, y);
|
||||
Quaternion newTargetRotation = rotation;
|
||||
|
||||
if (x != newX || y != newY) newTargetPosition = new Vector3(newX, transform.position.y, newY);
|
||||
if (rotation != newRotation) newTargetRotation = newRotation;
|
||||
|
||||
// 현재 위치와 새로운 목표 위치 사이의 거리를 계산합니다.
|
||||
float distanceToTarget = Vector3.Distance(transform.position, newTargetPosition);
|
||||
|
||||
// 거리가 설정된 임계값을 초과하면, 보간을 건너뛰고 즉시 위치/회전을 설정합니다.
|
||||
if (distanceToTarget > teleportDistanceThreshold)
|
||||
float? newX = newData.GetFloat("X");
|
||||
float? newY = newData.GetFloat("Y");
|
||||
if (newX.HasValue || newY.HasValue)
|
||||
{
|
||||
transform.position = newTargetPosition;
|
||||
transform.rotation = newTargetRotation;
|
||||
float x = data.GetFloat("X").Value;
|
||||
float y = data.GetFloat("Y").Value;
|
||||
|
||||
Vector3 newTargetPosition = transform.position;
|
||||
if (newX.HasValue && x != newX) newTargetPosition.x = newX.Value * scaleFactor;
|
||||
if (newY.HasValue && y != newY) newTargetPosition.z = newY.Value * scaleFactor;
|
||||
|
||||
if (newTargetPosition != transform.position)
|
||||
{
|
||||
|
||||
// 현재 위치와 새로운 목표 위치 사이의 거리를 계산합니다.
|
||||
float distanceToTarget = Vector3.Distance(transform.position, newTargetPosition);
|
||||
|
||||
// 거리가 설정된 임계값을 초과하면, 보간을 건너뛰고 즉시 위치을 설정합니다.
|
||||
if (distanceToTarget > teleportDistanceThreshold)
|
||||
{
|
||||
transform.position = newTargetPosition;
|
||||
isTeleport = true; // 순간이동이 발생했음을 표시합니다.
|
||||
}
|
||||
|
||||
// 새로운 목표 지점을 설정합니다.
|
||||
// (순간이동을 했든 안 했든, 다음 프레임부터의 보간을 위해 목표 지점은 항상 갱신되어야 합니다.)
|
||||
this.targetPosition = newTargetPosition;
|
||||
}
|
||||
}
|
||||
|
||||
// 새로운 목표 지점을 설정합니다.
|
||||
// (순간이동을 했든 안 했든, 다음 프레임부터의 보간을 위해 목표 지점은 항상 갱신되어야 합니다.)
|
||||
this.targetPosition = newTargetPosition;
|
||||
this.targetRotation = newTargetRotation;
|
||||
float? newDegree = newData.GetFloat("DEGREE");
|
||||
if(newDegree.HasValue)
|
||||
{
|
||||
if (data.GetFloat("DEGREE").Value != newDegree.Value)
|
||||
{
|
||||
Quaternion newTargetRotation = Quaternion.Euler(0, newDegree.Value, 0);
|
||||
|
||||
// 거리가 설정된 임계값을 초과하면, 보간을 건너뛰고 즉시 위치/회전을 설정합니다
|
||||
if (isTeleport) transform.rotation = newTargetRotation;
|
||||
|
||||
// 새로운 목표 지점을 설정합니다.
|
||||
// (순간이동을 했든 안 했든, 다음 프레임부터의 보간을 위해 목표 지점은 항상 갱신되어야 합니다.)
|
||||
this.targetRotation = newTargetRotation;
|
||||
}
|
||||
}
|
||||
|
||||
newData.ReturnToPool(); // 사용이 끝난 데이터 객체를 풀에 반환합니다.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,21 @@ namespace UVC.Factory.Component
|
||||
{
|
||||
|
||||
private readonly string prefabPath = "Prefabs/SampleProject/Factory/AGV";
|
||||
private MonoBehaviourPool<AGV>? agvPool;
|
||||
private GameObjectPool<AGV>? agvPool;
|
||||
|
||||
public GameObjectPool<AGV> AGVPool
|
||||
{
|
||||
get
|
||||
{
|
||||
if (agvPool == null)
|
||||
{
|
||||
Debug.LogError("AGVPool is not initialized. Please call InitializePoolAsync first.");
|
||||
}
|
||||
return agvPool!;
|
||||
}
|
||||
}
|
||||
|
||||
private bool created = false;
|
||||
|
||||
/// <summary>
|
||||
/// AGVManager의 초기화 메서드입니다.
|
||||
@@ -150,7 +164,7 @@ namespace UVC.Factory.Component
|
||||
Debug.LogError($"Prefab not found at path: {prefabPath}");
|
||||
return;
|
||||
}
|
||||
agvPool = new MonoBehaviourPool<AGV>(prefab, transform);
|
||||
agvPool = new GameObjectPool<AGV>(prefab, transform);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -176,7 +190,7 @@ namespace UVC.Factory.Component
|
||||
var RemovedItems = arr.RemovedItems;
|
||||
var ModifiedList = arr.ModifiedList;
|
||||
|
||||
Debug.Log($"AGVManager received data: Added={AddedItems.Count}, Removed={RemovedItems.Count}, Modified={ModifiedList.Count}");
|
||||
//Debug.Log($"AGVManager received data: Added={AddedItems.Count}, Removed={RemovedItems.Count}, Modified={ModifiedList.Count}");
|
||||
|
||||
// 새로 추가된 AGV 처리
|
||||
foreach (var item in AddedItems.ToList())
|
||||
@@ -194,7 +208,7 @@ namespace UVC.Factory.Component
|
||||
"",
|
||||
item.GetString("MODE")
|
||||
);
|
||||
agv.UpdateData(item.Clone());
|
||||
agv.UpdateData(item.Copy());
|
||||
}
|
||||
|
||||
// 제거된 AGV 처리
|
||||
@@ -211,16 +225,22 @@ namespace UVC.Factory.Component
|
||||
// 정보가 수정된 AGV 처리
|
||||
foreach (var item in ModifiedList.ToList())
|
||||
{
|
||||
Debug.Log($"AGVManager modified data: {item.ToString()}");
|
||||
if(item.Id == "HFF09CNA8047") Debug.Log($"AGVManager modified data: {item.ToString()}");
|
||||
string vhlName = item.GetString("VHL_NAME")!;
|
||||
AGV? agv = agvPool.FindActiveItem(vhlName);
|
||||
if (agv != null)
|
||||
{
|
||||
agv.UpdateData(item.Clone());
|
||||
agv.UpdateData(item.Copy());
|
||||
}
|
||||
}
|
||||
|
||||
arr.ReturnToPool();
|
||||
if(created == false)
|
||||
{
|
||||
created = true;
|
||||
// 씬이 처음 초기화될 때 AGVManager가 생성되었음을 알립니다.
|
||||
SceneMain.Instance.OnAGVManagerCreated();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -110,8 +110,11 @@ namespace UVC.Factory.Component
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public abstract class FactoryObject : InteractiveObject
|
||||
public abstract class FactoryObject : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler
|
||||
{
|
||||
[Tooltip("3D 모델 객체")]
|
||||
public InteractiveObject? modelObject;
|
||||
|
||||
protected FactoryObjectInfo? info;
|
||||
|
||||
/// <summary>
|
||||
@@ -149,9 +152,30 @@ namespace UVC.Factory.Component
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnDestroy()
|
||||
protected virtual void Awake()
|
||||
{
|
||||
// 초기화 작업을 수행합니다.
|
||||
if (modelObject == null)
|
||||
{
|
||||
Debug.LogError("FactoryObject requires an InteractiveObject component.");
|
||||
}
|
||||
else
|
||||
{
|
||||
modelObject.OnPointerClickHandler += OnPointerClick;
|
||||
modelObject.OnPointerEnterHandler += OnPointerEnter;
|
||||
modelObject.OnPointerExitHandler += OnPointerExit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
if (modelObject != null)
|
||||
{
|
||||
modelObject.OnPointerClickHandler -= OnPointerClick;
|
||||
modelObject.OnPointerEnterHandler -= OnPointerEnter;
|
||||
modelObject.OnPointerExitHandler -= OnPointerExit;
|
||||
}
|
||||
FactoryObjectManager.Instance.UnregisterFactoryObject(Info!);
|
||||
}
|
||||
|
||||
@@ -165,7 +189,7 @@ namespace UVC.Factory.Component
|
||||
/// `DataOrderedMask`가 설정되어 있으면 해당 순서대로, 그렇지 않으면 모든 데이터를 표시합니다.
|
||||
/// </remarks>
|
||||
/// <param name="eventData">포인터 클릭과 관련된 이벤트 데이터입니다.</param>
|
||||
public override void OnPointerClick(PointerEventData eventData)
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (data != null && data.Count > 0)
|
||||
{
|
||||
@@ -190,18 +214,28 @@ namespace UVC.Factory.Component
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 포인터가 이 객체 위로 들어왔을 때 호출됩니다. 하이라이트 효과 등에 사용할 수 있습니다.
|
||||
/// </summary>
|
||||
/// <param name="eventData">포인터 이벤트와 관련된 데이터입니다.</param>
|
||||
public void OnPointerEnter(PointerEventData eventData) { }
|
||||
|
||||
/// <summary>
|
||||
/// 포인터가 이 객체에서 벗어났을 때 호출됩니다.
|
||||
/// </summary>
|
||||
/// <param name="eventData">포인터 이벤트와 관련된 데이터입니다.</param>
|
||||
public void OnPointerExit(PointerEventData eventData) { }
|
||||
|
||||
/// <summary>
|
||||
/// 외부로부터 받은 새로운 데이터로 객체의 상태를 업데이트합니다.
|
||||
/// 이 메서드는 내부적으로 `ProcessData`를 호출하여 실제 데이터 처리 로직을 수행합니다.
|
||||
/// MQTTPipeLineInfo.updatedDataOnly가 true인 경우, 데이터가 변경된 경우에만 호출됩니다.
|
||||
/// </summary>
|
||||
/// <param name="newData">업데이트할 새로운 데이터가 포함된 IDataObject 객체입니다.</param>
|
||||
public void UpdateData(IDataObject? newData)
|
||||
public void UpdateData(DataObject newData)
|
||||
{
|
||||
if(newData == null) return;
|
||||
DataObject? dataObject = newData as DataObject;
|
||||
if (dataObject == null || dataObject.Count == 0) return;
|
||||
ProcessData(dataObject);
|
||||
ProcessData(newData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace UVC.Factory.Component
|
||||
/// <param name="id">찾고자 하는 객체의 ID입니다.</param>
|
||||
/// <returns>처음으로 발견된 일치하는 FactoryObject. 없으면 null을 반환합니다.</returns>
|
||||
public FactoryObject? FindById(string id)
|
||||
{
|
||||
{
|
||||
foreach (var kvp in FactoryObjects)
|
||||
{
|
||||
if (kvp.Key.Id.Equals(id, StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UVC.Object3d
|
||||
@@ -14,24 +16,37 @@ namespace UVC.Object3d
|
||||
/// 3. 메인 카메라에 <see cref="PhysicsRaycaster"/> 컴포넌트가 부착되어 있어야 합니다.
|
||||
/// </remarks>
|
||||
[RequireComponent(typeof(Collider))]
|
||||
public abstract class InteractiveObject : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler
|
||||
public class InteractiveObject : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler
|
||||
{
|
||||
public Action<PointerEventData> OnPointerClickHandler;
|
||||
public Action<PointerEventData> OnPointerEnterHandler;
|
||||
public Action<PointerEventData> OnPointerExitHandler;
|
||||
|
||||
/// <summary>
|
||||
/// 포인터로 이 객체를 클릭했을 때 호출됩니다.
|
||||
/// </summary>
|
||||
/// <param name="eventData">클릭 이벤트와 관련된 데이터입니다.</param>
|
||||
public virtual void OnPointerClick(PointerEventData eventData) {}
|
||||
public virtual void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
OnPointerClickHandler?.Invoke(eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 포인터가 이 객체 위로 들어왔을 때 호출됩니다. 하이라이트 효과 등에 사용할 수 있습니다.
|
||||
/// </summary>
|
||||
/// <param name="eventData">포인터 이벤트와 관련된 데이터입니다.</param>
|
||||
public virtual void OnPointerEnter(PointerEventData eventData) {}
|
||||
public virtual void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
OnPointerEnterHandler?.Invoke(eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 포인터가 이 객체에서 벗어났을 때 호출됩니다.
|
||||
/// </summary>
|
||||
/// <param name="eventData">포인터 이벤트와 관련된 데이터입니다.</param>
|
||||
public virtual void OnPointerExit(PointerEventData eventData) {}
|
||||
public virtual void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
OnPointerExitHandler?.Invoke(eventData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@ namespace UVC.Pool
|
||||
/// {
|
||||
/// public GameObject bulletPrefab;
|
||||
/// public Transform bulletContainer;
|
||||
/// private MonoBehaviourPool<Bullet> _bulletPool;
|
||||
/// private GameObjectPool<Bulle> _bulletPool;
|
||||
///
|
||||
/// void Start()
|
||||
/// {
|
||||
/// // 총알 프리팹과 부모 컨테이너를 사용하여 풀을 초기화합니다.
|
||||
/// _bulletPool = new MonoBehaviourPool<Bullet>(bulletPrefab, bulletContainer);
|
||||
/// _bulletPool = new GameObjectPool<Bulle>(bulletPrefab, bulletContainer);
|
||||
/// }
|
||||
///
|
||||
/// void SpawnBullet()
|
||||
@@ -42,7 +42,7 @@ namespace UVC.Pool
|
||||
/// </code>
|
||||
/// </summary>
|
||||
/// <typeparam name="T">풀링할 MonoBehaviour 타입입니다.</typeparam>
|
||||
public class MonoBehaviourPool<T> where T : MonoBehaviour
|
||||
public class GameObjectPool<T> where T : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Resources 폴더에 있는 프리팹의 경로입니다.
|
||||
@@ -88,13 +88,19 @@ namespace UVC.Pool
|
||||
/// </summary>
|
||||
public Transform? RecycledItemContainer { get { return _recycledItemContainer; } }
|
||||
|
||||
// --- 통계용 필드 ---
|
||||
private int _inUseCount = 0;
|
||||
private int _peakUsage = 0;
|
||||
private int _poolMisses = 0;
|
||||
private readonly object _statsLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// GameObject 프리팹을 사용하여 풀을 초기화합니다.
|
||||
/// </summary>
|
||||
/// <param name="originalPrefab">풀링할 오브젝트의 원본 프리팹입니다.</param>
|
||||
/// <param name="activeItemContainer">활성화된 오브젝트가 위치할 부모 Transform입니다.</param>
|
||||
/// <param name="recycledItemContainer">비활성화된 오브젝트가 위치할 부모 Transform입니다. 지정하지 않으면 activeItemContainer가 사용됩니다.</param>
|
||||
public MonoBehaviourPool(GameObject originalPrefab, Transform activeItemContainer, Transform recycledItemContainer = null)
|
||||
public GameObjectPool(GameObject originalPrefab, Transform activeItemContainer, Transform recycledItemContainer = null)
|
||||
{
|
||||
_originalPrefab = originalPrefab;
|
||||
_activeItemContainer = activeItemContainer;
|
||||
@@ -109,7 +115,7 @@ namespace UVC.Pool
|
||||
/// <param name="prefabsPath">Resources 폴더 기준의 프리팹 경로입니다.</param>
|
||||
/// <param name="activeItemContainer">활성화된 오브젝트가 위치할 부모 Transform입니다.</param>
|
||||
/// <param name="recycledItemContainer">비활성화된 오브젝트가 위치할 부모 Transform입니다. 지정하지 않으면 activeItemContainer가 사용됩니다.</param>
|
||||
public MonoBehaviourPool(string prefabsPath, Transform activeItemContainer, Transform recycledItemContainer)
|
||||
public GameObjectPool(string prefabsPath, Transform activeItemContainer, Transform recycledItemContainer)
|
||||
{
|
||||
_prefabsPath = prefabsPath;
|
||||
_originalPrefab = Resources.Load<GameObject>(prefabsPath);
|
||||
@@ -133,6 +139,16 @@ namespace UVC.Pool
|
||||
}
|
||||
|
||||
T? item = null;
|
||||
|
||||
lock (_statsLock)
|
||||
{
|
||||
_inUseCount++;
|
||||
if (_inUseCount > _peakUsage)
|
||||
{
|
||||
_peakUsage = _inUseCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (_recycledItems.Count > 0)
|
||||
{
|
||||
item = _recycledItems[0];
|
||||
@@ -140,6 +156,11 @@ namespace UVC.Pool
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (_statsLock)
|
||||
{
|
||||
_poolMisses++;
|
||||
}
|
||||
|
||||
GameObject go = UnityEngine.Object.Instantiate(_originalPrefab);
|
||||
item = go.GetComponent<T>();
|
||||
}
|
||||
@@ -173,6 +194,11 @@ namespace UVC.Pool
|
||||
return; // 키에 해당하는 아이템이 없으면 반환
|
||||
}
|
||||
|
||||
lock (_statsLock)
|
||||
{
|
||||
_inUseCount--;
|
||||
}
|
||||
|
||||
_activeItems.Remove(key);
|
||||
_recycledItems.Add(item);
|
||||
|
||||
@@ -224,5 +250,26 @@ namespace UVC.Pool
|
||||
}
|
||||
_recycledItems.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 풀의 현재 성능 통계를 문자열로 반환합니다.
|
||||
/// </summary>
|
||||
/// <returns>풀 통계 (최대 사용량, 현재 사용량, 풀 비어있을 때 생성 횟수, 현재 풀 크기)</returns>
|
||||
public string GetStats()
|
||||
{
|
||||
return $"최대 사용량: {_peakUsage}, 현재 사용량: {_inUseCount}, 풀 비어있을 때 생성 횟수: {_poolMisses}, 현재 풀 크기: {_recycledItems.Count}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 풀 통계를 초기화합니다.
|
||||
/// </summary>
|
||||
public void ResetStats()
|
||||
{
|
||||
lock (_statsLock)
|
||||
{
|
||||
_peakUsage = 0;
|
||||
_poolMisses = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/UVC/Pool/GameObjectPool.cs.meta
Normal file
2
Assets/Scripts/UVC/Pool/GameObjectPool.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e163d2d37fef9bd49acd0f3fa5b5d2dc
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9be41afc37616649924d7190be6215a
|
||||
@@ -1,5 +1,6 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
@@ -19,10 +20,14 @@ namespace UVC.UI.Info
|
||||
[SerializeField]
|
||||
private TextMeshProUGUI text;
|
||||
|
||||
[Tooltip("정보 창을 닫을 버튼")]
|
||||
[Tooltip("정보 창을 닫는 버튼")]
|
||||
[SerializeField]
|
||||
private Button closeButton;
|
||||
|
||||
[Tooltip("정보 창의 내용을 클립보드에 복사할 버튼")]
|
||||
[SerializeField]
|
||||
private Button copyButton;
|
||||
|
||||
[Tooltip("UI가 객체를 가리지 않도록 할 월드 좌표계 오프셋")]
|
||||
[SerializeField]
|
||||
private Vector2 screenOffset = new Vector2(10f, 10f);
|
||||
@@ -34,6 +39,7 @@ namespace UVC.UI.Info
|
||||
// 정보 창이 따라다닐 3D 객체의 Transform
|
||||
private Transform? target;
|
||||
|
||||
private string message = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 정보 창이 현재 화면에 표시되고 있는지 여부를 반환합니다.
|
||||
@@ -54,6 +60,12 @@ namespace UVC.UI.Info
|
||||
closeButton.onClick.AddListener(Hide);
|
||||
}
|
||||
|
||||
if (copyButton != null)
|
||||
{
|
||||
copyButton.onClick.AddListener(CopyToClipboard);
|
||||
}
|
||||
|
||||
|
||||
// 처음에는 정보 창을 숨깁니다.
|
||||
if (gameObject.activeSelf)
|
||||
{
|
||||
@@ -61,6 +73,15 @@ namespace UVC.UI.Info
|
||||
}
|
||||
}
|
||||
|
||||
private void CopyToClipboard()
|
||||
{
|
||||
// 클립보드에 현재 메시지를 복사합니다.
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
GUIUtility.systemCopyBuffer = message;
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
// target이 설정되어 있고 활성화 상태일 때만 위치와 방향을 업데이트합니다.
|
||||
@@ -158,6 +179,7 @@ namespace UVC.UI.Info
|
||||
}
|
||||
combinedString = combinedString.TrimEnd('\n'); // 마지막 줄바꿈 제거
|
||||
text.text = combinedString;
|
||||
message = combinedString;
|
||||
}
|
||||
// size를 text에 맞게 조정합니다.
|
||||
RectTransform? rect = GetComponent<RectTransform>();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UVC.Data;
|
||||
using UVC.Factory.Component;
|
||||
using UVC.Locale;
|
||||
using UVC.Log;
|
||||
using UVC.UI.Commands;
|
||||
@@ -215,17 +217,12 @@ namespace UVC.UI.Menu
|
||||
new MenuItemData("file_exit", "menu_file_exit", new QuitApplicationCommand()) // 애플리케이션 종료 명령 연결
|
||||
}));
|
||||
|
||||
// "편집" 메뉴 및 하위 메뉴들 정의
|
||||
model.MenuItems.Add(new MenuItemData("edit", "menu_edit", subMenuItems: new List<MenuItemData>
|
||||
// pool 로그
|
||||
model.MenuItems.Add(new MenuItemData("log", "Log", subMenuItems: new List<MenuItemData>
|
||||
{
|
||||
new MenuItemData("edit_undo", "menu_edit_undo", new DebugLogCommand("실행 취소 선택됨 (Command 실행)")),
|
||||
new MenuItemData("edit_redo", "menu_edit_redo", new DebugLogCommand("다시 실행 선택됨 (Command 실행)")),
|
||||
MenuItemData.CreateSeparator("edit_sep1"), // 구분선
|
||||
new MenuItemData("file_save", "menu_file_save", command: new DebugLogCommand("저장 선택됨 (Command 실행)") , subMenuItems: new List<MenuItemData>
|
||||
{
|
||||
new MenuItemData("file_save_as", "menu_file_save_as", new DebugLogCommand("다른 이름으로 저장 선택됨 (Command 실행)"))
|
||||
}),
|
||||
new MenuItemData("preferences", "menu_preferences", new DebugLogCommand("환경설정 선택됨 (Command 실행)"))
|
||||
new MenuItemData("dataArray", "DataArray", new ActionCommand(() => Debug.Log($"DataArrayPool stats: {DataArrayPool.GetStats()}"))),
|
||||
new MenuItemData("dataObject", "DataObjet", new ActionCommand(() => Debug.Log($"DataObjectPool stats: {DataObjectPool.GetStats()}"))),
|
||||
new MenuItemData("agv", "AGVPool", new ActionCommand(() => Debug.Log($"AGVPool stats: {AGVManager.Instance.AGVPool.GetStats()}"))),
|
||||
}));
|
||||
model.MenuItems.Add(new MenuItemData("modal", "모달", subMenuItems: new List<MenuItemData>
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"dependencies": {
|
||||
"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask",
|
||||
"com.holyshovelsoft.opensource.log4uni": "https://github.com/HolyShovelSoft/log4uni.git#upm",
|
||||
"com.unity.2d.sprite": "1.0.0",
|
||||
"com.unity.ai.navigation": "2.0.5",
|
||||
"com.unity.collab-proxy": "2.8.2",
|
||||
"com.unity.ide.rider": "3.0.31",
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
"dependencies": {},
|
||||
"hash": "39314556b525b9a5a4ea47b7166788422d1975e1"
|
||||
},
|
||||
"com.unity.2d.sprite": {
|
||||
"version": "1.0.0",
|
||||
"depth": 0,
|
||||
"source": "builtin",
|
||||
"dependencies": {}
|
||||
},
|
||||
"com.unity.ai.navigation": {
|
||||
"version": "2.0.5",
|
||||
"depth": 0,
|
||||
|
||||
Reference in New Issue
Block a user