This commit is contained in:
CortexCore 2024-11-13 17:47:45 +08:00
parent c4af12acd7
commit 416e3322db
208 changed files with 2591757 additions and 1497 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 797 KiB

View File

@ -12,7 +12,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 80b507ad25f1af24687db7fa18d953fd, type: 3}
m_Name: Asset Cache
m_EditorClassIdentifier:
_assets: []
_assets:
- {fileID: 6597837662838677036, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
folders:
_serializedList:
- Key: Scenes

View File

@ -34,7 +34,7 @@ MonoBehaviour:
m_LODCrossFadeDitheringType: 1
m_ShEvalMode: 0
m_MainLightRenderingMode: 1
m_MainLightShadowsSupported: 1
m_MainLightShadowsSupported: 0
m_MainLightShadowmapResolution: 2048
m_AdditionalLightsRenderingMode: 1
m_AdditionalLightsPerObjectLimit: 4
@ -54,7 +54,7 @@ MonoBehaviour:
m_ShadowDepthBias: 1
m_ShadowNormalBias: 1
m_AnyShadowsSupported: 1
m_SoftShadowsSupported: 1
m_SoftShadowsSupported: 0
m_ConservativeEnclosingSphere: 1
m_NumIterationsEnclosingSphere: 64
m_SoftShadowQuality: 2
@ -82,7 +82,7 @@ MonoBehaviour:
m_Textures:
blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3}
bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3}
m_PrefilteringModeMainLightShadows: 3
m_PrefilteringModeMainLightShadows: 0
m_PrefilteringModeAdditionalLight: 3
m_PrefilteringModeAdditionalLightShadows: 0
m_PrefilterXRKeywords: 1

View File

@ -0,0 +1,22 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1ee90b8fd1e6ff14188e5fd9f8502255, type: 3}
m_Name: scriptable_weather_city_crossing_day
m_EditorClassIdentifier:
lightingDataAsset: {fileID: 112000000, guid: 25d0d5da343038347940bb2d348911de, type: 2}
sunLightDirection: {x: 59.99977, y: 237.62167, z: 0.000071716495}
sunLightColor: {r: 0.6509433, g: 0.7518754, b: 1, a: 1}
sunLightIntensity: 2
skyboxMaterial: {fileID: 2100000, guid: 302cf695b2b5abe4a9581ff5d339b6a4, type: 2}
fogMode: 2
fogColor: {r: 0.72156864, g: 0.8431373, b: 0.882353, a: 1}
fogDensity: 0.005

View File

@ -0,0 +1,22 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1ee90b8fd1e6ff14188e5fd9f8502255, type: 3}
m_Name: scriptable_weather_city_crossing_dusk
m_EditorClassIdentifier:
lightingDataAsset: {fileID: 112000000, guid: ed972938a057232409608c2878f30921, type: 2}
sunLightDirection: {x: 59.99977, y: 237.62167, z: 0.000071716495}
sunLightColor: {r: 1, g: 0.6229734, b: 0.3679244, a: 1}
sunLightIntensity: 2
skyboxMaterial: {fileID: 2100000, guid: 1a8130968946512468b2ef495b8023bd, type: 2}
fogMode: 2
fogColor: {r: 0.8941177, g: 0.7294118, b: 0.5372549, a: 1}
fogDensity: 0.005

View File

@ -0,0 +1,22 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1ee90b8fd1e6ff14188e5fd9f8502255, type: 3}
m_Name: scriptable_weather_city_crossing_night
m_EditorClassIdentifier:
lightingDataAsset: {fileID: 112000000, guid: 3a6e02d860bb96144bdb1a761b896028, type: 2}
sunLightDirection: {x: 59.99977, y: 237.62167, z: 0.000071716495}
sunLightColor: {r: 0.6509433, g: 0.7518754, b: 1, a: 1}
sunLightIntensity: 1
skyboxMaterial: {fileID: 2100000, guid: 0d904fa38bb756041b611e213cd27a20, type: 2}
fogMode: 2
fogColor: {r: 0.31446534, g: 0.31446534, b: 0.31446534, a: 1}
fogDensity: 0.005

View File

@ -1,50 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc9361f3d76a86b45a39064e46111d59, type: 3}
m_Name: Assets/Artists/Configs/scriptable_animations.asset
m_EditorClassIdentifier:
animations:
_serializedList:
- Key: animation_humanoid_step_up
Value: {fileID: 3094330708855449807, guid: 6f77ba973a5a61c4ab15ef8362a5b624, type: 3}
- Key: animation_humanoid_run
Value: {fileID: 3094330708855449807, guid: 05ab35d27bb28ad49bc9c2b098b821ae, type: 3}
- Key: animation_humanoid_idle
Value: {fileID: 3094330708855449807, guid: ebf6d636f0bdc7642bca3e831800df09, type: 3}
- Key: animation_humanoid_walk
Value: {fileID: -203655887218126122, guid: 078997c74e0171e4eb7d040bd598475c, type: 3}
- Key: animation_humanoid_crouch
Value: {fileID: -203655887218126122, guid: 078997c74e0171e4eb7d040bd598475c, type: 3}
- Key: animation_humanoid_crouch_l
Value: {fileID: -203655887218126122, guid: 078997c74e0171e4eb7d040bd598475c, type: 3}
- Key: animation_humanoid_crouch_f
Value: {fileID: -203655887218126122, guid: 078997c74e0171e4eb7d040bd598475c, type: 3}
- Key: animation_humanoid_crouch_r
Value: {fileID: -203655887218126122, guid: 078997c74e0171e4eb7d040bd598475c, type: 3}
- Key: animation_humanoid_crouch_b
Value: {fileID: -203655887218126122, guid: 078997c74e0171e4eb7d040bd598475c, type: 3}
- Key: animation_humanoid_walk_l
Value: {fileID: 3094330708855449807, guid: 53ee308983da34a4d9eae29e5b8ebcf0, type: 3}
- Key: animation_humanoid_walk_f
Value: {fileID: 3094330708855449807, guid: d18c13a5b4b923244a524a76a303e61d, type: 3}
- Key: animation_humanoid_walk_r
Value: {fileID: 3094330708855449807, guid: 1cb35aa1eecdc0a44a7574a2f50af956, type: 3}
- Key: animation_humanoid_walk_b
Value: {fileID: 3094330708855449807, guid: ea1152d3598363b4ba8e5a2aaf1b9590, type: 3}
- Key: animation_humanoid_idle_l
Value: {fileID: -203655887218126122, guid: 078997c74e0171e4eb7d040bd598475c, type: 3}
- Key: animation_humanoid_idle_f
Value: {fileID: -203655887218126122, guid: 078997c74e0171e4eb7d040bd598475c, type: 3}
- Key: animation_humanoid_idle_r
Value: {fileID: -203655887218126122, guid: 078997c74e0171e4eb7d040bd598475c, type: 3}
- Key: animation_humanoid_idle_b
Value: {fileID: -203655887218126122, guid: 078997c74e0171e4eb7d040bd598475c, type: 3}

View File

@ -0,0 +1,81 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 495d5296549fa86488795de870c7aae4, type: 3}
m_Name: scriptable_player_animations
m_EditorClassIdentifier:
idleAnimations:
_serializedList:
- Key:
x: 0
y: 0
Value: {fileID: 3094330708855449807, guid: ebf6d636f0bdc7642bca3e831800df09, type: 3}
walkAnimations:
_serializedList:
- Key:
x: 0
y: 0
Value: {fileID: 3094330708855449807, guid: ebf6d636f0bdc7642bca3e831800df09, type: 3}
- Key:
x: -1
y: 0
Value: {fileID: 3094330708855449807, guid: ff44bb82f0146a74fb98ea1824cae44a, type: 3}
- Key:
x: 0
y: 1
Value: {fileID: 3094330708855449807, guid: d18c13a5b4b923244a524a76a303e61d, type: 3}
- Key:
x: 1
y: 0
Value: {fileID: 3094330708855449807, guid: 6ae6fc1ae59ede345b4fb194814f318f, type: 3}
- Key:
x: 0
y: -1
Value: {fileID: 3094330708855449807, guid: ea1152d3598363b4ba8e5a2aaf1b9590, type: 3}
crouchAnimations:
_serializedList:
- Key:
x: 0
y: 0
Value: {fileID: 3094330708855449807, guid: aa30e50360fde394fb96e9e6c0ba8e18, type: 3}
- Key:
x: -1
y: 0
Value: {fileID: 3094330708855449807, guid: 9aaaba966ff19b94d85b861b188e3c7c, type: 3}
- Key:
x: 0
y: 1
Value: {fileID: 3094330708855449807, guid: 8bb16e2bf48f0ba498b4ee70d2518ae0, type: 3}
- Key:
x: 1
y: 0
Value: {fileID: 3094330708855449807, guid: a04e7617c7224c140bb54bc5efa749d8, type: 3}
- Key:
x: 0
y: -1
Value: {fileID: 3094330708855449807, guid: c8513a8a84992304cbf5d83a50496982, type: 3}
inAirAnimations:
_serializedList: []
runAnimations:
_serializedList:
- Key: 1
Value: {fileID: 3094330708855449807, guid: 05ab35d27bb28ad49bc9c2b098b821ae, type: 3}
knockedAnimations:
_serializedList:
- Key:
x: 0
y: 0
Value: {fileID: 3094330708855449807, guid: dc16ad01d2a511e458758c191e0184de, type: 3}
knockingAnimations:
- {fileID: 3094330708855449807, guid: 9b137246d561dc540b25d5d2e248a02e, type: 3}
deathAnimations: []
stepUpAnimations:
- {fileID: 3094330708855449807, guid: 6f77ba973a5a61c4ab15ef8362a5b624, type: 3}

View File

@ -12,4 +12,5 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: bb5e13efe9398434da88451b0b157d0a, type: 3}
m_Name: Assets/Artists/Configs/scriptable_player_settings.asset
m_EditorClassIdentifier:
sensitivity: 0.09
sensitivity: 1.81
gamepadSensitivity: 6

View File

@ -7,24 +7,19 @@ Material:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: colo_yangdun
m_Shader: {fileID: 4800000, guid: be891319084e9d147b09d89e80ce60e0, type: 3}
m_Name: color_yangdun
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _EMISSIVE_SIMPLE
- _IS_ANGELRING_OFF
- _IS_CLIPPING_TRANSMODE
- _IS_OUTLINE_CLIPPING_YES
- _OUTLINE_NML
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: 3000
m_CustomRenderQueue: -1
stringTagMap:
IgnoreProjection: true
RenderType: Transparent
RenderType: Opaque
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 95 KiB

View File

@ -178,6 +178,78 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: ac0b09e7857660247b1477e93731de29, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &4604008723045209645
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6230482868901816064}
- component: {fileID: 4521177391585727142}
m_Layer: 0
m_Name: camera_death
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!4 &6230482868901816064
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4604008723045209645}
serializedVersion: 2
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: 5012373580952327810}
m_Father: {fileID: 5409078068046653646}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &4521177391585727142
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4604008723045209645}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 45e653bab7fb20e499bda25e1b646fea, type: 3}
m_Name:
m_EditorClassIdentifier:
m_ExcludedPropertiesInInspector:
- m_Script
m_LockStageInInspector:
m_StreamingVersion: 20170927
m_Priority: 10
m_StandbyUpdate: 2
m_LookAt: {fileID: 0}
m_Follow: {fileID: 170362110020077398}
m_Lens:
FieldOfView: 75
OrthographicSize: 10
NearClipPlane: 0.1
FarClipPlane: 5000
Dutch: 0
ModeOverride: 0
LensShift: {x: 0, y: 0}
GateFit: 2
FocusDistance: 10
m_SensorSize: {x: 1, y: 1}
m_Transitions:
m_BlendHint: 0
m_InheritPosition: 0
m_OnCameraLive:
m_PersistentCalls:
m_Calls: []
m_LegacyBlendHint: 0
m_ComponentOwner: {fileID: 5012373580952327810}
--- !u!1 &4953658134000561105
GameObject:
m_ObjectHideFlags: 0
@ -250,6 +322,75 @@ MonoBehaviour:
m_Calls: []
m_LegacyBlendHint: 0
m_ComponentOwner: {fileID: 5322233708266222292}
--- !u!1 &5304755674124373434
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5012373580952327810}
- component: {fileID: 3290939858515384911}
- component: {fileID: 4824582498268447138}
m_Layer: 0
m_Name: cm
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5012373580952327810
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5304755674124373434}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -41, y: 0, z: -43}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6230482868901816064}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &3290939858515384911
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5304755674124373434}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ac0b09e7857660247b1477e93731de29, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &4824582498268447138
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5304755674124373434}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bd6043bde05a7fc4cba197d06915c1e3, type: 3}
m_Name:
m_EditorClassIdentifier:
Damping: {x: 0.1, y: 0.5, z: 0.3}
ShoulderOffset: {x: 0.5, y: -0.4, z: 0}
VerticalArmLength: 0.4
CameraSide: 1
CameraDistance: 2
CameraCollisionFilter:
serializedVersion: 2
m_Bits: 1
IgnoreTag:
CameraRadius: 0.2
DampingIntoCollision: 0
DampingFromCollision: 2
--- !u!1 &6597837662838677036
GameObject:
m_ObjectHideFlags: 0
@ -289,6 +430,7 @@ Transform:
- {fileID: 3000941450394017340}
- {fileID: 5898424397362319259}
- {fileID: 7790705391717203476}
- {fileID: 6230482868901816064}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!95 &56232337106050265
@ -408,22 +550,28 @@ MonoBehaviour:
_serializedBlackboard: '{"_variables":{"player_view":{"_value":1,"_name":"player_view","_id":"a28d2c46-f3d5-4d32-85f0-cc2c7005f888","$type":"NodeCanvas.Framework.Variable`1[[UnityEngine.Transform,
UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"},"player_model_view":{"_value":2,"_name":"player_model_view","_id":"237bea97-29a1-42f3-9620-74f6682aabe0","$type":"NodeCanvas.Framework.Variable`1[[UnityEngine.Transform,
UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"},"player_vault_point":{"_value":3,"_name":"player_vault_point","_id":"f5bf8971-aa2f-49cb-8ce7-13b1097adfc8","$type":"NodeCanvas.Framework.Variable`1[[UnityEngine.Transform,
UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"},"camera_tps":{"_value":4,"_name":"camera_tps","_id":"e3375d97-0363-4c78-b87b-5f79e26b0553","$type":"NodeCanvas.Framework.Variable`1[[Cinemachine.CinemachineVirtualCamera,
Cinemachine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"},"fps_model":{"_value":[],"_name":"fps_model","_id":"af862b3e-bf88-4482-b175-58a3a89b747c","$type":"NodeCanvas.Framework.Variable`1[[System.Collections.Generic.List`1[[UnityEngine.Renderer,
UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"},"camera_fps":{"_value":4,"_name":"camera_fps","_id":"1a00ab91-c99d-416a-ae42-016334ca51df","$type":"NodeCanvas.Framework.Variable`1[[Cinemachine.CinemachineVirtualCamera,
Cinemachine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"},"camera_tps":{"_value":5,"_name":"camera_tps","_id":"e3375d97-0363-4c78-b87b-5f79e26b0553","$type":"NodeCanvas.Framework.Variable`1[[Cinemachine.CinemachineVirtualCamera,
Cinemachine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"},"fps_model":{"_value":[],"_name":"fps_model","_id":"8312ac1f-8f40-407e-ba8c-7ff940ff0235","$type":"NodeCanvas.Framework.Variable`1[[System.Collections.Generic.List`1[[UnityEngine.Renderer,
UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]],
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"},"tps_model":{"_value":[5,6,7],"_name":"tps_model","_id":"10388b0b-9298-4c41-9931-18448abe463f","$type":"NodeCanvas.Framework.Variable`1[[System.Collections.Generic.List`1[[UnityEngine.Renderer,
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"},"tps_model":{"_value":[6,7,8],"_name":"tps_model","_id":"10388b0b-9298-4c41-9931-18448abe463f","$type":"NodeCanvas.Framework.Variable`1[[System.Collections.Generic.List`1[[UnityEngine.Renderer,
UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]],
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"},"layer_interaction":{"_value":{"value":1},"_name":"layer_interaction","_id":"0ff45185-aa6c-4b6f-9575-4f0320c975d9","$type":"NodeCanvas.Framework.Variable`1[[UnityEngine.LayerMask,
UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"},"camera_death":{"_value":9,"_name":"camera_death","_id":"c17d11ca-5a73-47c3-9b75-acca2f8a20b5","$type":"NodeCanvas.Framework.Variable`1[[Cinemachine.CinemachineVirtualCamera,
Cinemachine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"},"player_model":{"_value":10,"_name":"player_model","_id":"77510471-a7ec-4b6c-be1d-d26d3b3e8d87","$type":"NodeCanvas.Framework.Variable`1[[UnityEngine.GameObject,
UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"}}}'
_objectReferences:
- {fileID: 0}
- {fileID: 5068637431085929427}
- {fileID: 3000941450394017340}
- {fileID: 5898424397362319259}
- {fileID: 2016646090912036908}
- {fileID: 7732065237544054777}
- {fileID: 808002870831096355}
- {fileID: 6999617879734815103}
- {fileID: 8508422567226032589}
- {fileID: 4521177391585727142}
- {fileID: 2396293088462277832}
_serializedVariables:
- _json: '{"_value":1,"_name":"player_view","_id":"a28d2c46-f3d5-4d32-85f0-cc2c7005f888","$type":"NodeCanvas.Framework.Variable`1[[UnityEngine.Transform,
UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"}'
@ -440,12 +588,17 @@ MonoBehaviour:
_references:
- {fileID: 0}
- {fileID: 5898424397362319259}
- _json: '{"_value":1,"_name":"camera_fps","_id":"1a00ab91-c99d-416a-ae42-016334ca51df","$type":"NodeCanvas.Framework.Variable`1[[Cinemachine.CinemachineVirtualCamera,
Cinemachine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"}'
_references:
- {fileID: 0}
- {fileID: 2016646090912036908}
- _json: '{"_value":1,"_name":"camera_tps","_id":"e3375d97-0363-4c78-b87b-5f79e26b0553","$type":"NodeCanvas.Framework.Variable`1[[Cinemachine.CinemachineVirtualCamera,
Cinemachine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"}'
_references:
- {fileID: 0}
- {fileID: 7732065237544054777}
- _json: '{"_value":[],"_name":"fps_model","_id":"af862b3e-bf88-4482-b175-58a3a89b747c","$type":"NodeCanvas.Framework.Variable`1[[System.Collections.Generic.List`1[[UnityEngine.Renderer,
- _json: '{"_value":[],"_name":"fps_model","_id":"8312ac1f-8f40-407e-ba8c-7ff940ff0235","$type":"NodeCanvas.Framework.Variable`1[[System.Collections.Generic.List`1[[UnityEngine.Renderer,
UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]],
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}'
_references: []
@ -460,6 +613,16 @@ MonoBehaviour:
- _json: '{"_value":{"value":1},"_name":"layer_interaction","_id":"0ff45185-aa6c-4b6f-9575-4f0320c975d9","$type":"NodeCanvas.Framework.Variable`1[[UnityEngine.LayerMask,
UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"}'
_references: []
- _json: '{"_value":1,"_name":"camera_death","_id":"c17d11ca-5a73-47c3-9b75-acca2f8a20b5","$type":"NodeCanvas.Framework.Variable`1[[Cinemachine.CinemachineVirtualCamera,
Cinemachine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"}'
_references:
- {fileID: 0}
- {fileID: 4521177391585727142}
- _json: '{"_value":1,"_name":"player_model","_id":"77510471-a7ec-4b6c-be1d-d26d3b3e8d87","$type":"NodeCanvas.Framework.Variable`1[[UnityEngine.GameObject,
UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]"}'
_references:
- {fileID: 0}
- {fileID: 2396293088462277832}
--- !u!114 &2519517685296362873
MonoBehaviour:
m_ObjectHideFlags: 0
@ -670,6 +833,11 @@ SkinnedMeshRenderer:
m_CorrespondingSourceObject: {fileID: -6433774303901412422, guid: c1ca0e46d184c0945b45ad4863c3e66e, type: 3}
m_PrefabInstance: {fileID: 3278688766353060249}
m_PrefabAsset: {fileID: 0}
--- !u!1 &2396293088462277832 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: c1ca0e46d184c0945b45ad4863c3e66e, type: 3}
m_PrefabInstance: {fileID: 3278688766353060249}
m_PrefabAsset: {fileID: 0}
--- !u!4 &3029382626029131378 stripped
Transform:
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: c1ca0e46d184c0945b45ad4863c3e66e, type: 3}

View File

@ -224,7 +224,7 @@ MonoBehaviour:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1174158329}
m_Enabled: 1
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a22846b573d5c4685160aed721d514, type: 3}
m_Name:

View File

@ -122,7 +122,7 @@ NavMeshSettings:
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &91030407
--- !u!1 &322064944
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@ -130,78 +130,57 @@ GameObject:
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 91030408}
- component: {fileID: 91030411}
- component: {fileID: 91030410}
- component: {fileID: 91030409}
- component: {fileID: 322064945}
- component: {fileID: 322064948}
- component: {fileID: 322064947}
- component: {fileID: 322064946}
m_Layer: 0
m_Name: Image
m_Name: button_console
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &91030408
--- !u!224 &322064945
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 91030407}
m_GameObject: {fileID: 322064944}
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_Children:
- {fileID: 514011360}
m_Father: {fileID: 1826672789}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 228, y: 190}
m_SizeDelta: {x: 256, y: 256}
m_AnchorMin: {x: 1, y: 0}
m_AnchorMax: {x: 1, y: 0}
m_AnchoredPosition: {x: -46.73, y: 444}
m_SizeDelta: {x: 64, y: 64}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &91030409
--- !u!114 &322064946
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 91030407}
m_GameObject: {fileID: 322064944}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e9d677f1681015749b15c436eec6d880, type: 3}
m_Script: {fileID: 11500000, guid: 6d54531977ecb194c95e2d3aa7a5d72a, type: 3}
m_Name:
m_EditorClassIdentifier:
m_MovementRange: 50
m_DynamicOriginRange: 100
m_ControlPath: <Gamepad>/leftStick
m_Behaviour: 0
m_UseIsolatedInputActions: 0
m_PointerDownAction:
m_Name:
m_Type: 0
m_ExpectedControlType:
m_Id: d7b33c51-dae4-4f1b-9643-00f9a3e9855d
m_Processors:
m_Interactions:
m_SingletonActionBindings: []
m_Flags: 0
m_PointerMoveAction:
m_Name:
m_Type: 0
m_ExpectedControlType:
m_Id: a38cce37-ecd3-4ecf-bfdc-946c7004aae8
m_Processors:
m_Interactions:
m_SingletonActionBindings: []
m_Flags: 0
--- !u!114 &91030410
m_ControlPath: <Keyboard>/backquote
--- !u!114 &322064947
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 91030407}
m_GameObject: {fileID: 322064944}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
@ -225,13 +204,13 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &91030411
--- !u!222 &322064948
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 91030407}
m_GameObject: {fileID: 322064944}
m_CullTransparentMesh: 1
--- !u!1 &435750794
GameObject:
@ -246,7 +225,7 @@ GameObject:
- component: {fileID: 435750797}
- component: {fileID: 435750796}
m_Layer: 0
m_Name: Image (4)
m_Name: button_toggleView
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@ -263,12 +242,13 @@ RectTransform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Children:
- {fileID: 1292158265}
m_Father: {fileID: 1826672789}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0}
m_AnchorMax: {x: 1, y: 0}
m_AnchoredPosition: {x: -180, y: 439}
m_AnchoredPosition: {x: -110, y: 204}
m_SizeDelta: {x: 64, y: 64}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &435750796
@ -322,6 +302,156 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 435750794}
m_CullTransparentMesh: 1
--- !u!1 &514011359
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 514011360}
- component: {fileID: 514011362}
- component: {fileID: 514011361}
m_Layer: 0
m_Name: Image (2)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &514011360
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 514011359}
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: 322064945}
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: -24, y: -24}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &514011361
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 514011359}
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: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 936d4e7e4eff78f4d9d62601cbef1818, type: 3}
m_Type: 0
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!222 &514011362
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 514011359}
m_CullTransparentMesh: 1
--- !u!1 &526170913
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 526170914}
- component: {fileID: 526170916}
- component: {fileID: 526170915}
m_Layer: 0
m_Name: Image (2)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &526170914
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 526170913}
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: 1876037496}
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: -24, y: -24}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &526170915
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 526170913}
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: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: f75638302ccf8ba41acbf96be794e86d, type: 3}
m_Type: 0
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!222 &526170916
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 526170913}
m_CullTransparentMesh: 1
--- !u!1 &538493207
GameObject:
m_ObjectHideFlags: 0
@ -491,7 +621,7 @@ MonoBehaviour:
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 10
--- !u!1 &1445691558
--- !u!1 &1292158264
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@ -499,10 +629,84 @@ GameObject:
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1445691559}
- component: {fileID: 1445691562}
- component: {fileID: 1445691561}
- component: {fileID: 1445691560}
- component: {fileID: 1292158265}
- component: {fileID: 1292158267}
- component: {fileID: 1292158266}
m_Layer: 0
m_Name: Image
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1292158265
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1292158264}
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: 435750795}
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: -32, y: -32}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1292158266
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1292158264}
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: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 3e1e9a9b6a5fcd846b968c314a55da8b, type: 3}
m_Type: 0
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!222 &1292158267
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1292158264}
m_CullTransparentMesh: 1
--- !u!1 &1333630871
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1333630872}
- component: {fileID: 1333630874}
- component: {fileID: 1333630873}
m_Layer: 0
m_Name: Image (1)
m_TagString: Untagged
@ -510,67 +714,122 @@ GameObject:
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1445691559
--- !u!224 &1333630872
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1445691558}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_GameObject: {fileID: 1333630871}
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: 2042865998}
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: -32, y: -32}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1333630873
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1333630871}
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: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: ba14ff41fff179940a74b985f742b85e, type: 3}
m_Type: 0
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!222 &1333630874
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1333630871}
m_CullTransparentMesh: 1
--- !u!1 &1432788300
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1432788301}
- component: {fileID: 1432788304}
- component: {fileID: 1432788303}
- component: {fileID: 1432788302}
m_Layer: 0
m_Name: button_run
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1432788301
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1432788300}
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: 1750435635}
m_Father: {fileID: 1826672789}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0}
m_AnchorMax: {x: 1, y: 0}
m_AnchoredPosition: {x: -244, y: 190}
m_SizeDelta: {x: 256, y: 256}
m_AnchoredPosition: {x: -110.73, y: 68}
m_SizeDelta: {x: 64, y: 64}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1445691560
--- !u!114 &1432788302
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1445691558}
m_GameObject: {fileID: 1432788300}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e9d677f1681015749b15c436eec6d880, type: 3}
m_Script: {fileID: 11500000, guid: 6d54531977ecb194c95e2d3aa7a5d72a, type: 3}
m_Name:
m_EditorClassIdentifier:
m_MovementRange: 50
m_DynamicOriginRange: 100
m_ControlPath: <Gamepad>/rightStick
m_Behaviour: 0
m_UseIsolatedInputActions: 0
m_PointerDownAction:
m_Name:
m_Type: 0
m_ExpectedControlType:
m_Id: 64e6a4ff-5f89-444c-819a-73c4d33d1157
m_Processors:
m_Interactions:
m_SingletonActionBindings: []
m_Flags: 0
m_PointerMoveAction:
m_Name:
m_Type: 0
m_ExpectedControlType:
m_Id: 370cbcf9-a31d-4617-b2f7-8d713d388a68
m_Processors:
m_Interactions:
m_SingletonActionBindings: []
m_Flags: 0
--- !u!114 &1445691561
m_ControlPath: <Keyboard>/leftShift
--- !u!114 &1432788303
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1445691558}
m_GameObject: {fileID: 1432788300}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
@ -594,13 +853,199 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &1445691562
--- !u!222 &1432788304
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1445691558}
m_GameObject: {fileID: 1432788300}
m_CullTransparentMesh: 1
--- !u!1 &1630997671
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1630997672}
- component: {fileID: 1630997674}
- component: {fileID: 1630997673}
- component: {fileID: 1630997675}
m_Layer: 0
m_Name: joystick_movement
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1630997672
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1630997671}
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: 1826672789}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 384, y: 0}
m_Pivot: {x: 0, y: 0.5}
--- !u!114 &1630997673
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1630997671}
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: 0}
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: 0}
m_Type: 0
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!222 &1630997674
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1630997671}
m_CullTransparentMesh: 1
--- !u!114 &1630997675
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1630997671}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e9d677f1681015749b15c436eec6d880, type: 3}
m_Name:
m_EditorClassIdentifier:
m_MovementRange: 50
m_DynamicOriginRange: 100
m_ControlPath: <Gamepad>/leftStick
m_Behaviour: 0
m_UseIsolatedInputActions: 0
m_PointerDownAction:
m_Name:
m_Type: 0
m_ExpectedControlType:
m_Id: 6c601e9e-57bf-4dc1-a122-7df342ca287a
m_Processors:
m_Interactions:
m_SingletonActionBindings: []
m_Flags: 0
m_PointerMoveAction:
m_Name:
m_Type: 0
m_ExpectedControlType:
m_Id: f3bf22d7-e520-439b-bc16-a053007a2234
m_Processors:
m_Interactions:
m_SingletonActionBindings: []
m_Flags: 0
--- !u!1 &1750435634
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1750435635}
- component: {fileID: 1750435637}
- component: {fileID: 1750435636}
m_Layer: 0
m_Name: Image (2)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1750435635
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1750435634}
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: 1432788301}
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: -24, y: -24}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1750435636
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1750435634}
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: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 20c29de72b51c9344b5fef47e6472693, type: 3}
m_Type: 0
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!222 &1750435637
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1750435634}
m_CullTransparentMesh: 1
--- !u!1 &1826672788
GameObject:
@ -633,9 +1078,10 @@ RectTransform:
m_LocalScale: {x: 0, y: 0, z: 0}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 91030408}
- {fileID: 1445691559}
- {fileID: 1630997672}
- {fileID: 1876037496}
- {fileID: 1432788301}
- {fileID: 322064945}
- {fileID: 2042865998}
- {fileID: 435750795}
m_Father: {fileID: 538493212}
@ -674,10 +1120,10 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier:
m_UiScaleMode: 0
m_UiScaleMode: 1
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 800, y: 600}
m_ReferenceResolution: {x: 917, y: 412}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 3
@ -721,7 +1167,7 @@ GameObject:
- component: {fileID: 1876037498}
- component: {fileID: 1876037497}
m_Layer: 0
m_Name: Image (2)
m_Name: button_jump
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@ -738,12 +1184,13 @@ RectTransform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Children:
- {fileID: 526170914}
m_Father: {fileID: 1826672789}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0}
m_AnchorMax: {x: 1, y: 0}
m_AnchoredPosition: {x: -524, y: 85}
m_AnchoredPosition: {x: -256, y: 68}
m_SizeDelta: {x: 64, y: 64}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1876037497
@ -810,7 +1257,7 @@ GameObject:
- component: {fileID: 2042866000}
- component: {fileID: 2042865999}
m_Layer: 0
m_Name: Image (3)
m_Name: button_interactive
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@ -827,12 +1274,13 @@ RectTransform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Children:
- {fileID: 1333630872}
m_Father: {fileID: 1826672789}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0}
m_AnchorMax: {x: 1, y: 0}
m_AnchoredPosition: {x: -308, y: 439}
m_AnchoredPosition: {x: -214, y: 204}
m_SizeDelta: {x: 64, y: 64}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &2042865999

View File

@ -3,7 +3,9 @@ using System.Collections;
using System.Collections.Generic;
using System.Threading;
using BITKit;
using BITKit.Console;
using BITKit.Mod;
using BITKit.Pool;
using BITKit.UX;
using BITKit.WorldNode;
using Cysharp.Threading.Tasks;
@ -14,6 +16,7 @@ using Microsoft.Extensions.Hosting.Unity;
using Microsoft.Extensions.Logging;
using Net.Like.Xue.Tokyo.GameService;
using Net.Like.Xue.Tokyo.UX;
using Net.Project.B.Health;
using Net.Project.B.Interaction;
using Net.Project.B.WorldNode;
using Project.B.Animation;
@ -51,12 +54,21 @@ namespace Net.Like.Xue.Tokyo
//玩家角色控制器服务
serviceCollection.AddSingleton<ICharacterService, CharacterService>();
//玩家生命值
serviceCollection.AddSingleton<IHealthService, HealthService>();
//对象池
serviceCollection.AddSingleton<IPoolService, UnityPoolService>();
//击倒服务
serviceCollection.AddSingleton<IKnockedService, KnockedService>();
var scriptablePlayerAnimation =await
ModService.LoadAsset<ScriptablePlayerAnimationFactory>("scriptable_player_animations");
//玩家动画
serviceCollection.AddSingleton<IPlayerAnimationFactory, PlayerAnimationFactory>();
serviceCollection.AddSingleton<IPlayerAnimationFactory>(scriptablePlayerAnimation);
//注册实体工厂
serviceCollection.AddProjectBEntitiesFactory();
serviceCollection.AddSingleton<IPlayerFactory, YangdunCreateFactory>();
//注册地图服务
serviceCollection.AddSingleton<IGameMapService, GameMapService>();
@ -93,6 +105,7 @@ namespace Net.Like.Xue.Tokyo
serviceCollection.AddSingleton<UXMap>();
serviceCollection.AddSingleton<UXLoadingMap>();
serviceCollection.AddSingleton<UXMenu>();
serviceCollection.AddSingleton<UXConsole>();
//生成玩家
serviceCollection.AddSingleton<GameSpawnPlayerService>();
@ -141,7 +154,9 @@ namespace Net.Like.Xue.Tokyo
//初始化场景高亮
serviceProvider.GetRequiredService<WorldHighlightService>();
Application.targetFrameRate = 60;
serviceProvider.GetRequiredService<UXConsole>();
Application.targetFrameRate = 90;
await destroyCancellationToken.WaitUntilCanceled();
}

View File

@ -93,7 +93,7 @@ namespace Net.Like.Xue.Tokyo.UX
var point = _minimapCamera.WorldToViewportPoint(_mainCamera.transform.position);
_miniPlayer.style.left = _minimapContainer.layout.width * point.x - _miniPlayer.layout.width / 2;
_miniPlayer.style.top = _minimapContainer.layout.height * point.y - _miniPlayer.layout.height / 2;
_miniPlayer.style.top = _minimapContainer.layout.height * (1-point.y) - _miniPlayer.layout.height / 2;
}
}

View File

@ -41,7 +41,7 @@ namespace Net.Like.Xue.Tokyo.UX
var point = _minimapCamera.WorldToViewportPoint(_mainCamera.transform.position);
_miniPlayer.style.left = _minimapContainer.layout.width * point.x - _miniPlayer.layout.width / 2;
_miniPlayer.style.top = _minimapContainer.layout.height * point.y - _miniPlayer.layout.height / 2;
_miniPlayer.style.top = _minimapContainer.layout.height * (1-point.y) - _miniPlayer.layout.height / 2;
}
}

View File

@ -0,0 +1,16 @@
{
"name": "Net.Like.Xue.Tokyo.Weather.Unity",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,62 @@
using System.Collections;
using System.Collections.Generic;
using BITKit;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Net.Like.Xue.Tokyo.Weather
{
public class ScriptableWeather : ScriptableObject
{
#if UNITY_EDITOR
[SerializeField] private LightingDataAsset lightingDataAsset;
#endif
[SerializeField] private Vector3 sunLightDirection = new Vector3(0, 1, 0);
[SerializeField] private Color sunLightColor;
[SerializeField] private float sunLightIntensity = 1;
[SerializeField] private Material skyboxMaterial;
[SerializeField] private FogMode fogMode;
[SerializeField] private Color fogColor;
[SerializeField] private float fogDensity;
[BIT]
public void Save()
{
#if UNITY_EDITOR
lightingDataAsset = Lightmapping.lightingDataAsset;
#endif
sunLightDirection = RenderSettings.sun.transform.eulerAngles;
sunLightIntensity = RenderSettings.sun.intensity;
sunLightColor = RenderSettings.sun.color;
skyboxMaterial = RenderSettings.skybox;
fogMode = RenderSettings.fogMode;
fogColor = RenderSettings.fogColor;
fogDensity = RenderSettings.fogDensity;
#if UNITY_EDITOR
EditorUtility.SetDirty(this);
#endif
}
[BIT]
public void Load()
{
#if UNITY_EDITOR
Lightmapping.lightingDataAsset = lightingDataAsset;
#endif
RenderSettings.sun.transform.eulerAngles = sunLightDirection;
RenderSettings.sun.intensity = sunLightIntensity;
RenderSettings.skybox = skyboxMaterial;
RenderSettings.fogMode = fogMode;
RenderSettings.fogColor = fogColor;
RenderSettings.fogDensity = fogDensity;
}
}
}

View File

@ -0,0 +1,38 @@
using System;
using System.Collections;
using System.Collections.Generic;
using MeshCombineStudio;
using NGS.AdvancedCullingSystem.Dynamic;
using UnityEngine;
namespace Net.Like.Xue.Tokyo
{
public class WorldOptimizeService : MonoBehaviour
{
[SerializeField] private Transform[] sources;
[SerializeField] private Camera minimapCamera;
private void Awake()
{
GetComponent<MeshCombiner>().onCombiningReady += OnReady;
}
private void OnReady(MeshCombiner meshcombiner)
{
minimapCamera.Render();
minimapCamera.enabled = false;
var controller = gameObject.AddComponent<DC_Controller>();
controller.AddCamera(Camera.main,3000);
foreach (var x in sources)
{
foreach (var renderer in x.GetComponentsInChildren<MeshRenderer>())
{
if (renderer.gameObject.activeInHierarchy)
controller.AddObjectForCulling(renderer);
}
}
}
}
}

View File

@ -0,0 +1,174 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Animancer;
using BITKit;
using BITKit.Entities;
using BITKit.GameSocket;
using BITKit.WorldNode;
using Cinemachine;
using Cysharp.Threading.Tasks;
using Lightbug.CharacterControllerPro.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Net.Project.B.Health;
using Net.Project.B.Interaction;
using Net.Project.B.Inventory;
using Net.Project.B.Weapon;
using NodeCanvas.Framework;
using Project.B.Animation;
using Project.B.CharacterController;
using Project.B.Entities;
using UnityEngine;
using YooAsset;
using Object = UnityEngine.Object;
namespace Net.Like.Xue.Tokyo
{
public class YangdunCreateFactory : IPlayerFactory
{
private readonly ILogger<PlayerFactory> _logger;
private readonly IServiceCollection _serviceCollection;
private readonly IServiceProvider _serviceProvider;
private readonly IWorldNodeService _worldNodeService;
private const string PlayerPath = "Player_Base";
private readonly List<(IEntity entity,GameObject go)> _entities = new();
private readonly IHealthService _healthService;
private GameObject _playerPrefab;
private readonly InputActionGroup _inputActionGroup=new();
private UniTaskCompletionSource<WorldInfoPlayerStart> _waitPlayerStart=new();
public YangdunCreateFactory(IServiceProvider serviceProvider, IServiceCollection serviceCollection, IWorldNodeService worldNodeService, ILogger<PlayerFactory> logger, IHealthService healthService)
{
_serviceProvider = serviceProvider;
_serviceCollection = serviceCollection;
_worldNodeService = worldNodeService;
_logger = logger;
_healthService = healthService;
_worldNodeService.OnNodeRegistered += OnNodeRegistered;
_healthService.OnHealthChanged+=OnHealthChanged;
}
private void OnNodeRegistered(IWorldNode obj)
{
if(obj is not WorldInfoPlayerStart infoPlayerStart)return;
_waitPlayerStart.TrySetResult(infoPlayerStart);
}
public async UniTask<IEntity> CreateAsync(string addressablePath)
{
await UniTask.SwitchToMainThread();
if (_playerPrefab is not null)
{
return await Create(addressablePath);
}
var asyncHandle = YooAssets.LoadAssetAsync<GameObject>(PlayerPath);
await asyncHandle;
_playerPrefab = asyncHandle.AssetObject as GameObject;
return await Create(addressablePath);
}
public event Func<string, IEntity,UniTask> OnEntityCreate;
public event Func<string, IEntity,UniTask> OnEntityCreated;
private async UniTask<IEntity> Create(string addressablePath = null)
{
var entity = new Entity();
var startNode = await _waitPlayerStart.Task;
var startTransform = startNode.WorldObject.As<GameObject>().transform;
_waitPlayerStart = new();
var go = Object.Instantiate(_playerPrefab,startTransform.position,startTransform.rotation);
entity.ServiceCollection.Add(_serviceCollection);
go.GetCancellationTokenOnDestroy().Register(entity.Dispose);
entity.ServiceCollection.AddSingleton<IEntity>(entity);
entity.ServiceCollection.AddSingleton(go);
entity.ServiceCollection.AddSingleton(go.transform);
entity.ServiceCollection.AddSingleton(go.GetComponent<IBlackboard>());
entity.ServiceCollection.AddSingleton(go.GetComponent<CharacterActor>());
entity.ServiceCollection.AddSingleton(go.GetComponentInChildren<CinemachineVirtualCameraBase>());
entity.ServiceCollection.AddSingleton<IAnimancerComponent>(go.GetComponent<AnimancerComponent>());
entity.ServiceCollection.AddSingleton<IPlayerCharacterController, PlayerCharacterController>();
entity.ServiceCollection.AddSingleton<ICharacterController>(x=>x.GetRequiredService<IPlayerCharacterController>().CharacterController);
entity.ServiceCollection.AddSingleton(_inputActionGroup);
entity.ServiceCollection.AddSingleton<ICharacterStateWalk, CharacterWalkState>();
entity.ServiceCollection.AddSingleton<ICharacterStateIdle, CharacterIdleState>();
entity.ServiceCollection.AddSingleton<ICharacterStateCrouched, CharacterCrouchedState>();
entity.ServiceCollection.AddSingleton<ICharacterStateRun, CharacterRunState>();
entity.ServiceCollection.AddSingleton<ICharacterSprint, CharacterSprintState>();
entity.ServiceCollection.AddSingleton<ICharacterStateStepUp, CharacterStepUpState>();
entity.ServiceCollection.AddSingleton<ICharacterKnocked, CharacterKnockedState>();
entity.ServiceCollection.AddSingleton<PlayerCameraController>();
entity.ServiceCollection.AddSingleton<PlayerModelController>();
entity.ServiceCollection.AddSingleton<PlayerAnimancerController>();
entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService<IWorldInteractionService>());
entity.ServiceCollection.AddSingleton<PlayerInteractionController>();
await OnEntityCreate.UniTaskFunc(addressablePath,entity);
entity.ServiceProvider.GetRequiredService<ICharacterStateWalk>();
entity.ServiceProvider.GetRequiredService<PlayerInteractionController>();
var characterController = entity.ServiceProvider.GetRequiredService<ICharacterController>();
characterController.TransitionState<ICharacterStateWalk>();
entity.ServiceProvider.GetRequiredService<PlayerAnimancerController>();
entity.ServiceProvider.GetRequiredService<PlayerCameraController>();
entity.ServiceProvider.GetRequiredService<PlayerModelController>();
await OnEntityCreated.UniTaskFunc(addressablePath,entity);
_entities.Add(new ValueTuple<IEntity, GameObject>(entity,go));
_logger.LogInformation($"Player Created. {entity.Id}");
return entity;
}
public async void Dispose()
{
await UniTask.SwitchToMainThread();
foreach (var (entity, go) in _entities)
{
if (entity is IDisposable disposable)
{
disposable.Dispose();
}
if (go)
Object.Destroy(go);
}
_healthService.OnHealthChanged-=OnHealthChanged;
}
private void OnHealthChanged(int arg1, int arg2, int arg3, object arg4)
{
_inputActionGroup.allowInput.SetDisableElements(this,arg3<0);
}
}
}

View File

@ -20,3 +20,9 @@
flex-grow: 1;
transition-duration: 0.2s;
}
.level-button:focus {
-unity-background-image-tint-color: rgb(255, 255, 255);
flex-grow: 1;
transition-duration: 0.2s;
}

View File

@ -0,0 +1,4 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:Template name="BITConsole" src="project://database/Assets/BITKit/Unity/UX/BITConsole.uxml?fileID=9197481963319205126&amp;guid=b42b9a148466f1f41a27bfc482972943&amp;type=3#BITConsole" />
<ui:Instance template="BITConsole" name="BITConsole" picking-mode="Ignore" style="flex-grow: 1;" />
</ui:UXML>

View File

@ -6,4 +6,12 @@
</ui:VisualElement>
</ui:VisualElement>
<ui:Label tabindex="-1" text="互动" parse-escape-sequences="true" display-tooltip-when-elided="true" name="interaction-tips" class="flex-center tl" style="top: 32px; background-color: rgba(0, 0, 0, 0.78); padding-top: 4px; padding-right: 8px; padding-bottom: 4px; padding-left: 8px;" />
<ui:VisualElement picking-mode="Ignore" class="root">
<ui:VisualElement style="margin-top: auto; margin-right: auto; margin-bottom: 16px; margin-left: auto; flex-direction: row; align-items: center; background-color: rgba(0, 0, 0, 0.78); width: 256px;">
<ui:VisualElement style="width: 64px; height: 64px; background-image: url(&quot;project://database/Assets/Artists/Arts/Avatars/avatar_player.jpg?fileID=2800000&amp;guid=dc1a7b7a5cc9437438280932e8b541a0&amp;type=3#avatar_player&quot;);" />
<ui:VisualElement style="flex-grow: 1; margin-top: 5px; margin-right: 5px; margin-bottom: 5px; margin-left: 5px;">
<ui:Label tabindex="-1" text="羊顿爵士" parse-escape-sequences="true" display-tooltip-when-elided="true" class="tl" style="flex-grow: 1;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>

View File

@ -2,7 +2,7 @@
<Style src="project://database/Assets/BITKit/Unity/UX/Common/Common.uss?fileID=7433441132597879392&amp;guid=a3a69d3518fd02b489e721f3c5b0b539&amp;type=3#Common" />
<ui:VisualElement class="root" style="background-image: url(&quot;project://database/Assets/Artists/Arts/Backgrounds/background_menu.jpg?fileID=21300000&amp;guid=5abe2ac5974a6104fbf483cf5f3f19eb&amp;type=3#background_menu&quot;); background-color: rgb(0, 0, 0); -unity-background-image-tint-color: rgba(255, 255, 255, 0.32);" />
<ui:VisualElement class="flex-center" style="min-width: 256px;">
<ui:ProgressBar value="48.2" name="load-progress" style="background-color: rgba(255, 255, 255, 0.21);" />
<ui:ProgressBar value="48.2" name="load-progress" style="background-color: rgba(255, 255, 255, 0.21); height: 4px; width: 512px;" />
<ui:VisualElement style="flex-direction: row; justify-content: space-between;">
<ui:Label tabindex="-1" text="map_tokyo" parse-escape-sequences="true" display-tooltip-when-elided="true" name="map-label" class="tl" />
<ui:Label tabindex="-1" text="加载中..." parse-escape-sequences="true" display-tooltip-when-elided="true" name="load_step-label" />

View File

@ -1,12 +1,12 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<Style src="project://database/Assets/BITKit/Unity/UX/Common/Common.uss?fileID=7433441132597879392&amp;guid=a3a69d3518fd02b489e721f3c5b0b539&amp;type=3#Common" />
<Style src="project://database/Assets/Artists/UX/Style.uss?fileID=7433441132597879392&amp;guid=506d41b7c5d56a44bb5845e69055a5eb&amp;type=3#Style" />
<ui:VisualElement class="root" style="background-image: url(&quot;project://database/Assets/Artists/Arts/Backgrounds/background_menu.jpg?fileID=21300000&amp;guid=5abe2ac5974a6104fbf483cf5f3f19eb&amp;type=3#background_menu&quot;); -unity-background-scale-mode: scale-and-crop; background-color: rgb(255, 255, 255); -unity-background-image-tint-color: rgba(255, 255, 255, 0.51);" />
<ui:VisualElement class="root" style="background-image: url(&quot;project://database/Assets/Artists/Arts/Backgrounds/background_menu.jpg?fileID=21300000&amp;guid=5abe2ac5974a6104fbf483cf5f3f19eb&amp;type=3#background_menu&quot;); -unity-background-scale-mode: scale-and-crop; background-color: rgb(0, 0, 0); -unity-background-image-tint-color: rgba(255, 255, 255, 0.35);" />
<ui:VisualElement name="level-container" style="flex-direction: row; flex-grow: 1;">
<ui:Button view-data-key="map_city_crossing" class="level-button" style="background-image: url(&quot;project://database/Assets/Artists/Arts/Textures/texture_akiba.jpg?fileID=21300000&amp;guid=4f4c68ed2c65cee4d98fa5dc45e00c8b&amp;type=3#texture_akiba&quot;);" />
<ui:Button view-data-key="map_suburbs" class="level-button" style="background-image: url(&quot;project://database/Assets/Artists/Arts/Textures/texture_suburb.jpg?fileID=21300000&amp;guid=8de2e8ea76d2fbb4f946bfb49bab55fd&amp;type=3#texture_suburb&quot;);" />
<ui:Button view-data-key="map_street" class="level-button" style="background-image: url(&quot;project://database/Assets/Artists/Arts/Textures/texture_street.jpg?fileID=21300000&amp;guid=4b7dac409ae6a5849b3088d55792c00b&amp;type=3#texture_street&quot;);" />
<ui:VisualElement style="flex-grow: 1; background-color: rgb(22, 22, 22);">
<ui:VisualElement style="flex-grow: 1;">
<ui:VisualElement class="flex-center">
<ui:Label tabindex="-1" text="立课学日语" parse-escape-sequences="true" display-tooltip-when-elided="true" class="tl" />
<ui:Label tabindex="-1" text="选择入口" parse-escape-sequences="true" display-tooltip-when-elided="true" />

View File

@ -15,7 +15,7 @@ RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 9
m_Fog: 1
m_FogColor: {r: 0.8941177, g: 0.7294118, b: 0.5372549, a: 1}
m_FogColor: {r: 0.72156864, g: 0.8431373, b: 0.882353, a: 1}
m_FogMode: 2
m_FogDensity: 0.005
m_LinearFogStart: 19.92
@ -26,7 +26,7 @@ RenderSettings:
m_AmbientIntensity: 1
m_AmbientMode: 0
m_SubtractiveShadowColor: {r: 0.80817604, g: 0.84014666, b: 1, a: 1}
m_SkyboxMaterial: {fileID: 2100000, guid: 1a8130968946512468b2ef495b8023bd, type: 2}
m_SkyboxMaterial: {fileID: 2100000, guid: 302cf695b2b5abe4a9581ff5d339b6a4, type: 2}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
@ -96,7 +96,7 @@ LightmapSettings:
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 112000000, guid: ed972938a057232409608c2878f30921, type: 2}
m_LightingDataAsset: {fileID: 112000000, guid: 25d0d5da343038347940bb2d348911de, type: 2}
m_LightingSettings: {fileID: 4890085278179872738, guid: b8bda31b0c64cfd418e764aff2484d6e, type: 2}
--- !u!196 &4
NavMeshSettings:
@ -1583,6 +1583,171 @@ GameObject:
m_CorrespondingSourceObject: {fileID: 1692580468371725842, guid: 621396ca03792684e8df9485b8d4d46d, type: 3}
m_PrefabInstance: {fileID: 28178367}
m_PrefabAsset: {fileID: 0}
--- !u!43 &32445914
Mesh:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: pb_Mesh-95304(Clone)(Clone)(Clone)(Clone)(Clone)(Clone)(Clone)
serializedVersion: 11
m_SubMeshes:
- serializedVersion: 2
firstByte: 0
indexCount: 6
topology: 0
baseVertex: 0
firstVertex: 0
vertexCount: 4
localAABB:
m_Center: {x: -3.8750002, y: 3.5, z: -4.0856207e-13}
m_Extent: {x: 3.8750002, y: 3.5, z: 4.0856207e-13}
m_Shapes:
vertices: []
shapes: []
channels: []
fullWeights: []
m_BindPose: []
m_BoneNameHashes:
m_RootBoneNameHash: 0
m_BonesAABB: []
m_VariableBoneCountWeights:
m_Data:
m_MeshCompression: 0
m_IsReadable: 1
m_KeepVertices: 1
m_KeepIndices: 1
m_IndexFormat: 0
m_IndexBuffer: 000001000200010003000200
m_VertexData:
serializedVersion: 3
m_VertexCount: 4
m_Channels:
- stream: 0
offset: 0
format: 0
dimension: 3
- stream: 0
offset: 12
format: 0
dimension: 3
- stream: 0
offset: 24
format: 0
dimension: 4
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 40
format: 0
dimension: 2
- stream: 0
offset: 48
format: 0
dimension: 2
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
m_DataSize: 224
_typelessdata: 0100f8c00000e040000066ab00000000dbb6012a0000803f000080bf0000000000000000000080bf0100f8400000e04052d8a33ccf73633f0000f8c03a1ba131000040a88b3146a64992022a0000803f000080bf499202058b3146a6000080bf0000f8403a1ba1310bd7a33c86d8a33ce64ea6b40000e040000066ab8b3146a64992022a0000803f000080bf499202058b3146a6000080bfe64ea6340000e0401b467b3fcf73633f0000000047e0ccb0000000008b31c6a6b76d032a0000803f000080bfb76d83058b31c6a6000080bf0000008047e0ccb010467b3f0bd7a33c
m_CompressedMesh:
m_Vertices:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_UV:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Normals:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Tangents:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Weights:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_NormalSigns:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_TangentSigns:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_FloatColors:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_BoneIndices:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_Triangles:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_UVInfo: 0
m_LocalAABB:
m_Center: {x: -3.8750002, y: 3.5, z: -4.0856207e-13}
m_Extent: {x: 3.8750002, y: 3.5, z: 4.0856207e-13}
m_MeshUsageFlags: 0
m_CookingOptions: 30
m_BakedConvexCollisionMesh:
m_BakedTriangleCollisionMesh:
m_MeshMetrics[0]: 1
m_MeshMetrics[1]: 64.96373
m_MeshOptimizationFlags: 1
m_StreamData:
serializedVersion: 2
offset: 0
size: 0
path:
--- !u!1001 &33617094
PrefabInstance:
m_ObjectHideFlags: 0
@ -8734,6 +8899,171 @@ GameObject:
m_CorrespondingSourceObject: {fileID: 4598833067129945393, guid: f71ab078c7427814bbf506a76af16b3a, type: 3}
m_PrefabInstance: {fileID: 158907866}
m_PrefabAsset: {fileID: 0}
--- !u!43 &159773858
Mesh:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: pb_Mesh-95304(Clone)(Clone)(Clone)(Clone)(Clone)(Clone)(Clone)(Clone)
serializedVersion: 11
m_SubMeshes:
- serializedVersion: 2
firstByte: 0
indexCount: 6
topology: 0
baseVertex: 0
firstVertex: 0
vertexCount: 4
localAABB:
m_Center: {x: -3.8750002, y: 3.5, z: -4.0856207e-13}
m_Extent: {x: 3.8750002, y: 3.5, z: 4.0856207e-13}
m_Shapes:
vertices: []
shapes: []
channels: []
fullWeights: []
m_BindPose: []
m_BoneNameHashes:
m_RootBoneNameHash: 0
m_BonesAABB: []
m_VariableBoneCountWeights:
m_Data:
m_MeshCompression: 0
m_IsReadable: 1
m_KeepVertices: 1
m_KeepIndices: 1
m_IndexFormat: 0
m_IndexBuffer: 000001000200010003000200
m_VertexData:
serializedVersion: 3
m_VertexCount: 4
m_Channels:
- stream: 0
offset: 0
format: 0
dimension: 3
- stream: 0
offset: 12
format: 0
dimension: 3
- stream: 0
offset: 24
format: 0
dimension: 4
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 40
format: 0
dimension: 2
- stream: 0
offset: 48
format: 0
dimension: 2
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
- stream: 0
offset: 0
format: 0
dimension: 0
m_DataSize: 224
_typelessdata: 0100f8c00000e040000066ab00000000dbb6012a0000803f000080bf0000000000000000000080bf0100f8400000e04052d8a33ccf73633f0000f8c03a1ba131000040a88b3146a64992022a0000803f000080bf499202058b3146a6000080bf0000f8403a1ba1310bd7a33c86d8a33ce64ea6b40000e040000066ab8b3146a64992022a0000803f000080bf499202058b3146a6000080bfe64ea6340000e0401b467b3fcf73633f0000000047e0ccb0000000008b31c6a6b76d032a0000803f000080bfb76d83058b31c6a6000080bf0000008047e0ccb010467b3f0bd7a33c
m_CompressedMesh:
m_Vertices:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_UV:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Normals:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Tangents:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_Weights:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_NormalSigns:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_TangentSigns:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_FloatColors:
m_NumItems: 0
m_Range: 0
m_Start: 0
m_Data:
m_BitSize: 0
m_BoneIndices:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_Triangles:
m_NumItems: 0
m_Data:
m_BitSize: 0
m_UVInfo: 0
m_LocalAABB:
m_Center: {x: -3.8750002, y: 3.5, z: -4.0856207e-13}
m_Extent: {x: 3.8750002, y: 3.5, z: 4.0856207e-13}
m_MeshUsageFlags: 0
m_CookingOptions: 30
m_BakedConvexCollisionMesh:
m_BakedTriangleCollisionMesh:
m_MeshMetrics[0]: 1
m_MeshMetrics[1]: 64.96373
m_MeshOptimizationFlags: 1
m_StreamData:
serializedVersion: 2
offset: 0
size: 0
path:
--- !u!1001 &161024109
PrefabInstance:
m_ObjectHideFlags: 0
@ -98302,6 +98632,7 @@ GameObject:
- component: {fileID: 1514850088}
- component: {fileID: 1514850087}
- component: {fileID: 1514850086}
- component: {fileID: 1514850089}
m_Layer: 0
m_Name: Mesh Combiner
m_TagString: Untagged
@ -174761,6 +175092,22 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1514850089
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1514850085}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2737ded29b4eeae4098ac25184794668, type: 3}
m_Name:
m_EditorClassIdentifier:
sources:
- {fileID: 1514850088}
- {fileID: 1907932602}
minimapCamera: {fileID: 1661301926}
--- !u!1001 &1517229764
PrefabInstance:
m_ObjectHideFlags: 0
@ -184555,7 +184902,7 @@ MonoBehaviour:
serializedVersion: 2
m_Bits: 1
m_VolumeTrigger: {fileID: 0}
m_VolumeFrameworkUpdateModeOption: 1
m_VolumeFrameworkUpdateModeOption: 0
m_RenderPostProcessing: 0
m_Antialiasing: 0
m_AntialiasingQuality: 2
@ -187001,7 +187348,7 @@ PrefabInstance:
- target: {fileID: 145984109026135374, guid: 99dfa85f379cc534c9205932aec3d108, type: 3}
propertyPath: m_Mesh
value:
objectReference: {fileID: 1735121239}
objectReference: {fileID: 159773858}
- target: {fileID: 145984109026135374, guid: 99dfa85f379cc534c9205932aec3d108, type: 3}
propertyPath: m_VersionIndex
value: 1664
@ -187073,7 +187420,7 @@ PrefabInstance:
- target: {fileID: 6742821831046128576, guid: 99dfa85f379cc534c9205932aec3d108, type: 3}
propertyPath: m_Mesh
value:
objectReference: {fileID: 1735121239}
objectReference: {fileID: 159773858}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
@ -190464,7 +190811,7 @@ PrefabInstance:
- target: {fileID: 145984109026135374, guid: 99dfa85f379cc534c9205932aec3d108, type: 3}
propertyPath: m_Mesh
value:
objectReference: {fileID: 1114106005}
objectReference: {fileID: 32445914}
- target: {fileID: 145984109026135374, guid: 99dfa85f379cc534c9205932aec3d108, type: 3}
propertyPath: m_VersionIndex
value: 1664
@ -190536,7 +190883,7 @@ PrefabInstance:
- target: {fileID: 6742821831046128576, guid: 99dfa85f379cc534c9205932aec3d108, type: 3}
propertyPath: m_Mesh
value:
objectReference: {fileID: 1114106005}
objectReference: {fileID: 32445914}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
@ -202015,6 +202362,7 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 1907932602}
- component: {fileID: 1907932603}
m_Layer: 0
m_Name: Meshs
m_TagString: Untagged
@ -203701,6 +204049,22 @@ Transform:
- {fileID: 1379036781}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1907932603
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1907932601}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: febea78e49e8f684da3648894af8d4ec, type: 3}
m_Name:
m_EditorClassIdentifier:
_controllerID: 0
_objectsLifetime: 2
_mergeInGroups: 1
_cellSize: 10
--- !u!1001 &1908706508
PrefabInstance:
m_ObjectHideFlags: 0
@ -204649,7 +205013,7 @@ Light:
serializedVersion: 10
m_Type: 1
m_Shape: 0
m_Color: {r: 1, g: 0.692486, b: 0.26729542, a: 1}
m_Color: {r: 0.6509433, g: 0.7518754, b: 1, a: 1}
m_Intensity: 2
m_Range: 10
m_SpotAngle: 30
@ -204708,7 +205072,7 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1918141541}
serializedVersion: 2
m_LocalRotation: {x: -0.24095845, y: 0.7588259, z: -0.43810654, w: -0.41735473}
m_LocalRotation: {x: -0.24095842, y: 0.75882596, z: -0.4381065, w: -0.4173547}
m_LocalPosition: {x: -150.37766, y: 9.037246, z: 84.91737}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
@ -222323,63 +222687,6 @@ GameObject:
m_CorrespondingSourceObject: {fileID: 3695345767536283586, guid: 13dbf1089cf115a429e8f1e06c1ca311, type: 3}
m_PrefabInstance: {fileID: 4578446357911419639}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &4821481747913579479
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 5409078068046653646, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
propertyPath: m_LocalPosition.x
value: 41
objectReference: {fileID: 0}
- target: {fileID: 5409078068046653646, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5409078068046653646, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
propertyPath: m_LocalPosition.z
value: 43
objectReference: {fileID: 0}
- target: {fileID: 5409078068046653646, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 5409078068046653646, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5409078068046653646, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5409078068046653646, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5409078068046653646, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5409078068046653646, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5409078068046653646, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6597837662838677036, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
propertyPath: m_Name
value: prefab_player
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 2bbcc1e35c6def44294f0e9fe4766c0b, type: 3}
--- !u!1001 &5979081436217199172
PrefabInstance:
m_ObjectHideFlags: 0
@ -222910,6 +223217,5 @@ SceneRoots:
- {fileID: 1514850088}
- {fileID: 162969040}
- {fileID: 45663147}
- {fileID: 4821481747913579479}
- {fileID: 1661301927}
- {fileID: 141466854}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -26,12 +26,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4352211019846292106}
serializedVersion: 2
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: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &36631212584191893
MeshFilter:
@ -91,9 +92,17 @@ MeshCollider:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4352211019846292106}
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: 4
m_Convex: 0
serializedVersion: 5
m_Convex: 1
m_CookingOptions: 30
m_Mesh: {fileID: 8034118207443510062, guid: 231f59fd0a5bae0459ed43768af58879, type: 3}

View File

@ -26,12 +26,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6670758144064960994}
serializedVersion: 2
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: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &6951094959604133117
MeshFilter:
@ -91,9 +92,17 @@ MeshCollider:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6670758144064960994}
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: 4
m_Convex: 0
serializedVersion: 5
m_Convex: 1
m_CookingOptions: 30
m_Mesh: {fileID: 6006839936527036828, guid: 7fcf3a93a0562cb448c2d669b84f9c6a, type: 3}

View File

@ -11,7 +11,6 @@ GameObject:
- component: {fileID: 4898787589732913549}
- component: {fileID: 8382367476441177640}
- component: {fileID: 6030550278934145762}
- component: {fileID: -6252671193898491044}
m_Layer: 0
m_Name: SM_cables_01
m_TagString: Untagged
@ -26,13 +25,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5237736906563717943}
serializedVersion: 2
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: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &8382367476441177640
MeshFilter:
@ -85,17 +84,3 @@ MeshRenderer:
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!64 &-6252671193898491044
MeshCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5237736906563717943}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 4
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: 5708574288081384823, guid: 0d80fd0187e0a434cbe7830f72a5ca93, type: 3}

View File

@ -11,7 +11,6 @@ GameObject:
- component: {fileID: 7937560762131369743}
- component: {fileID: 6451471200221937834}
- component: {fileID: 9109882275854857312}
- component: {fileID: 3614400517922374479}
m_Layer: 0
m_Name: SM_cables_03
m_TagString: Untagged
@ -26,13 +25,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7308271106939098549}
serializedVersion: 2
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: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &6451471200221937834
MeshFilter:
@ -85,17 +84,3 @@ MeshRenderer:
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!64 &3614400517922374479
MeshCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7308271106939098549}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 4
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: 212377424962436556, guid: 57be0d2635882f14ea032521832cbc60, type: 3}

View File

@ -11,7 +11,7 @@ GameObject:
- component: {fileID: 5495486924051013576}
- component: {fileID: 8929582156012998765}
- component: {fileID: 6631771320461993127}
- component: {fileID: 1926296589686369538}
- component: {fileID: 8126959155057834021}
m_Layer: 0
m_Name: SM_recycling_bin_01
m_TagString: Untagged
@ -26,12 +26,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5118398774643590514}
serializedVersion: 2
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: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &8929582156012998765
MeshFilter:
@ -83,17 +84,24 @@ MeshRenderer:
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!64 &1926296589686369538
MeshCollider:
--- !u!65 &8126959155057834021
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5118398774643590514}
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: 4
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: -7903601131801283245, guid: 2c83a1f4592fa6b4a8fc78f3d68b305e, type: 3}
serializedVersion: 3
m_Size: {x: 0.67337483, y: 1.3043426, z: 0.6562424}
m_Center: {x: 0, y: 0.6521713, z: 0.000000014901161}

View File

@ -11,7 +11,7 @@ GameObject:
- component: {fileID: 4574806955231601633}
- component: {fileID: 635888508545788996}
- component: {fileID: 3402423834363500686}
- component: {fileID: 4939686457437405649}
- component: {fileID: 4530652701107511624}
m_Layer: 0
m_Name: SM_recycling_bin_02
m_TagString: Untagged
@ -26,12 +26,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3762522207677364571}
serializedVersion: 2
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: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &635888508545788996
MeshFilter:
@ -83,17 +84,24 @@ MeshRenderer:
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!64 &4939686457437405649
MeshCollider:
--- !u!65 &4530652701107511624
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3762522207677364571}
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: 4
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: -364711736255444030, guid: b8a6f9597ec1c6948a6fb2fcc7afddcb, type: 3}
serializedVersion: 3
m_Size: {x: 0.4747013, y: 1.3043426, z: 0.65126157}
m_Center: {x: 0, y: 0.6521713, z: 0.000000014901161}

View File

@ -26,12 +26,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4348898787988389288}
serializedVersion: 2
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: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &53602695672752311
MeshFilter:
@ -91,9 +92,17 @@ MeshCollider:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4348898787988389288}
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: 4
m_Convex: 0
serializedVersion: 5
m_Convex: 1
m_CookingOptions: 30
m_Mesh: {fileID: 648714052394000240, guid: 53108ad0b699b1e46847f5e04ea42887, type: 3}

View File

@ -11,7 +11,6 @@ GameObject:
- component: {fileID: 88427125099519180}
- component: {fileID: 3933317671694619497}
- component: {fileID: 1256791117577267107}
- component: {fileID: 6464418259320279234}
m_Layer: 0
m_Name: SM_utilitypole_preset
m_TagString: Untagged
@ -26,12 +25,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 752656034369144438}
serializedVersion: 2
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: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &3933317671694619497
MeshFilter:
@ -86,17 +86,3 @@ MeshRenderer:
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!64 &6464418259320279234
MeshCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 752656034369144438}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 4
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: -3653064924848412416, guid: 800f7c6eb7c02c2489b6d262162ced41, type: 3}

View File

@ -24,14 +24,15 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3580805424342727505}
serializedVersion: 2
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: 7904053889668872404}
- {fileID: 5505205207917966442}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!64 &530171374678490546
MeshCollider:
@ -41,10 +42,18 @@ MeshCollider:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3580805424342727505}
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: 4
m_Convex: 0
serializedVersion: 5
m_Convex: 1
m_CookingOptions: 30
m_Mesh: {fileID: -1240630588651888049, guid: d252e833a26bc9d408a2bec7d7553e9f, type: 3}
--- !u!1 &4397004673239638052
@ -72,12 +81,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4397004673239638052}
serializedVersion: 2
m_LocalRotation: {x: 0.000000021855694, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1.084993}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4249783016602018283}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &6978097597853231374
MeshFilter:
@ -155,12 +165,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5128776820715015935}
serializedVersion: 2
m_LocalRotation: {x: 0.000000021855694, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1.093315}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4249783016602018283}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &3123967007459893591
MeshFilter:
@ -226,9 +237,17 @@ MeshCollider:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5128776820715015935}
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: 4
serializedVersion: 5
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: -1240630588651888049, guid: d252e833a26bc9d408a2bec7d7553e9f, type: 3}

View File

@ -25,12 +25,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3794497658683199951}
serializedVersion: 2
m_LocalRotation: {x: 0.000000021855694, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1.084993}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3699650826256404480}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &7600564596973181157
MeshFilter:
@ -106,14 +107,15 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4043137900232968890}
serializedVersion: 2
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: 7214019839595284799}
- {fileID: 5029365231670248833}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!64 &-409416719070770103
MeshCollider:
@ -123,10 +125,18 @@ MeshCollider:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4043137900232968890}
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: 4
m_Convex: 0
serializedVersion: 5
m_Convex: 1
m_CookingOptions: 30
m_Mesh: {fileID: -1240630588651888049, guid: d252e833a26bc9d408a2bec7d7553e9f, type: 3}
--- !u!1 &5656693378889989908
@ -155,12 +165,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5656693378889989908}
serializedVersion: 2
m_LocalRotation: {x: 0.000000021855694, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1.093315}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3699650826256404480}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &2519483070979805372
MeshFilter:
@ -226,9 +237,17 @@ MeshCollider:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5656693378889989908}
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: 4
serializedVersion: 5
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: -1240630588651888049, guid: d252e833a26bc9d408a2bec7d7553e9f, type: 3}

View File

@ -25,12 +25,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 22957774268812125}
serializedVersion: 2
m_LocalRotation: {x: 0.000000021855694, 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: 553521290116532882}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &6738490353789321847
MeshFilter:
@ -106,14 +107,15 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 929236871327993896}
serializedVersion: 2
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: 8156768196802289427}
- {fileID: 7173960088779622052}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!64 &10196678631910779
MeshCollider:
@ -123,10 +125,18 @@ MeshCollider:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 929236871327993896}
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: 4
m_Convex: 0
serializedVersion: 5
m_Convex: 1
m_CookingOptions: 30
m_Mesh: {fileID: 5828714007021999026, guid: a7496d926bcaeb14da4feae9222506f9, type: 3}
--- !u!1 &8390678221298777502
@ -154,12 +164,13 @@ Transform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8390678221298777502}
serializedVersion: 2
m_LocalRotation: {x: 0.00000008146034, 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: 553521290116532882}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &270871763828183667
MeshFilter:

View File

@ -8,22 +8,6 @@ namespace BITKit.Entities
{
public class Entity : IEntity, IDisposable
{
private class EntityServiceProvider : IServiceProvider
{
public ServiceProvider ServiceProvider;
public readonly List<Object> Services = new();
public object GetService(Type serviceType)
{
var value = ServiceProvider.GetService(serviceType);
if (value != null)
{
Services.TryAdd(value);
}
return value;
}
}
public Entity()
{
ServiceCollection.AddSingleton<IEntity>(this);
@ -36,26 +20,12 @@ namespace BITKit.Entities
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
private readonly CancellationTokenSource _cancellationTokenSource = new();
public IServiceProvider ServiceProvider
{
get
{
if (_serviceProvider is not null)
{
return _serviceProvider;
}
var value = new EntityServiceProvider()
{
ServiceProvider = ServiceCollection.BuildServiceProvider()
};
_serviceProvider = value;
return _serviceProvider;
}
}
public IServiceProvider ServiceProvider => _serviceProvider ??= ServiceCollection.BuildServiceProvider();
private ServiceProvider _serviceProvider;
public IServiceCollection ServiceCollection { get; } = new ServiceCollection();
private EntityServiceProvider _serviceProvider;
public object[] GetServices()=> _serviceProvider.Services.ToArray();
public object[] GetServices() => ServiceCollection.ToArray()
.Select(x => _serviceProvider.GetService(x.ServiceType)).ToArray();
public void Inject(object obj)
{
foreach (var fieldInfo in obj.GetType().GetFields(ReflectionHelper.Flags))
@ -70,11 +40,7 @@ namespace BITKit.Entities
public void Dispose()
{
_cancellationTokenSource.Cancel();
_serviceProvider.ServiceProvider.Dispose();
foreach (var x in GetServices().OfType<IDisposable>())
{
x.Dispose();
}
_serviceProvider.Dispose();
}
}
}

View File

@ -39,5 +39,29 @@ namespace BITKit
{
return self?.GetInvocationList().Cast<Func<T0, T1, T2, T3>>();
}
public static IEnumerable<Func<T0, T1, T2, T3, T4>> CastAsFunc<T0, T1, T2, T3, T4>(
this Func<T0, T1, T2, T3, T4> self)
{
return self?.GetInvocationList().Cast<Func<T0, T1, T2, T3, T4>>();
}
public static IEnumerable<Func<T0, T1, T2, T3, T4, T5>> CastAsFunc<T0, T1, T2, T3, T4, T5>(
this Func<T0, T1, T2, T3, T4, T5> self)
{
return self?.GetInvocationList().Cast<Func<T0, T1, T2, T3, T4, T5>>();
}
public static IEnumerable<Func<T0, T1, T2, T3, T4, T5, T6>> CastAsFunc<T0, T1, T2, T3, T4, T5, T6>(
this Func<T0, T1, T2, T3, T4, T5, T6> self)
{
return self?.GetInvocationList().Cast<Func<T0, T1, T2, T3, T4, T5, T6>>();
}
public static IEnumerable<Func<T0, T1, T2, T3, T4, T5, T6, T7>> CastAsFunc<T0, T1, T2, T3, T4, T5, T6, T7>(
this Func<T0, T1, T2, T3, T4, T5, T6, T7> self)
{
return self?.GetInvocationList().Cast<Func<T0, T1, T2, T3, T4, T5, T6, T7>>();
}
}
}

View File

@ -167,6 +167,13 @@ namespace BITKit
}
return false;
}
public static IEnumerable<T> RemoveIn<T>(this IEnumerable<T> self, T t)
{
var list = self.ToList();
list.Remove(t);
return list.ToArray();
}
public static bool TryRemove<TKey, TValue>(this IDictionary<TKey, TValue> self, TKey t)
{
if (self.ContainsKey(t))

View File

@ -1,8 +0,0 @@
namespace BITKit.IO
{
public interface IAsset
{
string Name { get; set; }
byte[] Buffer{ get; set; }
}
}

View File

@ -94,6 +94,11 @@ namespace BITKit
/// </summary>
/// <returns></returns>
int Value => 10;
/// <summary>
/// 创建运行时物品
/// </summary>
/// <returns></returns>
IRuntimeItem CreateRuntimeItem();
}
public interface IRuntimeItem : ICloneable
@ -101,7 +106,7 @@ namespace BITKit
/// <summary>
/// 运行时Id
/// </summary>
public int Id { get; }
public int Id { get; set; }
/// <summary>
/// 配置Id
@ -111,7 +116,7 @@ namespace BITKit
/// <summary>
/// 数量
/// </summary>
public int Amount { get; }
public int Amount { get; set; }
/// <summary>
/// 运行时属性
@ -133,14 +138,23 @@ namespace BITKit
/// 被托管的物品
/// </summary>
[Serializable]
public record RuntimeItem : IRuntimeItem
public struct RuntimeItem : IRuntimeItem
{
public int Id { get; set; } = new Random().Next();
public static RuntimeItem Create()
{
var item = new RuntimeItem()
{
Id = new Random().Next(),
RuntimeProperties =
new Dictionary<Type, IScriptableItemProperty>()
};
return item;
}
public int Id { get; set; }
public int ScriptableId { get; set; }
public int Amount { get; set; }
public IDictionary<Type, IScriptableItemProperty> RuntimeProperties { get; set; } =
new Dictionary<Type, IScriptableItemProperty>();
public IDictionary<Type, IScriptableItemProperty> RuntimeProperties { get; set; }
public event Action<IRuntimeItem> OnRuntimePropertiesChanged;

View File

@ -1,8 +1,13 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.SqlServer.Server;
namespace BITKit
{
/// <summary>
/// 支持二进制化的的物品容器,适用于网络化物品容器
/// 支持属性
@ -10,6 +15,7 @@ namespace BITKit
/// </summary>
public interface IRuntimeItemContainer:IBinarySerialize
{
public ValidHandle IsBusy { get; }
/// <summary>
/// 物品容器的唯一Id
/// </summary>
@ -27,6 +33,11 @@ namespace BITKit
/// </summary>
bool Remove(int id);
/// <summary>
/// 设置物品
/// </summary>
/// <param name="id"></param>
void Set(IRuntimeItem id);
/// <summary>
/// 通过通过Id丢下物品
/// </summary>
bool Drop(int id);
@ -67,4 +78,98 @@ namespace BITKit
/// </summary>
event Action<bool> OnRelease;
}
public class RuntimeItemContainer : IRuntimeItemContainer
{
public RuntimeItemContainer()
{
IsBusy.AddListener(x=>OnRelease?.Invoke(!x));
}
public readonly ConcurrentDictionary<int, IRuntimeItem> Items = new();
public void Read(BinaryReader r)
{
throw new NotImplementedException();
}
public void Write(BinaryWriter w)
{
throw new NotImplementedException();
}
public ValidHandle IsBusy { get; } = new();
public int Id { get; set; }
public IRuntimeItem[] GetItems()=>Items.Values.ToArray();
public bool Add(IRuntimeItem item)
{
using var _ = IsBusy.GetHandle();
foreach (var func in AddFactory.CastAsFunc())
{
if (func.Invoke(item) is false)
{
return false;
}
}
Items.Set(item.Id, item);
OnAdd?.Invoke(item);
//BIT4Log.Log<RuntimeItemContainer>($"添加了了:{item.Id}");
return true;
}
public bool Remove(int id)
{
using var _ = IsBusy.GetHandle();
if (Items.TryGetValue(id, out var item) is false) return false;
foreach (var func in RemoveFactory.CastAsFunc())
{
if (func.Invoke(item) is false)
{
return false;
}
}
Items.TryRemove(item.Id);
OnRemove?.Invoke(item);
//BIT4Log.Log<RuntimeItemContainer>($"移除了:{id}");
return true;
}
public void Set(IRuntimeItem id)
{
using var _ = IsBusy.GetHandle();
if (!Items.TryGetValue(id.Id, out var item)) return;
item = id;
OnSet?.Invoke(item);
}
public bool Drop(int id)
{
using var _ = IsBusy.GetHandle();
if (Items.TryGetValue(id, out var item) is false) return false;
foreach (var func in DropFactory.CastAsFunc())
{
if (func.Invoke(item) is false)
{
return false;
}
}
Items.TryRemove(item.Id);
OnDrop?.Invoke(item);
//BIT4Log.Log<RuntimeItemContainer>($"丢下了:{id}");
return true;
}
public event Func<IRuntimeItem, bool> AddFactory;
public event Func<IRuntimeItem, bool> RemoveFactory;
public event Func<IRuntimeItem, bool> DropFactory;
public event Action<IRuntimeItem> OnAdd;
public event Action<IRuntimeItem> OnRemove;
public event Action<IRuntimeItem> OnSet;
public event Action<IRuntimeItem> OnDrop;
public event Action<IRuntimeItemContainer> OnRebuild;
public event Action<bool> OnRelease;
}
}

View File

@ -0,0 +1,13 @@
using System.Collections;
using System.Collections.Generic;
namespace BITKit
{
/// <summary>
/// 玩家向背包添加物品,但是被其他逻辑处理
/// </summary>
public sealed class PlayerInventoryAddItemOverridden : InGameException
{
}
}

View File

@ -0,0 +1,32 @@
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
namespace BITKit.Pool
{
/// <summary>
/// 对象池服务
/// </summary>
public interface IPoolService
{
/// <summary>
/// 生成对象
/// </summary>
/// <param name="path">可寻址路径</param>
/// <typeparam name="T">类型</typeparam>
/// <returns></returns>
UniTask<T> Spawn<T>(string path) where T : class;
/// <summary>
/// 回收对象
/// </summary>
/// <param name="obj">对象实例</param>
/// <param name="path">可寻址路径</param>
/// <typeparam name="T">类型</typeparam>
void Despawn<T>(T obj,string path) where T : class;
/// <summary>
/// 初始化,在此提前生成所有对象
/// </summary>
/// <returns></returns>
UniTask InitializeAsync();
}
}

View File

@ -0,0 +1,176 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Random = UnityEngine.Random;
namespace BITKit.StateMachine
{
/// <summary>
/// 动态异步状态机
/// </summary>
/// <typeparam name="T">异步状态</typeparam>
public class AsyncStateMachine<T>:IStateMachine<T> ,IDisposable where T : class, IStateAsync
{
private readonly IServiceProvider _serviceProvider;
public AsyncStateMachine(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public AsyncStateMachine()
{
_serviceProvider = new ServiceCollection().BuildServiceProvider();
}
public bool Enabled { get; set; } = true;
public T CurrentState { get;private set; }
public T NextOrCurrentState => _nextTargetState.IfNotAllow(CurrentState);
private T _nextState;
public event Action<T, T> OnStateChanging;
public event Action<T, T> OnStateChanged;
public event Action<T> OnStateRegistered;
public IReadOnlyDictionary<int, T> Dictionary => _dictionary;
public event Action<T> OnStateUnRegistered;
public IDictionary<Type, T> StateDictionary { get; } = new Dictionary<Type, T>();
public readonly ValidHandle IsBusy=new();
private readonly CancellationTokenSource _cancellationTokenSource=new();
private readonly Dictionary<int, T> _dictionary = new();
private readonly Optional<T> _nextTargetState = new();
public async void Initialize()
{
await IsBusy;
if(_cancellationTokenSource.IsCancellationRequested)return;
using var _ = IsBusy.GetHandle();
foreach (var (_,value) in StateDictionary)
{
await value.InitializeAsync();
value.Initialize();
}
}
public async void UpdateState(float deltaTime)
{
if (CurrentState is null) return;
using var _ = IsBusy.GetHandle();
await CurrentState.OnStateUpdateAsync(deltaTime);
CurrentState.OnStateUpdate(deltaTime);
}
public async void DisposeState()
{
await IsBusy;
if(_cancellationTokenSource.IsCancellationRequested)return;
if (CurrentState is null) return;
using var _ = IsBusy.GetHandle();
await CurrentState.OnStateExitAsync(CurrentState, null);
if(_cancellationTokenSource.IsCancellationRequested)return;
CurrentState.OnStateExit(CurrentState, null);
CurrentState = null;
}
public T TransitionState<TState>() where TState : T
{
T nextState;
foreach (var (type, value) in Dictionary)
{
if ((typeof(TState) == value.GetType()) is false) continue;
nextState = value;
TransitionState(nextState);
return nextState;
}
nextState = _serviceProvider.GetRequiredService<TState>();
return TransitionState(nextState);;
}
public async UniTask TransitionStateAsync(T nextState)
{
if (nextState is not null)
{
if (nextState.Identifier == 0)
{
nextState.Identifier = nextState.GetHashCode();
}
}
if (Equals(nextState, CurrentState)) return;
if(_nextTargetState.Allow && Equals(_nextTargetState.Value,nextState))return;
if (_nextTargetState.Allow)
{
_nextTargetState.Value = nextState;
return;
}
_nextTargetState.SetValueThenAllow(nextState);
await IsBusy;
if(_cancellationTokenSource.IsCancellationRequested)return;
using var _ = IsBusy.GetHandle();
OnStateChanging?.Invoke(CurrentState,nextState);
if (_dictionary.TryAdd(nextState.Identifier, nextState))
{
await nextState.InitializeAsync();
if(_cancellationTokenSource.IsCancellationRequested)return;
nextState.Initialize();
}
if (CurrentState is not null)
{
CurrentState.Enabled = false;
await CurrentState.OnStateExitAsync(CurrentState, nextState);
if(_cancellationTokenSource.IsCancellationRequested)return;
CurrentState.OnStateExit(CurrentState,nextState);
}
var tempState = CurrentState;
CurrentState = _nextTargetState.Value;
_nextTargetState.Clear();
nextState.Enabled = true;
await nextState.OnStateEntryAsync(tempState);
if(_cancellationTokenSource.IsCancellationRequested)return;
nextState.OnStateEntry(tempState);
OnStateChanged?.Invoke(tempState,nextState);
}
public T TransitionState(T nextState)
{
TransitionStateAsync(nextState).Forget();
return nextState;
}
public async void UnRegister(T newState)
{
if (newState is null) return;
if (Dictionary.ContainsKey(newState.Identifier) is false) return;
_dictionary.Remove(newState.Identifier);
if (Equals(CurrentState, newState))
{
await CurrentState.OnStateExitAsync(CurrentState, null);
CurrentState.OnStateExit(CurrentState, null);
if (CurrentState is IAsyncDisposable asyncDisposable)
{
await asyncDisposable.DisposeAsync();
}
if (CurrentState is IDisposable disposable)
{
disposable.Dispose();
}
CurrentState = null;
}
OnStateUnRegistered?.Invoke(newState);
}
public void Dispose()
{
if(_isDisposed)return;
_cancellationTokenSource.Cancel();
_cancellationTokenSource.Dispose();
_isDisposed = true;
}
private bool _isDisposed;
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
namespace BITKit.StateMachine
{
@ -31,10 +32,22 @@ namespace BITKit.StateMachine
void OnStateExit(IState old, IState newState);
}
public interface IStateAsync:IState
{
/// <summary>
/// 识别符,用于识别多个相同状态但不同用途的状态机
/// </summary>
int Identifier { get; set; }
UniTask InitializeAsync();
UniTask OnStateEntryAsync(IState old);
UniTask OnStateUpdateAsync(float deltaTime);
UniTask OnStateExitAsync(IState old, IState newState);
}
public interface IStateMachine<T> where T:IState
{
bool Enabled { get; set; }
T CurrentState { get; set; }
T CurrentState { get; }
event Action<T,T> OnStateChanged;
event Action<T> OnStateRegistered;
event Action<T> OnStateUnRegistered;
@ -43,14 +56,13 @@ namespace BITKit.StateMachine
void Initialize();
void UpdateState(float deltaTime);
void DisposeState();
void TransitionState<State>() where State : T;
void TransitionState(T state);
T TransitionState<TState>() where TState : T;
T TransitionState(T state);
void Register(T newState) => throw new NotImplementedException("未实现的接口");
void UnRegister(T newState) => throw new NotImplementedException("未实现的接口");
void InvokeOnStateRegistered(T state){}
void InvokeOnStateUnRegistered(T state){}
}
public static class StateMachineUtils
{
public static void Register<T>(this IStateMachine<T> stateMachine, T newState) where T : IState

View File

@ -43,6 +43,14 @@ namespace BITKit.UX
/// </summary>
/// <param name="panelName">面板名称</param>
void Entry(string panelName);
/// <summary>
/// 当前面板
/// </summary>
IUXPanel CurrentPanel { get; }
/// <summary>
/// 面板改变回调
/// </summary>
public event Action<IUXPanel, IUXPanel> OnPanelChanged;
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
namespace BITKit
{
@ -22,6 +23,41 @@ namespace BITKit
[CustomType(typeof(IValidHandle))]
public sealed class ValidHandle: IValidHandle
{
public class MyHandle:IDisposable
{
private readonly ValidHandle _validHandle;
private bool _isDisable = false;
public MyHandle(ValidHandle validHandle,bool isDisable = false)
{
_validHandle = validHandle;
_isDisable = isDisable;
if (isDisable)
{
_validHandle.AddDisableElements(this);
}
else
{
_validHandle.AddElement(this);
}
}
public void Dispose()
{
if (_isDisable)
{
_validHandle.RemoveDisableElements(this);
}
else
{
_validHandle.RemoveElement(this);
}
}
}
public MyHandle GetHandle() => new MyHandle(this);
public MyHandle GetDisableHandle()=> new MyHandle(this,true);
public override string ToString()
{
return $"Allow:{enableHandle}\nElements:{string.Join("\n",objs)}\nDisableElements:{string.Join("\n",disableObjs)}";
@ -51,6 +87,7 @@ namespace BITKit
public readonly List<object> disableObjs = new List<object>();
private bool tempEnable;
private Action<bool> EventOnEnableChanged;
private readonly Queue<UniTaskCompletionSource> _completionSources = new();
public void AddElement(object obj)
@ -73,7 +110,14 @@ namespace BITKit
{
enableHandle = tempEnable;
if (EventOnEnableChanged is not null)
{
EventOnEnableChanged.Invoke(enableHandle);
}
if (tempEnable) return;
if (_completionSources.TryDequeue(out var cs))
{
cs.TrySetResult();
}
}
}
public void RemoveElement(object obj)
@ -164,7 +208,16 @@ namespace BITKit
EventOnEnableChanged -= action;
}
}
public UniTask.Awaiter GetAwaiter()
{
if (Allow is false)
{
return UniTask.CompletedTask.GetAwaiter();
}
var cs = new UniTaskCompletionSource();
_completionSources.Enqueue(cs);
return cs.Task.GetAwaiter();
}
public void Clear()
{
objs.Clear();

View File

@ -72,9 +72,9 @@
"name": "Aim",
"type": "Button",
"id": "f521b9d3-bfbb-4ce2-85c8-15cb3fcc2534",
"expectedControlType": "Button",
"expectedControlType": "",
"processors": "",
"interactions": "Tap,Hold,Press",
"interactions": "Press",
"initialStateCheck": false
},
{
@ -135,7 +135,7 @@
"name": "Primary",
"type": "Button",
"id": "113a3c02-0fbb-4081-9fac-c39878ddfd09",
"expectedControlType": "Button",
"expectedControlType": "",
"processors": "",
"interactions": "Press,Hold",
"initialStateCheck": false
@ -144,7 +144,7 @@
"name": "Secondary",
"type": "Button",
"id": "57a12f28-2fde-45e5-957f-d8d61afe44de",
"expectedControlType": "Button",
"expectedControlType": "",
"processors": "",
"interactions": "Press,Hold",
"initialStateCheck": false
@ -153,7 +153,7 @@
"name": "Tertiary",
"type": "Button",
"id": "c2535f43-fec8-42bd-b680-6d1cee5246e5",
"expectedControlType": "Button",
"expectedControlType": "",
"processors": "",
"interactions": "Press,Hold",
"initialStateCheck": false
@ -162,7 +162,7 @@
"name": "Quaternary",
"type": "Button",
"id": "6740f3a7-7571-4277-96e9-15aa08af7302",
"expectedControlType": "Button",
"expectedControlType": "",
"processors": "",
"interactions": "Press,Hold",
"initialStateCheck": false
@ -171,7 +171,7 @@
"name": "Quinary",
"type": "Button",
"id": "97511588-e441-4e27-953e-e60cbea80489",
"expectedControlType": "Button",
"expectedControlType": "",
"processors": "",
"interactions": "",
"initialStateCheck": false
@ -180,7 +180,7 @@
"name": "Senary",
"type": "Button",
"id": "46173186-2ef3-4ab9-8ff4-b94cc113df67",
"expectedControlType": "Button",
"expectedControlType": "",
"processors": "",
"interactions": "",
"initialStateCheck": false

View File

@ -13,25 +13,82 @@ using System.Text;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using BITKit.Mod;
using UnityEngine.InputSystem.Interactions;
using Label = UnityEngine.UIElements.Label;
using Object = UnityEngine.Object;
// ReSharper disable PossibleMultipleEnumeration
namespace BITKit.Console
{
public class BITConsole : MonoBehaviour
public class UXConsole:IDisposable
{
[RuntimeInitializeOnLoadMethod]
private static void Reload()
{
Application.logMessageReceivedThreaded += EnqueueLog;
}
[BITCommand]
// ReSharper disable once UnusedMember.Global
public static void Console_Exception_Print_StackTrace(int allow)
{
exceptionPrintStackTrace = allow is 1;
_exceptionPrintStackTrace = allow is 1;
}
private static bool exceptionPrintStackTrace = false;
private readonly IMainTicker _ticker;
public UXConsole(IMainTicker ticker)
{
_ticker = ticker;
_singleton = this;
_ticker.Add(OnTick);
InitializeAsync();
Application.logMessageReceivedThreaded += EnqueueLog;
}
private async void InitializeAsync()
{
var go = new GameObject("UXConsole");
Object.DontDestroyOnLoad(go);
var document = go.AddComponent<UIDocument>();
document.sortingOrder = 1;
try
{
var panelSettings =await ModService.LoadAsset<PanelSettings>("ux_panel_settings");
document.panelSettings = panelSettings;
}
catch (Exception e)
{
BIT4Log.Warning<UXService>("未找到ux_panel_settings");
throw;
}
document.visualTreeAsset = await ModService.LoadAsset<VisualTreeAsset>("ux_console");
_rootVisualElement = document.rootVisualElement;
UXUtils.Inject(this,_rootVisualElement);
_commandSelector = new()
{
Container = _commandContainer,
};
_commandSelector.OnSelected += x =>
{
_textField.SetValueWithoutNotify(x.Name);
_textField.Blur();
_textField.Focus();
};
_singleton = this;
_textField.RegisterValueChangedCallback(OnTextFieldValueChanged);
_textField.RegisterCallback<KeyDownEvent>(OnKeyDown);
_text.text = string.Empty;
Toggle(false);
}
private VisualElement _rootVisualElement;
private static bool _exceptionPrintStackTrace;
private class CommandSelector
{
public VisualElement Container { get; set; }
@ -100,111 +157,58 @@ namespace BITKit.Console
public static async void Clear()
{
await BITApp.SwitchToMainThread();
singleton.outputString.Clear();
singleton.text.text = string.Empty;
_singleton._outputString.Clear();
_singleton._text.text = string.Empty;
}
private static BITConsole singleton;
[SerializeField] private UIDocument document;
[SerializeReference] private InputActionReference toggleAction;
private static UXConsole _singleton;
private static ConcurrentQueue<(string condition, string stackTrace, LogType type)> logQueue = new();
private static readonly ConcurrentQueue<(string condition, string stackTrace, LogType type)> LOGQueue = new();
private static void EnqueueLog(string condition, string stackTrace, LogType type)
{
logQueue.Enqueue((condition, stackTrace, type));
LOGQueue.Enqueue((condition, stackTrace, type));
}
private readonly InputActionGroup _inputActionGroup=new()
{
allowGlobalActivation = false
};
public int logLineLimit = 64;
private const int LOGLineLimit = 64;
[UXBindPath("commands-container")]
private VisualElement commandContainer;
private VisualElement _commandContainer;
[UXBindPath("TextField")]
private TextField textField;
private TextField _textField;
[UXBindPath("Text")]
private Label text;
private Label _text;
[UXBindPath( "context-scrollview")]
private ScrollView scrollView;
private ScrollView _scrollView;
private bool _isRunning;
private List<string> outputString = new();
private List<string> _outputString = new();
private CommandSelector _commandSelector;
private void Start()
{
UXUtils.Inject(this);
_commandSelector = new()
{
Container = commandContainer,
};
_commandSelector.OnSelected += x =>
{
textField.SetValueWithoutNotify(x.Name);
textField.Blur();
textField.Focus();
};
singleton = this;
textField.RegisterValueChangedCallback(OnTextFieldValueChanged);
textField.RegisterCallback<KeyDownEvent>(OnKeyDown);
text.text = string.Empty;
_inputActionGroup.RegisterCallback(toggleAction,Toggle);
//_inputActionGroup.RegisterCallback(nextOrPreviousAction, OnNextCommand);
_inputActionGroup.allowInput.AddElement(this);
Toggle(false);
BIT4Log.OnNextLine += OnNextLine;
destroyCancellationToken.Register(() =>
{
BIT4Log.OnNextLine -= OnNextLine;
});
}
private void OnNextLine()
{
if (outputString.Count is not 0 && outputString.Last() != string.Empty)
outputString.Add(string.Empty);
if (_outputString.Count is not 0 && _outputString.Last() != string.Empty)
_outputString.Add(string.Empty);
}
private void OnDestroy()
{
_inputActionGroup.allowInput.RemoveElement(this);
}
public async void Toggle(bool active)
private void Toggle(bool active)
{
_commandSelector.SetMethods(null);
document.rootVisualElement.SetActive(active);
_rootVisualElement.SetActive(active);
_isRunning = active;
BITAppForUnity.AllowCursor.SetElements(this,active);
BITInputSystem.AllowInput.SetDisableElements(this,active);
await UniTask.WaitForEndOfFrame(this);
if (active)
{
textField.SetValueWithoutNotify(string.Empty);
_textField.SetValueWithoutNotify(string.Empty);
textField.Focus();
_textField.Focus();
scrollView.ScrollToBottom();
_scrollView.ScrollToBottom();
}
else
{
text.Blur();
_text.Blur();
}
}
private void OnTextFieldValueChanged(ChangeEvent<string> callback)
@ -215,11 +219,11 @@ namespace BITKit.Console
_commandSelector.SetMethods(commands);
commandContainer.SetActive(commands.Length is not 0);
_commandContainer.SetActive(commands.Length is not 0);
}
else
{
commandContainer.SetActive(false);
_commandContainer.SetActive(false);
_commandSelector.SetMethods(null);
}
@ -230,20 +234,17 @@ namespace BITKit.Console
switch (keyDownEvent.keyCode)
{
case KeyCode.Return:
var cmd = textField.text;
var cmd = _textField.text;
LogCallback($">{cmd}", string.Empty, LogType.Log);
textField.SetValueWithoutNotify(string.Empty);
_textField.SetValueWithoutNotify(string.Empty);
await UniTask.NextFrame();
if (destroyCancellationToken.IsCancellationRequested) return;
_textField.Blur();
textField.Blur();
textField.Focus();
_textField.Focus();
BITCommands.Excute(cmd);
@ -252,10 +253,10 @@ namespace BITKit.Console
break;
case KeyCode.Tab:
break;
case KeyCode.DownArrow when string.IsNullOrEmpty(textField.text) is false:
case KeyCode.DownArrow when string.IsNullOrEmpty(_textField.text) is false:
_commandSelector.Index-=1;
break;
case KeyCode.UpArrow when string.IsNullOrEmpty(textField.text) is false:
case KeyCode.UpArrow when string.IsNullOrEmpty(_textField.text) is false:
_commandSelector.Index+=1;
break;
default:
@ -269,16 +270,6 @@ namespace BITKit.Console
keyDownEvent.PreventDefault();
}
}
private void Toggle(InputAction.CallbackContext context)
{
switch (context)
{
case { interaction: PressInteraction, performed: true }:
Toggle(!_isRunning);
break;
}
}
private async void LogCallback(string condition, string stackTrace, LogType type)
{
try
@ -286,33 +277,33 @@ namespace BITKit.Console
switch (type)
{
case LogType.Error:
outputString.Add($"<color=red>{condition}</color>");
_outputString.Add($"<color=red>{condition}</color>");
break;
case LogType.Warning:
outputString.Add($"<color=yellow>{condition}</color>");
_outputString.Add($"<color=yellow>{condition}</color>");
break;
case LogType.Exception:
outputString.Add($"<color=red>{condition}</color>");
if (exceptionPrintStackTrace)
outputString.Add($"<color=red>{stackTrace}</color>");
_outputString.Add($"<color=red>{condition}</color>");
if (_exceptionPrintStackTrace)
_outputString.Add($"<color=red>{stackTrace}</color>");
break;
default:
outputString.Add(condition);
_outputString.Add(condition);
break;
}
var length = outputString.Count;
if (length > logLineLimit)
var length = _outputString.Count;
if (length > LOGLineLimit)
{
outputString = outputString.GetRange(length - logLineLimit, logLineLimit);
_outputString = _outputString.GetRange(length - LOGLineLimit, LOGLineLimit);
}
StringBuilder stringBuilder = new();
outputString.ForEach(x => stringBuilder.AppendLine(x));
_outputString.ForEach(x => stringBuilder.AppendLine(x));
try
{
await BITApp.SwitchToMainThread();
scrollView.ScrollToBottomAutomatic();
text.text = stringBuilder.ToString();
_scrollView.ScrollToBottomAutomatic();
_text.text = stringBuilder.ToString();
}
catch (OperationCanceledException)
@ -325,25 +316,39 @@ namespace BITKit.Console
}
}
private void Update()
private void OnTick(float delta)
{
while (logQueue.TryDequeue(out var log))
if (_rootVisualElement is null) return;
if (Keyboard.current is { backquoteKey: { wasPressedThisFrame: true } })
{
Toggle(_isRunning=!_isRunning);
return;
}
if(LOGQueue.TryDequeue(out var log))
{
LogCallback(log.condition, log.stackTrace, log.type);
}
if (_isRunning is false) return;
var pos = textField.worldTransform.GetPosition();
var size = textField.layout.size;
var pos = _textField.worldTransform.GetPosition();
var size = _textField.layout.size;
commandContainer.style.left = 0;
commandContainer.style.top = 0;
_commandContainer.style.left = 0;
_commandContainer.style.top = 0;
pos.y += size.y;
commandContainer.transform.position = pos;
_commandContainer.transform.position = pos;
commandContainer.style.width = size.x;
_commandContainer.style.width = size.x;
}
public void Dispose()
{
_ticker.Remove(OnTick);
Application.logMessageReceivedThreaded -= EnqueueLog;
}
}
}

View File

@ -1,74 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using BITKit.StateMachine;
using UnityEngine;
namespace BITKit
{
public abstract class StateBasedMonoBehaviour<T> : MonoBehaviour, IStateMachine<T> where T : IState
{
[SerializeField] private MonoStateMachine<T> stateMachine;
protected Transform Transform => _transform ? _transform : _transform = transform;
private Transform _transform;
public bool Enabled
{
get => stateMachine.Enabled;
set => stateMachine.Enabled = value;
}
public T CurrentState
{
get => stateMachine.CurrentState;
set => stateMachine.CurrentState = value;
}
public event Action<T, T> OnStateChanged
{
add => stateMachine.OnStateChanged += value;
remove => stateMachine.OnStateChanged -= value;
}
public event Action<T> OnStateRegistered;
public event Action<T> OnStateUnRegistered;
public IDictionary<Type, T> StateDictionary => stateMachine.StateDictionary;
public virtual void Initialize()
{
stateMachine.Initialize();
}
public virtual void UpdateState(float deltaTime)
{
stateMachine.UpdateState(deltaTime);
}
public virtual void DisposeState()
{
stateMachine.DisposeState();
}
public virtual void TransitionState<State>() where State : T
{
stateMachine.TransitionState<State>();
}
public virtual void TransitionState(T state)
{
stateMachine.TransitionState(state);
}
public virtual void Register(T newState) => StateMachineUtils.Register(this,newState);
public virtual void UnRegister(T newState)=>StateMachineUtils.UnRegister(this,newState);
void IStateMachine<T>.InvokeOnStateRegistered(T state)
{
OnStateRegistered?.Invoke(state);
}
void IStateMachine<T>.InvokeOnStateUnRegistered(T state)
{
OnStateUnRegistered?.Invoke(state);
}
}
}

View File

@ -0,0 +1,48 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BITKit.Physics
{
public class UnityCollisionController : MonoBehaviour
{
public event Action<Collision> OnUnityCollisionEnter;
public event Action<Collision> OnUnityCollisionStay;
public event Action<Collision> OnUnityCollisionExit;
public event Action<Collider> OnUnityTriggerEnter;
public event Action<Collider> OnUnityTriggerExit;
public event Action<Collider> OnUnityTriggerStay;
private void OnCollisionEnter(Collision other)
{
OnUnityCollisionEnter?.Invoke(other);
}
private void OnCollisionStay(Collision other)
{
OnUnityCollisionStay?.Invoke(other);
}
private void OnCollisionExit(Collision other)
{
OnUnityCollisionExit?.Invoke(other);
}
private void OnTriggerEnter(Collider other)
{
OnUnityTriggerEnter?.Invoke(other);
}
private void OnTriggerExit(Collider other)
{
OnUnityTriggerExit?.Invoke(other);
}
private void OnTriggerStay(Collider other)
{
OnUnityTriggerStay?.Invoke(other);
}
}
}

View File

@ -0,0 +1,141 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using BITKit.Mod;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using UnityEngine;
using Object = UnityEngine.Object;
namespace BITKit.Pool
{
public class UnityPoolService:IPoolService,IDisposable
{
private readonly IServiceProvider _serviceProvider;
public UnityPoolService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
private static readonly ConcurrentDictionary<string,List<object>> Pool = new();
private static readonly ConcurrentDictionary<string,List<object>> UsingPool = new();
private static readonly ConcurrentDictionary<string, Queue<object>> ReadyPool = new();
public void Dispose()
{
var hashset = new HashSet<GameObject>();
foreach (var (_,list) in Pool)
{
foreach (var obj in list)
{
if (obj is not Component component) continue;
if (!hashset.Add(component.gameObject)) continue;
if (component.gameObject)
Object.Destroy(component.gameObject);
}
}
Pool.Clear();
UsingPool.Clear();
ReadyPool.Clear();
}
public async UniTask<T> Spawn<T>(string path) where T : class
{
if (Pool.ContainsKey(path))
{
var readyQueue = ReadyPool[path];
var usingList = UsingPool[path];
if (readyQueue.TryDequeue(out var obj))
{
var value = obj as T;
usingList.Add(value);
return obj as T;
}
if (usingList.Count>0)
{
obj = usingList[0];
usingList.RemoveAt(0);
usingList.Add(obj);
#if UNITY_5_3_OR_NEWER
if (obj is GameObject gameObject)
{
gameObject.SetActive(false);
gameObject.SetActive(true);
}
#endif
return obj as T;
}
}
var list = Pool.GetOrCreate(path);
UsingPool.GetOrCreate(path);
ReadyPool.GetOrCreate(path);
#if UNITY_5_3_OR_NEWER
if (typeof(Object).IsAssignableFrom(typeof(T)))
{
var asset =await ModService.LoadAsset<T>(path);
if (asset is Object o)
{
var instance = Object.Instantiate(o);
list.Add(instance);
UsingPool.GetOrCreate(path).Add(instance);
ReadyPool.GetOrCreate(path);
return instance as T;
}
}
#endif
//检查T的构造函数,如果有需要参数的构造函数,就从ServiceProvider中获取,如果没有,则直接通过System.Activator创建
if (typeof(T).GetConstructors().Any(constructorInfo => constructorInfo.GetParameters().Length is 0))
{
var value = Activator.CreateInstance<T>();
list.Add(value);
UsingPool.GetOrCreate(path).Add(value);
ReadyPool.GetOrCreate(path);
return value;
}
{
var value = _serviceProvider.GetRequiredService<T>();
list.Add(value);
UsingPool.GetOrCreate(path).Add(value);
ReadyPool.GetOrCreate(path);
return value;
}
}
public void Despawn<T>(T obj, string path) where T : class
{
if (UsingPool.TryGetValue(path, out var value))
{
value.Remove(obj);
ReadyPool[path].Enqueue(obj);
#if UNITY_5_3_OR_NEWER
if (obj is GameObject gameObject)
{
gameObject.SetActive(false);
}
#endif
return;
}
if (Pool.ContainsKey(path)) return;
Pool.GetOrCreate(path).Add(obj);
ReadyPool.GetOrCreate(path).Enqueue(obj);
}
public UniTask InitializeAsync()
{
return UniTask.CompletedTask;
}
}
}

View File

@ -2,11 +2,21 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using BITKit.Mod;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
namespace BITKit
{
public static class ModServiceDictionaryReferenceExtensions
{
public static UniTask<T> LoadAssets<T>(int id) where T :class
{
var path = DictionaryReferenceScriptableObject.Dictionary[id];
return ModService.LoadAsset<T>(path);
}
}
public sealed class DictionaryReferenceConfigAttribute : System.Attribute
{
public readonly int index;

View File

@ -2,9 +2,10 @@ using System.Collections;
using System.Collections.Generic;
using System.IO;
using AYellowpaper.SerializedCollections;
using YooAsset;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
@ -21,7 +22,15 @@ namespace BITKit
{
if (_singleton == null)
{
//_singleton = ScriptableObjectHelper.Get<DictionaryReferenceScriptableObject>();
#if UNITY_EDITOR
_singleton =
AssetDatabase.LoadAssetAtPath<DictionaryReferenceScriptableObject>(
"Assets/Artists/Configs/reference_dictionary.asset");
#else
var task = YooAssets.LoadAssetAsync("reference_directory");
task.WaitForAsyncComplete();
_singleton=task.AssetObject as DictionaryReferenceScriptableObject;
#endif
}
return _singleton;
}

View File

@ -18,7 +18,9 @@
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"defineConstraints": [
"deprecated"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -1,29 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace BITKit.Sensors
{
public class SensorEditorWindow : EditorWindow
{
private Toggle _toggle;
[MenuItem("Tools/Sensor/EditorWindow")]
public static void ShowWindow()
{
GetWindow<SensorEditorWindow>("SensorEditorWindow");
}
private void CreateGUI()
{
_toggle = rootVisualElement.Create<Toggle>("Enable Sensor");
_toggle.label = "Enable Sensor";
_toggle.value = SensorGlobalSettings.Enabled;
}
private void Update()
{
SensorGlobalSettings.Enabled = _toggle.value;
}
}
}

View File

@ -1,130 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.UIElements;
#endif
using UnityEngine;
using UnityEngine.UIElements;
namespace BITKit.StateMachine
{
[Serializable]
public class MonoStateMachine<TState> : IStateMachine<TState> where TState : IState
{
public bool Enabled
{
get => _enabled;
set
{
_enabled = value;
if (CurrentState is null) return;
if (value)
{
CurrentState.OnStateExit(null,null);
}
else
{
CurrentState.OnStateEntry(null);
}
}
}
public TState CurrentState { get; set; }
public event Action<TState, TState> OnStateChanged;
public event Action<TState> OnStateRegistered;
public event Action<TState> OnStateUnRegistered;
[SerializeReference, SubclassSelector] public List<TState> states = new();
[SerializeField,ReadOnly] private string _currentStateName;
[SerializeField] private bool debug;
[SerializeField] private bool transitionOnNextFrame;
public IDictionary<Type, TState> StateDictionary { get; } = new Dictionary<Type, TState>();
private bool _enabled = true;
private readonly DoubleBuffer<TState> _nextState = new();
protected bool cancelUpdateStateThisFrame;
public void Initialize()
{
foreach (var state in states)
{
//state.TransitionState = InternalTransitionState;
state.Initialize();
StateDictionary.Add(state.GetType(), state);
}
// if (states.Count > 0)
// {
// TransitionState(states[0]);
// }
}
public void UpdateState(float deltaTime)
{
if(transitionOnNextFrame && _nextState.TryGetRelease(out var nextState))
TransitionStateInternal(nextState);
if (Enabled)
{
if (cancelUpdateStateThisFrame is false)
{
CurrentState?.OnStateUpdate(deltaTime);
}
cancelUpdateStateThisFrame = false;
}
}
public void DisposeState()
{
}
public void TransitionState<State>() where State : TState
{
var nextState = StateDictionary.GetOrCreate(typeof(State));
TransitionState(nextState);
}
public void TransitionState(TState newState)
{
if(transitionOnNextFrame)
_nextState.Release(newState);
else
{
TransitionStateInternal(newState);
cancelUpdateStateThisFrame = true;
}
}
private void TransitionStateInternal(TState newState)
{
if (Equals(newState,CurrentState)) return;
var oldState = CurrentState;
if (oldState is not null)
{
oldState.OnStateExit(oldState, newState);
oldState.Enabled = false;
}
_currentStateName = newState is not null ? newState.GetType().Name : "null";
if (debug)
{
BIT4Log.Log<MonoStateMachine<TState>>($"TransitionState from {_currentStateName} to {_currentStateName}");
}
CurrentState = newState;
if (newState is not null)
{
newState.Enabled = true;
newState.OnStateEntry(oldState);
}
OnStateChanged?.Invoke(oldState, newState);
}
public virtual void Register(TState newState)=>StateMachineUtils.Register(this,newState);
public virtual void UnRegister(TState newState)=>StateMachineUtils.UnRegister(this,newState);
public void InvokeOnStateRegistered(TState state)
{
OnStateRegistered?.Invoke(state);
}
public void InvokeOnStateUnRegistered(TState state)
{
OnStateUnRegistered?.Invoke(state);
}
}
}

View File

@ -1,12 +1,12 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Remoting.Contexts;
using System.ComponentModel.Design;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.InputSystem;
using BITKit;
using Cysharp.Threading.Tasks;
using BITKit.Mod;
using Object = UnityEngine.Object;
namespace BITKit.UX.Internal
{
public class ContextMenu : IContextMenu
@ -20,16 +20,16 @@ namespace BITKit.UX.Internal
{
public Label(string text)
{
this.text = text;
_text = text;
}
string text;
private readonly string _text;
public override VisualElement GetVisualElement()
{
UnityEngine.UIElements.Label label = new(text);
UnityEngine.UIElements.Label label = new(_text);
return label;
}
}
[System.Serializable]
[Serializable]
public class TestContextMenu
{
public void Execute()
@ -45,19 +45,20 @@ namespace BITKit.UX.Internal
{
public Button(string text, params Action[] actions)
{
this.text = text;
_text = text;
foreach (var x in actions)
{
action += x;
_action += x;
}
}
string text;
Action action;
private readonly string _text;
private readonly Action _action;
public override VisualElement GetVisualElement()
{
UnityEngine.UIElements.Button button = new();
button.clicked += action;
button.text = text;
button.clicked += _action;
button.text = _text;
return button;
}
}
@ -77,14 +78,14 @@ namespace BITKit.UX
}
public static ContextMenuBuilder BuildAction(this ContextMenuBuilder self, string text, Action action)
{
self.Add(new Internal.Button(text, action, self.Excute));
self.Add(new Internal.Button(text, action, self.Execute));
return self;
}
}
public class ContextMenuBuilder
{
readonly List<IContextMenu> contexts = new();
public event Action OnExcuted;
private readonly List<IContextMenu> _contexts = new();
public event Action OnExecuted;
private ContextMenuBuilder()
{
@ -97,53 +98,89 @@ namespace BITKit.UX
{
UXContextMenu.Singleton.Create(this);
}
internal void Excute()
internal void Execute()
{
OnExcuted?.Invoke();
OnExecuted?.Invoke();
}
public void Add(IContextMenu x) => contexts.Add(x);
public IEnumerable<IContextMenu> GetContextMenus() => contexts.ToArray();
public void Add(IContextMenu x) => _contexts.Add(x);
public IEnumerable<IContextMenu> GetContextMenus() => _contexts.ToArray();
}
public class UXContextMenu : MonoBehaviour
public class UXContextMenu:IDisposable
{
internal static UXContextMenu Singleton;
[SerializeField] private UIDocument document;
private VisualElement root;
private VisualElement container;
private void Awake()
private readonly IUXService _uxService;
private VisualElement _root;
private VisualElement _container;
private bool _isInitialized = false;
public UXContextMenu(IUXService uxService)
{
_uxService = uxService;
Singleton = this;
root = document.rootVisualElement;
container = document.rootVisualElement[1];
root.Q("background-image").RegisterCallback<MouseDownEvent>(x =>
uxService.OnPanelChanged += OnPanelChanged;
InitializeAsync();
}
private async void InitializeAsync()
{
var go = new GameObject(nameof(UXContextMenu));
Object.DontDestroyOnLoad(go);
var document = go.AddComponent<UIDocument>();
document.sortingOrder = 1;
try
{
var panelSettings =await ModService.LoadAsset<PanelSettings>("ux_panel_settings");
document.panelSettings = panelSettings;
}
catch (Exception)
{
BIT4Log.Warning<UXService>("未找到ux_panel_settings");
throw;
}
document.visualTreeAsset = await ModService.LoadAsset<VisualTreeAsset>("ux_context_menu");
_root = document.rootVisualElement;
_container = _root.Q<VisualElement>("menu-container");
_root.Q("background-image").RegisterCallback<MouseDownEvent>(_ =>
{
Close();
});
_isInitialized = true;
Close();
}
public void Create(ContextMenuBuilder builder)
{
var pos = Mouse.current.position.ReadValue();
pos.y = Screen.height - pos.y;
pos = RuntimePanelUtils.ScreenToPanel(root.panel, pos);
pos = RuntimePanelUtils.ScreenToPanel(_root.panel, pos);
container.style.position = Position.Absolute;
container.style.left = pos.x;
container.style.top = pos.y;
container.Clear();
_container.style.position = Position.Absolute;
_container.style.left = pos.x;
_container.style.top = pos.y;
_container.Clear();
root.SetActive(true);
_root.SetActive(true);
foreach (var context in builder.GetContextMenus())
{
container.Add(context.GetVisualElement());
_container.Add(context.GetVisualElement());
}
builder.OnExcuted += Close;
builder.OnExecuted += Close;
}
void Close()
private void Close()
{
container.Clear();
root.SetActive(false);
if(_isInitialized is false)return;
_container.Clear();
_root.SetActive(false);
}
public void Dispose()
{
_uxService.OnPanelChanged -= OnPanelChanged;
}
private void OnPanelChanged(IUXPanel arg1, IUXPanel arg2)
{
Close();
}
}
}

View File

@ -28,10 +28,55 @@ namespace BITKit.UX
protected abstract string DocumentPath { get; }
public VisualElement RootVisualElement { get; set; }
protected VisualTreeAsset VisualTreeAsset { get; private set; }
private readonly ValidHandle _isBusy = new();
protected UIToolKitPanel(IUXService uxService)
{
UXService = uxService;
uxService.Register(this);
InitializeAsync().Forget();
}
private async UniTask InitializeAsync()
{
await _isBusy;
using var b = _isBusy.GetHandle();
if (RootVisualElement is null)
{
VisualTreeAsset = await ModService.LoadAsset<VisualTreeAsset>(DocumentPath);
RootVisualElement = UXService.Root.As<VisualElement>().Create(VisualTreeAsset);
RootVisualElement.pickingMode = PickingMode.Ignore;
RootVisualElement.style.position = Position.Absolute;
RootVisualElement.style.left = 0;
RootVisualElement.style.right = 0;
RootVisualElement.style.top = 0;
RootVisualElement.style.bottom = 0;
var invisible = RootVisualElement.Create<VisualElement>();
invisible.name = "invisible_return_generate";
invisible.style.position = Position.Absolute;
invisible.pickingMode = PickingMode.Ignore;
invisible.style.left = 0;
invisible.style.right = 0;
invisible.style.top = 0;
invisible.style.bottom = 0;
invisible.SendToBack();
if (CloseWhenClickOutside)
{
invisible.RegisterCallback<MouseDownEvent>(x => { OnReturn(); });
invisible.pickingMode = PickingMode.Position;
}
if (IsWindow)
{
invisible.style.backgroundColor = new Color(0, 0, 0, 0.9f);
}
UXUtils.Inject(this);
RootVisualElement.SetActive(false);
}
}
protected virtual Optional<float> EntryDuration { get; }= new();
@ -62,42 +107,8 @@ namespace BITKit.UX
OnEntry?.Invoke();
}
async UniTask IEntryElement.EntryAsync()
{
if (RootVisualElement is null)
{
VisualTreeAsset = await ModService.LoadAsset<VisualTreeAsset>(DocumentPath);
RootVisualElement = UXService.Root.As<VisualElement>().Create(VisualTreeAsset);
RootVisualElement.pickingMode = PickingMode.Ignore;
RootVisualElement.style.position = Position.Absolute;
RootVisualElement.style.left = 0;
RootVisualElement.style.right = 0;
RootVisualElement.style.top = 0;
RootVisualElement.style.bottom = 0;
var invisible = RootVisualElement.Create<VisualElement>();
invisible.name = "invisible_return_generate";
invisible.style.position = Position.Absolute;
invisible.pickingMode = PickingMode.Ignore;
invisible.style.left = 0;
invisible.style.right = 0;
invisible.style.top = 0;
invisible.style.bottom = 0;
invisible.SendToBack();
if (CloseWhenClickOutside)
{
invisible.RegisterCallback<MouseDownEvent>(x => { OnReturn(); });
invisible.pickingMode = PickingMode.Position;
}
if (IsWindow)
{
invisible.style.backgroundColor = new Color(0, 0, 0, 0.9f);
}
UXUtils.Inject(this);
}
{
await InitializeAsync();
RootVisualElement.SetActive(true);
RootVisualElement.AddToClassList(USSEntry);

View File

@ -103,7 +103,9 @@ namespace BITKit.UX
public void Entry(IUXPanel panel) => _entryQueue.Push(panel);
public void Entry(string panelName) => _entryQueueByName.TryAdd(panelName);
public IUXPanel CurrentPanel => _currentPanel;
public event Action<IUXPanel, IUXPanel> OnPanelChanged;
public void Return()
{
if(_windowEntryGroup.TryGetEntried(out _))
@ -124,6 +126,7 @@ namespace BITKit.UX
private void OnEntry(IUXPanel obj)
{
OnPanelChanged?.Invoke(_currentPanel,obj);
_currentPanel = obj;
}
private void OnTick(float delta)

View File

@ -2,15 +2,15 @@
<Style src="project://database/Assets/BITKit/Unity/UX/Common/Common.uss?fileID=7433441132597879392&amp;guid=a3a69d3518fd02b489e721f3c5b0b539&amp;type=3#Common" />
<Style src="project://database/Assets/BITKit/Unity/UX/BITConsole.uss?fileID=7433441132597879392&amp;guid=9175bfb75cd47b9488b9f12bd34e50fd&amp;type=3#BITConsole" />
<ui:VisualElement name="Root" style="position: absolute; left: 0; top: 0; right: 0; bottom: 0;">
<ui:VisualElement name="Console" class="Console" style="width: 1024px; height: 768px; border-top-left-radius: 16px; border-bottom-left-radius: 16px; border-top-right-radius: 16px; border-bottom-right-radius: 16px; padding-left: 16px; padding-right: 16px; padding-top: 8px; padding-bottom: 8px; margin-left: auto; margin-right: auto; margin-top: auto; margin-bottom: auto;">
<ui:Label text="Console" display-tooltip-when-elided="true" class="Console-Text" />
<ui:ScrollView name="context-scrollview" class="Console-ScrollView" style="height: auto; flex-grow: 1; display: flex;">
<ui:Label text="This is Console&#10;This is &lt;size=24&gt;Rich Text&lt;/size&gt;&#10;This is &lt;color=yellow&gt;Warning&lt;/color&gt;&#10;This is &lt;color=red&gt;Error&lt;/color&gt;&#10;This is loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong text&#10;This is Console&#10;This is &lt;size=24&gt;Rich Text&lt;/size&gt;&#10;This is &lt;color=yellow&gt;Warning&lt;/color&gt;&#10;This is &lt;color=red&gt;Error&lt;/color&gt;&#10;This is loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong text&#10;&lt;color=#add8e6ff&gt;&lt;b&gt;TypeName&lt;/b&gt;&lt;/color&gt;:MyMessage" display-tooltip-when-elided="true" name="Text" enable-rich-text="true" parse-escape-sequences="false" class="Console-Text" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px; white-space: normal;" />
<ui:VisualElement name="console" class="console" style="width: 1024px; height: 768px; border-top-left-radius: 16px; border-bottom-left-radius: 16px; border-top-right-radius: 16px; border-bottom-right-radius: 16px; padding-left: 16px; padding-right: 16px; padding-top: 8px; padding-bottom: 8px; margin-left: auto; margin-right: auto; margin-top: auto; margin-bottom: auto;">
<ui:Label text="console" display-tooltip-when-elided="true" class="console-Text" />
<ui:ScrollView name="context-scrollview" class="console-container" style="height: auto; flex-grow: 1; display: flex;">
<ui:Label text="This is console&#10;This is &lt;size=24&gt;Rich Text&lt;/size&gt;&#10;This is &lt;color=yellow&gt;Warning&lt;/color&gt;&#10;This is &lt;color=red&gt;Error&lt;/color&gt;&#10;This is loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong text&#10;This is console&#10;This is &lt;size=24&gt;Rich Text&lt;/size&gt;&#10;This is &lt;color=yellow&gt;Warning&lt;/color&gt;&#10;This is &lt;color=red&gt;Error&lt;/color&gt;&#10;This is loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong text&#10;&lt;color=#add8e6ff&gt;&lt;b&gt;TypeName&lt;/b&gt;&lt;/color&gt;:MyMessage" display-tooltip-when-elided="true" name="Text" enable-rich-text="true" parse-escape-sequences="false" class="console-Text" style="padding-left: 8px; padding-right: 8px; padding-top: 4px; padding-bottom: 4px; white-space: normal;" />
</ui:ScrollView>
<ui:TextField picking-mode="Ignore" value="filler text" text="filler text" name="TextField" class="Console-TextField" style="height: 48px;" />
<ui:TextField picking-mode="Ignore" value="filler text" text="filler text" name="TextField" class="console-TextField" style="height: 48px; margin-top: 8px;" />
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement name="commands-container" picking-mode="Ignore" style="position: absolute; top: 830px; left: 120px; align-items: stretch; min-width: 512px;">
<ui:VisualElement name="commands-container" picking-mode="Ignore" class="console" style="position: absolute; top: 830px; left: 120px; align-items: stretch; min-width: 512px;">
<ui:Button text="Button" parse-escape-sequences="true" display-tooltip-when-elided="true" />
<ui:Button text="Button" parse-escape-sequences="true" display-tooltip-when-elided="true" />
<ui:Button text="Button" parse-escape-sequences="true" display-tooltip-when-elided="true" />

View File

@ -31,3 +31,4 @@
scale: 1.2 1.2;
opacity: 0.5;
}

View File

@ -1,19 +1,16 @@
Button {
background-color: rgba(0, 0, 0, 0);
color: rgba(255, 255, 255, 0.5);
-unity-font-definition: url('project://database/Assets/Artist/Art/Fonts/NotoSansSC-Bold%20SDF.asset?fileID=11400000&guid=033cc1a4c6c35c6488ad74f4cee476ac&type=2#NotoSansSC-Bold SDF');
border-left-width: 0;
border-right-width: 0;
border-top-width: 0;
border-bottom-width: 0;
-unity-text-align: middle-left;
}
Button:hover {
background-color: rgba(64, 64, 64, 255);
background-color: rgb(64, 64, 64);
}
Button:active {
background-color: rgba(125, 125, 125, 255);
color: rgba(29, 29, 29, 255);
background-color: rgb(125, 125, 125);
color: rgb(29, 29, 29);
}

View File

@ -0,0 +1,56 @@
using System.Collections;
using System.Collections.Generic;
using System.Text;
using MonKey;
using UnityEditor;
using UnityEngine;
namespace BITKit.GameEditor
{
public class QuickFixBoxCollider
{
[Command(nameof(FixCollider), "快速修复BoxCollider编写", QuickName = "fb"),
MenuItem("Tools/Scenes/Fix Float Model Position")]
public static void FixCollider()
{
foreach (var transform in UnityEditor.Selection.transforms)
{
// 获取或创建 BoxCollider 组件
var boxCollider = transform.GetComponent<BoxCollider>();
if (boxCollider == null)
{
continue;
}
// 获取所有可见的 MeshRenderer 组件
var meshRenderers = transform.GetComponentsInChildren<MeshRenderer>();
if (meshRenderers.Length == 0)
{
Debug.LogWarning("No MeshRenderer components found in children.");
return;
}
// 初始化包围盒,以第一个 MeshRenderer 的包围盒为基准
Bounds bounds = new Bounds(transform.transform.InverseTransformPoint(meshRenderers[0].bounds.center),
transform.transform.InverseTransformVector(meshRenderers[0].bounds.size));
// 遍历所有 MeshRenderer合并包围盒
for (int i = 1; i < meshRenderers.Length; i++)
{
Bounds localBounds = meshRenderers[i].bounds;
Vector3 localCenter = transform.transform.InverseTransformPoint(localBounds.center);
Vector3 localSize = transform.transform.InverseTransformVector(localBounds.size);
bounds.Encapsulate(new Bounds(localCenter, localSize));
}
// 设置 BoxCollider 的中心和大小
boxCollider.center = bounds.center;
boxCollider.size = bounds.size;
EditorUtility.SetDirty(boxCollider);
}
}
}
}

View File

@ -0,0 +1,21 @@
{
"name": "AdvancedCullingSystem.Editor",
"rootNamespace": "",
"references": [
"GUID:37151e2099022af42afa90e2ee1b768a",
"GUID:d8b63aba1907145bea998dd612889d6b",
"GUID:e0cd26848372d4e5c891c569017e11f1",
"GUID:2665a8d13d1b3f18800f46e256720795"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,11 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AdvancedCullingSystem
{
public class ChunkMark : MonoBehaviour
{
}
}

View File

@ -0,0 +1,485 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
namespace AdvancedCullingSystem.ChunksMaster
{
public class ChunksMaster
{
private int _uvChannelsCount = 8;
private List<Mesh> _meshes;
private List<List<Bounds>> _bounds;
private List<List<Mesh>> _chunks;
private List<int> _maxTriangles;
public List<Mesh> meshes
{
get
{
return _meshes;
}
}
public List<List<Bounds>> bounds
{
get
{
return _bounds;
}
}
public List<int> maxTriangles
{
get
{
return _maxTriangles;
}
}
private string _saveFolder;
public ChunksMaster()
{
_meshes = new List<Mesh>();
_bounds = new List<List<Bounds>>();
_chunks = new List<List<Mesh>>();
_maxTriangles = new List<int>();
}
public void CreateChunksBounds(Mesh mesh, int maxTriangles)
{
int index = _meshes.IndexOf(mesh);
if (index >= 0)
{
if (_maxTriangles[index] == maxTriangles && _bounds[index].Count > 0)
return;
_bounds[index].Clear();
_maxTriangles[index] = maxTriangles;
}
else
{
_meshes.Add(mesh);
_bounds.Add(new List<Bounds>());
_chunks.Add(new List<Mesh>());
_maxTriangles.Add(maxTriangles);
}
ProcessChunk(mesh, GetTriangles(mesh), mesh.bounds, maxTriangles, true, false);
}
public void CreateChunks(Mesh mesh, int maxTriangles, string saveFolder)
{
_saveFolder = saveFolder;
int index = _meshes.IndexOf(mesh);
if (index >= 0)
{
if (_maxTriangles[index] == maxTriangles && _chunks[index].Count > 0 && _chunks[0] != null)
return;
_bounds[index].Clear();
_chunks[index].Clear();
_maxTriangles[index] = maxTriangles;
}
else
{
_meshes.Add(mesh);
_bounds.Add(new List<Bounds>());
_chunks.Add(new List<Mesh>());
_maxTriangles.Add(maxTriangles);
}
if (!Directory.Exists(saveFolder))
Directory.CreateDirectory(saveFolder);
ProcessChunk(mesh, GetTriangles(mesh), mesh.bounds, maxTriangles, true, true);
}
public List<GameObject> SetupChunks(MeshFilter filter)
{
int index = _meshes.IndexOf(filter.sharedMesh);
if (index < 0)
return null;
List<Mesh> chunks = _chunks[index];
List<GameObject> chunksObjects = new List<GameObject>();
for (int i = 0; i < chunks.Count; i++)
{
GameObject chunkObject = new GameObject(filter.gameObject.name + "_chunk");
ComponentUtility.CopyComponent(filter);
ComponentUtility.PasteComponentAsNew(chunkObject);
ComponentUtility.CopyComponent(filter.GetComponent<MeshRenderer>());
ComponentUtility.PasteComponentAsNew(chunkObject);
chunkObject.transform.parent = filter.transform;
chunkObject.transform.localPosition = Vector3.zero;
chunkObject.transform.localRotation = Quaternion.identity;
chunkObject.transform.localScale = Vector3.one;
chunkObject.GetComponent<MeshFilter>().sharedMesh = chunks[i];
chunkObject.AddComponent<ChunkMark>();
chunkObject.isStatic = filter.gameObject.isStatic;
chunksObjects.Add(chunkObject);
}
filter.GetComponent<MeshRenderer>().enabled = false;
return chunksObjects;
}
public void Clear()
{
_meshes.Clear();
_bounds.Clear();
_chunks.Clear();
_maxTriangles.Clear();
}
private void ProcessChunk(Mesh mesh, List<int>[] triangles, Bounds bounds, int maxTriangles,
bool createBounds, bool createChunks)
{
int count = 0;
for (int i = 0; i < triangles.Length; i++)
count += triangles[i].Count / 3;
if (count < maxTriangles)
{
if(createBounds)
_bounds[_meshes.IndexOf(mesh)].Add(bounds);
if (createChunks)
CreateAndSaveMesh(mesh, triangles);
return;
}
Vector3 size = bounds.size;
if (bounds.size.x >= bounds.size.y && bounds.size.x >= bounds.size.z)
size.x /= 2;
else if (bounds.size.y >= bounds.size.x && bounds.size.y >= bounds.size.z)
size.y /= 2;
else
size.z /= 2;
Bounds leftBounds = new Bounds(bounds.min + size / 2, size);
Bounds rightBounds = new Bounds(bounds.max - size / 2, size);
Vector3[] vertices = mesh.vertices;
List<int>[] leftTriangles = new List<int>[triangles.Length];
List<int>[] rightTriangles = new List<int>[triangles.Length];
for (int i = 0; i < triangles.Length; i++)
{
leftTriangles[i] = new List<int>();
rightTriangles[i] = new List<int>();
for (int c = 0; c < triangles[i].Count; c += 3)
{
Vector3 vec1 = vertices[triangles[i][c]];
Vector3 vec2 = vertices[triangles[i][c + 1]];
Vector3 vec3 = vertices[triangles[i][c + 2]];
if (leftBounds.Contains(vec1) || leftBounds.Contains(vec2) || leftBounds.Contains(vec3))
{
leftTriangles[i].Add(triangles[i][c]);
leftTriangles[i].Add(triangles[i][c + 1]);
leftTriangles[i].Add(triangles[i][c + 2]);
}
else
{
rightTriangles[i].Add(triangles[i][c]);
rightTriangles[i].Add(triangles[i][c + 1]);
rightTriangles[i].Add(triangles[i][c + 2]);
}
}
}
ProcessChunk(mesh, leftTriangles, leftBounds, maxTriangles, createBounds, createChunks);
ProcessChunk(mesh, rightTriangles, rightBounds, maxTriangles, createBounds, createChunks);
}
private List<int>[] GetTriangles(Mesh mesh)
{
int subMeshCount = mesh.subMeshCount;
List<int>[] triangles = new List<int>[subMeshCount];
for (int i = 0; i < subMeshCount; i++)
triangles[i] = new List<int>(mesh.GetTriangles(i));
return triangles;
}
private void GetUVs(Mesh mesh, out List<List<Vector2>> uvs, out List<int> uvChannels)
{
uvs = new List<List<Vector2>>();
uvChannels = new List<int>();
for (int i = 0; i < _uvChannelsCount; i++)
{
List<Vector2> uv = new List<Vector2>();
mesh.GetUVs(i, uv);
if (uv != null && uv.Count > 0)
{
uvs.Add(uv);
uvChannels.Add(i);
}
}
}
private void CreateAndSaveMesh(Mesh src, List<int>[] triangles)
{
Mesh chunk = CreateChunkMesh(src, triangles);
string path = _saveFolder + chunk.GetHashCode() + ".asset";
AssetDatabase.CreateAsset(chunk, path);
_chunks[_meshes.IndexOf(src)].Add(AssetDatabase.LoadAssetAtPath<Mesh>(path));
}
private Mesh CreateChunkMesh(Mesh src, List<int>[] triangles)
{
Mesh mesh = new Mesh();
GetUVs(src, out List<List<Vector2>> srcUvs, out List<int> uvChannels);
Vector3[] srcVertices = src.vertices;
Vector4[] srcTangents = src.tangents;
Vector3[] srcNormals = src.normals;
Color[] srcColors = src.colors;
Color32[] srcColors32 = src.colors32;
List<Vector3> vertices = new List<Vector3>();
List<Vector4> tangents = new List<Vector4>();
List<Vector3> normals = new List<Vector3>();
List<Color> colors = new List<Color>();
List<Color32> colors32 = new List<Color32>();
List<Vector2>[] uvs = new List<Vector2>[uvChannels.Count];
List<int>[] meshTriangles = new List<int>[triangles.Length];
for (int i = 0; i < uvs.Length; i++)
uvs[i] = new List<Vector2>();
Dictionary<int, int> srcToNewTriangles = new Dictionary<int, int>();
for (int i = 0; i < triangles.Length; i++)
{
meshTriangles[i] = new List<int>();
for (int c = 0; c < triangles[i].Count; c++)
{
int srcTriangle = triangles[i][c];
int newTriangle = -1;
if (srcToNewTriangles.ContainsKey(srcTriangle))
{
newTriangle = srcToNewTriangles[srcTriangle];
}
else
{
newTriangle = vertices.Count;
vertices.Add(srcVertices[srcTriangle]);
tangents.Add(srcVertices[srcTriangle]);
normals.Add(srcVertices[srcTriangle]);
for (int j = 0; j < uvChannels.Count; j++)
uvs[j].Add(srcUvs[j][srcTriangle]);
if (srcColors.Length > 0)
colors.Add(srcColors[srcTriangle]);
if (srcColors32.Length > 0)
colors32.Add(srcColors32[srcTriangle]);
srcToNewTriangles.Add(srcTriangle, newTriangle);
}
meshTriangles[i].Add(newTriangle);
}
}
mesh.vertices = vertices.ToArray();
mesh.tangents = tangents.ToArray();
mesh.normals = normals.ToArray();
if (colors.Count > 0)
mesh.SetColors(colors);
if (colors32.Count > 0)
mesh.SetColors(colors32);
for (int i = 0; i < uvChannels.Count; i++)
mesh.SetUVs(uvChannels[i], uvs[i]);
mesh.subMeshCount = triangles.Length;
for (int i = 0; i < triangles.Length; i++)
mesh.SetTriangles(meshTriangles[i], i);
mesh.RecalculateBounds();
mesh.RecalculateNormals();
mesh.RecalculateTangents();
return mesh;
}
}
public static class BoundsHelper
{
public static bool Intersects(this Bounds bounds, Vector3 t1, Vector3 t2, Vector3 t3)
{
float p0, p1, p2, r;
Vector3 extents = bounds.max - bounds.center;
Vector3 v0 = t1 - bounds.center,
v1 = t2 - bounds.center,
v2 = t3 - bounds.center;
Vector3 f0 = v1 - v0,
f1 = v2 - v1,
f2 = v0 - v2;
Vector3 a00 = new Vector3(0, -f0.z, f0.y),
a01 = new Vector3(0, -f1.z, f1.y),
a02 = new Vector3(0, -f2.z, f2.y),
a10 = new Vector3(f0.z, 0, -f0.x),
a11 = new Vector3(f1.z, 0, -f1.x),
a12 = new Vector3(f2.z, 0, -f2.x),
a20 = new Vector3(-f0.y, f0.x, 0),
a21 = new Vector3(-f1.y, f1.x, 0),
a22 = new Vector3(-f2.y, f2.x, 0);
// Test axis a00
p0 = Vector3.Dot(v0, a00);
p1 = Vector3.Dot(v1, a00);
p2 = Vector3.Dot(v2, a00);
r = extents.y * Mathf.Abs(f0.z) + extents.z * Mathf.Abs(f0.y);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
return false;
// Test axis a01
p0 = Vector3.Dot(v0, a01);
p1 = Vector3.Dot(v1, a01);
p2 = Vector3.Dot(v2, a01);
r = extents.y * Mathf.Abs(f1.z) + extents.z * Mathf.Abs(f1.y);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
return false;
// Test axis a02
p0 = Vector3.Dot(v0, a02);
p1 = Vector3.Dot(v1, a02);
p2 = Vector3.Dot(v2, a02);
r = extents.y * Mathf.Abs(f2.z) + extents.z * Mathf.Abs(f2.y);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
return false;
// Test axis a10
p0 = Vector3.Dot(v0, a10);
p1 = Vector3.Dot(v1, a10);
p2 = Vector3.Dot(v2, a10);
r = extents.x * Mathf.Abs(f0.z) + extents.z * Mathf.Abs(f0.x);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
return false;
// Test axis a11
p0 = Vector3.Dot(v0, a11);
p1 = Vector3.Dot(v1, a11);
p2 = Vector3.Dot(v2, a11);
r = extents.x * Mathf.Abs(f1.z) + extents.z * Mathf.Abs(f1.x);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
return false;
// Test axis a12
p0 = Vector3.Dot(v0, a12);
p1 = Vector3.Dot(v1, a12);
p2 = Vector3.Dot(v2, a12);
r = extents.x * Mathf.Abs(f2.z) + extents.z * Mathf.Abs(f2.x);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
return false;
// Test axis a20
p0 = Vector3.Dot(v0, a20);
p1 = Vector3.Dot(v1, a20);
p2 = Vector3.Dot(v2, a20);
r = extents.x * Mathf.Abs(f0.y) + extents.y * Mathf.Abs(f0.x);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
return false;
// Test axis a21
p0 = Vector3.Dot(v0, a21);
p1 = Vector3.Dot(v1, a21);
p2 = Vector3.Dot(v2, a21);
r = extents.x * Mathf.Abs(f1.y) + extents.y * Mathf.Abs(f1.x);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
return false;
// Test axis a22
p0 = Vector3.Dot(v0, a22);
p1 = Vector3.Dot(v1, a22);
p2 = Vector3.Dot(v2, a22);
r = extents.x * Mathf.Abs(f2.y) + extents.y * Mathf.Abs(f2.x);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
return false;
if (Mathf.Max(v0.x, v1.x, v2.x) < -extents.x || Mathf.Min(v0.x, v1.x, v2.x) > extents.x)
return false;
if (Mathf.Max(v0.y, v1.y, v2.y) < -extents.y || Mathf.Min(v0.y, v1.y, v2.y) > extents.y)
return false;
if (Mathf.Max(v0.z, v1.z, v2.z) < -extents.z || Mathf.Min(v0.z, v1.z, v2.z) > extents.z)
return false;
var normal = Vector3.Cross(f1, f0).normalized;
var pl = new Plane(normal, Vector3.Dot(normal, t1));
return Intersects(bounds, pl);
}
public static bool Intersects(this Bounds bounds, Plane plane)
{
Vector3 center = bounds.center;
var extents = bounds.max - center;
var r = extents.x * Mathf.Abs(plane.normal.x) + extents.y * Mathf.Abs(plane.normal.y) + extents.z * Mathf.Abs(plane.normal.z);
var s = Vector3.Dot(plane.normal, center) - plane.distance;
return Mathf.Abs(s) <= r;
}
}
}

View File

@ -0,0 +1,411 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEditor;
using Directory = System.IO.Directory;
namespace AdvancedCullingSystem.ChunksMaster
{
public class ChunksMasterEditorWindow : EditorWindow
{
public Vector2 size
{
get
{
return position.size;
}
}
private ChunksMaster _chunksMaster;
private string _dataSaveFolder;
private int _maxTriangles = 10000;
private bool _showChunks = true;
private Vector2 _scrollPosition;
private List<GameObject> _selectedObjects;
[MenuItem("Tools/NGSTools/Advanced Culling System/Chunks Master")]
private static void CreateWindow()
{
var window = GetWindow<ChunksMasterEditorWindow>(false, "Chunks Master", true);
window.minSize = new Vector2(490, 205);
window.Show();
}
private void OnEnable()
{
SceneView.duringSceneGui += OnSceneView;
_selectedObjects = new List<GameObject>();
_chunksMaster = new ChunksMaster();
string scenePath = SceneManager.GetActiveScene().path;
_dataSaveFolder = (scenePath == null || scenePath == "") ? "ACSData/" :
scenePath.Replace("Assets/", "").Replace(".unity", "_ACSData/");
}
private void OnGUI()
{
CheckData();
GUILayout.BeginArea(new Rect(10, 10, size.x / 2 - 20, size.y - 70));
GUILayout.BeginHorizontal();
GUILayout.Label("Data Save Folder :", GUILayout.Width(110));
_dataSaveFolder = GUILayout.TextField(_dataSaveFolder);
GUILayout.EndHorizontal();
_maxTriangles = Mathf.Max(EditorGUILayout.IntField("Max Triangles Per Chunk : ", _maxTriangles), 1000);
GUILayout.Space(10);
GUILayout.Label(_selectedObjects.Count > 0 ? "Selected Objects :" : "No objects selected");
_scrollPosition = GUILayout.BeginScrollView(_scrollPosition);
for (int i = 0; i < _selectedObjects.Count; i++)
EditorGUILayout.ObjectField(_selectedObjects[i], typeof(GameObject), false);
GUILayout.EndScrollView();
GUILayout.EndArea();
GUILayout.BeginArea(new Rect(size.x / 2 + 10, 10, size.x / 2 - 20, size.y - 70));
if (GUILayout.Button("Add Static")) AddStatic();
if (GUILayout.Button("Add Selected")) AddSelected();
if (GUILayout.Button("Remove Selected")) RemoveSelected();
if (GUILayout.Button("Remove All")) RemoveAll();
_showChunks = EditorGUILayout.ToggleLeft("Show Created Chunks", _showChunks);
GUILayout.EndArea();
GUILayout.BeginArea(new Rect(10, size.y - 50, size.x - 20, 40));
GUILayout.BeginHorizontal();
if (IsSceneContainsChunks())
if (GUILayout.Button("Delete Chunks", GUILayout.Width(100), GUILayout.Height(40)))
DeleteChunks();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Split", GUILayout.Width(70), GUILayout.Height(40))) Split();
if (GUILayout.Button("Apply", GUILayout.Width(70), GUILayout.Height(40))) Apply();
GUILayout.EndHorizontal();
GUILayout.EndArea();
}
private void OnSceneView(SceneView sceneView)
{
if (!_showChunks)
return;
CheckData();
Handles.color = Color.blue;
foreach (var go in _selectedObjects)
{
Mesh mesh = go.GetComponent<MeshFilter>().sharedMesh;
int index = _chunksMaster.meshes.IndexOf(mesh);
Handles.matrix = Matrix4x4.TRS(go.transform.position, go.transform.rotation, go.transform.lossyScale);
foreach (var bounds in _chunksMaster.bounds[index])
Handles.DrawWireCube(bounds.center, bounds.size);
}
Handles.matrix = Matrix4x4.identity;
}
private void OnDestroy()
{
SceneView.duringSceneGui -= OnSceneView;
}
private void AddStatic()
{
int saveObjectsCount = _selectedObjects.Count;
GameObject[] objects = FindObjectsOfType<Transform>()
.Select(t => t.gameObject)
.Where(go => go.isStatic)
.ToArray();
for (int i = 0; i < objects.Length; i++)
{
EditorUtility.DisplayProgressBar("Adding static objects", i + " of " + objects.Length, (float)i / objects.Length);
if (IsValidGameObject(objects[i]))
AddGameObject(objects[i]);
}
EditorUtility.ClearProgressBar();
if ((_selectedObjects.Count - saveObjectsCount) == 0)
Debug.Log("No new static objects added");
else
Debug.Log("Added " + (_selectedObjects.Count - saveObjectsCount) + " objects");
}
private void AddSelected()
{
int saveObjectsCount = _selectedObjects.Count;
GameObject[] selected = Selection.gameObjects;
if (selected == null || selected.Length == 0)
{
Debug.Log("No objects selected");
return;
}
for (int i = 0; i < selected.Length; i++)
{
EditorUtility.DisplayProgressBar("Adding selected objects", i + " of " + selected.Length, (float)i / selected.Length);
foreach (var go in selected[i].GetComponentsInChildren<Transform>().Select(t => t.gameObject))
if (IsValidGameObject(go))
AddGameObject(go);
}
EditorUtility.ClearProgressBar();
if ((_selectedObjects.Count - saveObjectsCount) == 0)
Debug.Log("No new objects added");
else
Debug.Log("Added " + (_selectedObjects.Count - saveObjectsCount) + " objects");
}
private void RemoveSelected()
{
int saveObjectsCount = _selectedObjects.Count;
GameObject[] selected = Selection.gameObjects;
if (selected == null || selected.Length == 0)
{
Debug.Log("No objects selected");
return;
}
for (int i = 0; i < selected.Length; i++)
{
EditorUtility.DisplayProgressBar("Removing selected objects", i + " of " + selected.Length, (float)i / selected.Length);
foreach (var go in selected[i].GetComponentsInChildren<Transform>().Select(t => t.gameObject))
if (_selectedObjects.Contains(go))
_selectedObjects.Remove(go);
}
EditorUtility.ClearProgressBar();
if ((saveObjectsCount - _selectedObjects.Count) == 0)
Debug.Log("No objects removed");
else
Debug.Log("Removed " + (saveObjectsCount - _selectedObjects.Count) + " objects");
}
private void RemoveAll()
{
_selectedObjects.Clear();
Debug.Log("Removed all objects");
}
private void Apply()
{
Mesh[] meshes = _selectedObjects.Select(go => go.GetComponent<MeshFilter>().sharedMesh).ToArray();
for (int i = 0; i < meshes.Length; i++)
{
try
{
EditorUtility.DisplayProgressBar("Applying...", i + " of " + meshes.Length, (float)i / meshes.Length);
_chunksMaster.CreateChunksBounds(meshes[i], _maxTriangles);
}
catch (System.Exception ex)
{
Debug.Log("Can't compute mesh " + meshes[i].name);
Debug.Log("Cause : " + ex.Message + " " + ex.StackTrace);
Debug.Log("Please write about it on e-mail(andre-orsk@yandex.ru) and I will help You");
Debug.Log("-----------------------------------");
}
}
EditorUtility.ClearProgressBar();
}
private void Split()
{
int count = _selectedObjects.Count;
for (int i = 0; i < count; i++)
{
try
{
EditorUtility.DisplayProgressBar("Splitting...", i + " of " + count, (float)i / count);
MeshFilter filter = _selectedObjects[0].GetComponent<MeshFilter>();
_chunksMaster.CreateChunks(filter.sharedMesh, _maxTriangles,
"Assets/" + _dataSaveFolder + filter.gameObject.name + "/");
_chunksMaster.SetupChunks(filter);
}
catch (System.Exception ex)
{
Debug.Log("Can't split mesh " + _selectedObjects[0].name);
Debug.Log("Cause : " + ex.Message + " " + ex.StackTrace);
Debug.Log("Please write about it on e-mail(andre-orsk@yandex.ru) and I will help You");
Debug.Log("-----------------------------------");
}
_selectedObjects.RemoveAt(0);
}
EditorUtility.ClearProgressBar();
}
private void DeleteChunks()
{
ChunkMark[] chunks = FindObjectsOfType<ChunkMark>();
for(int i = 0; i < chunks.Length; i++)
{
try
{
EditorUtility.DisplayProgressBar("Deleting...", i + " of " + chunks.Length, (float)i / chunks.Length);
Mesh mesh = chunks[i].GetComponent<MeshFilter>().sharedMesh;
if (mesh != null)
{
string path = AssetDatabase.GetAssetPath(mesh);
string parentFolder = path.Remove(path.LastIndexOf("/"), path.Length - path.LastIndexOf("/"));
if (path != null && path != "")
AssetDatabase.DeleteAsset(path);
if (Directory.GetFiles(parentFolder).Length == 0)
Directory.Delete(parentFolder, false);
}
chunks[i].transform.parent.GetComponent<MeshRenderer>().enabled = true;
DestroyImmediate(chunks[i].gameObject);
}
catch (System.Exception ex)
{
Debug.Log("Can't remove chunk " + chunks[i].name);
Debug.Log("Cause : " + ex.Message + " " + ex.StackTrace);
Debug.Log("Please write about it on e-mail(andre-orsk@yandex.ru) and I will help You");
Debug.Log("-----------------------------------");
}
}
AssetDatabase.Refresh();
EditorUtility.ClearProgressBar();
}
private void CheckData()
{
if (!_dataSaveFolder.EndsWith("/"))
_dataSaveFolder += "/";
_selectedObjects = _selectedObjects.Where(obj => obj != null && IsValidGameObject(obj)).ToList();
}
private bool IsSceneContainsChunks()
{
return FindObjectsOfType<ChunkMark>().Length > 0;
}
private bool IsValidGameObject(GameObject go)
{
try
{
if (go.GetComponent<MeshRenderer>() == null)
return false;
MeshFilter filter = go.GetComponent<MeshFilter>();
if (filter == null || filter.sharedMesh == null)
return false;
int subMeshCount = filter.sharedMesh.subMeshCount;
for (int i = 0; i < subMeshCount; i++)
if ((filter.sharedMesh.GetTriangles(i).Length / 3) >= _maxTriangles)
return true;
return false;
}
catch (System.Exception ex)
{
Debug.Log("Can't process " + go.name);
Debug.Log("Cause : " + ex.Message + " " + ex.StackTrace);
Debug.Log("Please write about it on e-mail(andre-orsk@yandex.ru) and I will help You");
Debug.Log("-----------------------------------");
return false;
}
}
private void AddGameObject(GameObject go)
{
try
{
if (!_selectedObjects.Contains(go))
{
Mesh mesh = go.GetComponent<MeshFilter>().sharedMesh;
_chunksMaster.CreateChunksBounds(mesh, _maxTriangles);
_selectedObjects.Add(go);
}
}
catch (System.Exception ex)
{
Debug.Log("Can't add " + go.name);
Debug.Log("Cause : " + ex.Message + " " + ex.StackTrace);
Debug.Log("Please write about it on e-mail(andre-orsk@yandex.ru) and I will help You");
Debug.Log("-----------------------------------");
}
}
}
}

View File

@ -0,0 +1,22 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace NGS.AdvancedCullingSystem
{
public static class EditorHelper
{
public static void DrawSeparatorLine(float thickness, float padding)
{
Rect previousRect = GUILayoutUtility.GetLastRect();
GUILayout.Space(padding);
EditorGUILayout.LabelField("", GUILayout.Height(thickness));
Rect lineRect = GUILayoutUtility.GetLastRect();
lineRect.x = previousRect.x;
lineRect.width = previousRect.width;
EditorGUI.DrawRect(lineRect, Color.gray);
GUILayout.Space(padding);
}
}
}

View File

@ -0,0 +1,63 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Linq;
namespace NGS.AdvancedCullingSystem
{
public static class LayersHelper
{
public static bool IsLayerExist(string name)
{
return LayerMask.NameToLayer(name) != -1;
}
public static void CreateLayer(string name)
{
if (IsLayerExist(name))
{
Debug.Log("Layer " + name + " already exists");
return;
}
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
SerializedProperty layers = tagManager.FindProperty("layers");
for (int j = 8; j < layers.arraySize; j++)
{
SerializedProperty newLayer = layers.GetArrayElementAtIndex(j);
if (string.IsNullOrEmpty(newLayer.stringValue))
{
newLayer.stringValue = name;
tagManager.ApplyModifiedProperties();
Debug.Log("Layer created: " + name);
return;
}
}
Debug.LogError("Failed to create layer: " + name + ", maximum number of layers reached.");
}
public static void DisableCollisions(int layer)
{
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
string[] layers = Enumerable.Range(0, 31)
.Select(index => LayerMask.LayerToName(index))
.Where(l => !string.IsNullOrEmpty(l))
.ToArray();
for (int i = 0; i < layers.Length; i++)
{
int current = LayerMask.NameToLayer(layers[i]);
Physics.IgnoreLayerCollision(layer, current);
Physics2D.IgnoreLayerCollision(layer, current);
}
tagManager.ApplyModifiedProperties();
}
}
}

View File

@ -0,0 +1,14 @@
using UnityEditor;
namespace NGS.AdvancedCullingSystem
{
public static class SerializedObjectHelper
{
public static SerializedProperty FindAutoProperty(this SerializedObject obj, string name)
{
string path = string.Format("<{0}>k__BackingField", name);
return obj.FindProperty(path);
}
}
}

View File

@ -0,0 +1,213 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace NGS.AdvancedCullingSystem.Dynamic
{
[CustomEditor(typeof(DC_Controller))]
public class DC_ControllerEditor : Editor
{
private static Dictionary<int, DC_SelectionTool> _indexToSelection;
private static GUIStyle TitleLabelStyle;
private static GUIStyle ButtonGUIStyle;
private new DC_Controller target
{
get
{
return base.target as DC_Controller;
}
}
private DC_SelectionTool _selectionTool;
private bool _containsReadyToBake;
private bool _containsBaked;
private bool _containsNonReadableMeshes;
private void OnEnable()
{
string layer = DC_Controller.GetCullingLayerName();
if (!LayersHelper.IsLayerExist(layer))
{
LayersHelper.CreateLayer(layer);
LayersHelper.DisableCollisions(LayerMask.NameToLayer(layer));
}
UpdateSelectionTool();
UpdateSceneInfo();
}
public override void OnInspectorGUI()
{
if (TitleLabelStyle == null)
CreateGUIStyles();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Dynamic Culling", TitleLabelStyle);
EditorHelper.DrawSeparatorLine(1, 2);
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
EditorGUI.BeginChangeCheck();
if (Application.isPlaying && target.MergeInGroups)
{
target.DrawGizmos = EditorGUILayout.Toggle("Draw Gizmos", target.DrawGizmos);
EditorGUILayout.Space();
}
EditorGUI.BeginDisabledGroup(Application.isPlaying);
target.ControllerID = EditorGUILayout.IntField("Controller ID", target.ControllerID);
if (EditorGUI.EndChangeCheck())
UpdateSelectionTool();
target.ObjectsLifetime = EditorGUILayout.FloatField("Objects Lifetime", target.ObjectsLifetime);
EditorGUILayout.Space();
bool merge = EditorGUILayout.Toggle("Merge In Groups", target.MergeInGroups);
float cellSize = target.CellSize;
if (target.MergeInGroups)
cellSize = EditorGUILayout.FloatField("Cell Size", target.CellSize);
if (!Application.isPlaying)
{
target.MergeInGroups = merge;
target.CellSize = cellSize;
}
EditorGUI.EndDisabledGroup();
if (EditorGUI.EndChangeCheck() && !Application.isPlaying)
EditorUtility.SetDirty(base.target);
EditorGUILayout.Space();
EditorGUILayout.Space();
if (_selectionTool.Controller.gameObject != null)
{
bool sceneChanged = false;
_selectionTool.OnInspectorGUI(ref sceneChanged);
if (sceneChanged)
UpdateSceneInfo();
}
if (Application.isPlaying)
return;
EditorGUILayout.BeginHorizontal();
if (_containsReadyToBake)
{
if (GUILayout.Button("Bake", ButtonGUIStyle))
{
DC_ControllerEditorUtil.BakeScene();
UpdateSceneInfo();
}
}
if (_containsBaked)
{
if (GUILayout.Button("Clear", ButtonGUIStyle))
{
DC_ControllerEditorUtil.ClearBakedData();
UpdateSceneInfo();
}
}
EditorGUILayout.EndHorizontal();
if (_containsNonReadableMeshes)
{
EditorGUILayout.Space();
if (GUILayout.Button("Make Meshes Readable", ButtonGUIStyle))
{
DC_ControllerEditorUtil.MakeMeshesReadable();
UpdateSceneInfo();
}
}
}
private void UpdateSelectionTool()
{
if (_indexToSelection == null)
_indexToSelection = new Dictionary<int, DC_SelectionTool>();
if (!_indexToSelection.TryGetValue(target.ControllerID, out _selectionTool))
{
_selectionTool = new DC_SelectionTool(target);
_indexToSelection.Add(target.ControllerID, _selectionTool);
}
_selectionTool.Initialize(target, this);
_selectionTool.Refresh();
}
private void UpdateSceneInfo()
{
DC_SourceSettings[] settings = FindObjectsOfType<DC_SourceSettings>();
_containsReadyToBake = DC_ControllerEditorUtil.ContainsReadyToBakeSources(settings);
_containsBaked = DC_ControllerEditorUtil.ContainsBakedSources(settings);
_containsNonReadableMeshes = DC_ControllerEditorUtil.ContainsNonReadableMeshes(settings);
}
private void CreateGUIStyles()
{
if (TitleLabelStyle == null)
{
TitleLabelStyle = new GUIStyle();
TitleLabelStyle.fontSize = 24;
TitleLabelStyle.fontStyle = FontStyle.Bold;
TitleLabelStyle.alignment = TextAnchor.MiddleLeft;
TitleLabelStyle.normal.textColor = Color.white;
}
if (ButtonGUIStyle == null)
{
ButtonGUIStyle = new GUIStyle(GUI.skin.button);
ButtonGUIStyle.fontSize = 12;
ButtonGUIStyle.fixedHeight = 24;
ButtonGUIStyle.margin = new RectOffset(5, 5, 5, 5);
ButtonGUIStyle.border = new RectOffset(0, 0, 0, 0);
ButtonGUIStyle.padding = new RectOffset(5, 5, 5, 5);
}
}
[MenuItem("Tools/NGSTools/Advanced Culling System/Dynamic")]
private static void CreateDynamicCulling()
{
GameObject go = new GameObject("Dynamic Culling");
go.AddComponent<DC_Controller>();
Selection.activeGameObject = go;
}
[DrawGizmo(GizmoType.Selected | GizmoType.NonSelected)]
private static void OnDrawGizmos(DC_Controller controller, GizmoType gizmoType)
{
if (_indexToSelection == null)
_indexToSelection = new Dictionary<int, DC_SelectionTool>();
if (_indexToSelection.TryGetValue(controller.ControllerID, out DC_SelectionTool tool))
tool.OnDrawGizmos();
}
}
}

View File

@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using Object = UnityEngine.Object;
namespace NGS.AdvancedCullingSystem.Dynamic
{
public static class DC_ControllerEditorUtil
{
public static bool ContainsReadyToBakeSources(DC_SourceSettings[] sources)
{
foreach (var settings in sources)
{
if (!settings.IsIncompatible && !settings.ReadyForCulling)
return true;
}
return false;
}
public static bool ContainsBakedSources(DC_SourceSettings[] sources)
{
foreach (var settings in sources)
{
if (settings.ReadyForCulling)
return true;
}
return false;
}
public static bool ContainsNonReadableMeshes(DC_SourceSettings[] sources)
{
for (int i = 0; i < sources.Length; i++)
{
DC_SourceSettings source = sources[i];
if (source.SourceType == SourceType.SingleMesh)
{
if (source.TryGetComponent(out MeshFilter filter))
{
Mesh mesh = filter.sharedMesh;
if (mesh != null && !mesh.isReadable)
return true;
}
}
else
{
foreach (MeshFilter filter in source.GetComponentsInChildren<MeshFilter>())
{
Mesh mesh = filter.sharedMesh;
if (mesh != null && !mesh.isReadable)
return true;
}
}
}
return false;
}
public static void MakeMeshesReadable()
{
DC_SourceSettings[] sources = Object.FindObjectsOfType<DC_SourceSettings>();
int count = 0;
for (int i = 0; i < sources.Length; i++)
{
DC_SourceSettings source = sources[i];
if (source.SourceType == SourceType.SingleMesh)
{
if (source.TryGetComponent(out MeshFilter filter))
{
if (filter.sharedMesh != null)
if (MakeMeshReadable(filter.sharedMesh))
count++;
}
}
else
{
foreach (MeshFilter filter in source.GetComponentsInChildren<MeshFilter>())
{
if (filter.sharedMesh != null)
if (MakeMeshReadable(filter.sharedMesh))
count++;
}
}
}
Debug.Log(count + " meshes maked readable");
}
public static void BakeScene()
{
try
{
DC_SourceSettings[] sources = Object.FindObjectsOfType<DC_SourceSettings>();
int count = sources.Length;
for (int i = 0; i < count; i++)
{
EditorUtility.DisplayProgressBar("Bake...", i + " of " + count, (float)i / count);
sources[i].Bake();
}
}
finally
{
EditorUtility.ClearProgressBar();
}
}
public static void ClearBakedData()
{
try
{
DC_SourceSettings[] sources = Object.FindObjectsOfType<DC_SourceSettings>();
int count = sources.Length;
for (int i = 0; i < count; i++)
{
EditorUtility.DisplayProgressBar("Clear...", i + " of " + count, (float)i / count);
sources[i].ClearBakedData();
}
}
finally
{
EditorUtility.ClearProgressBar();
}
}
private static bool MakeMeshReadable(Mesh mesh)
{
try
{
if (mesh.isReadable)
return false;
string path = AssetDatabase.GetAssetPath(mesh.GetInstanceID());
if (path == null || path == "")
Debug.Log("Unable find path for mesh : " + mesh.name);
ModelImporter importer = (ModelImporter)AssetImporter.GetAtPath(path);
importer.isReadable = true;
importer.SaveAndReimport();
Debug.Log(string.Format("Maked {0} mesh readable", mesh.name));
return true;
}
catch (Exception ex)
{
Debug.Log(string.Format("Unable to make mesh {0} readable. Reason : {1}{2}",
mesh.name, ex.Message, ex.StackTrace));
return false;
}
}
}
}

View File

@ -0,0 +1,76 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace NGS.AdvancedCullingSystem.Dynamic
{
public class DC_SelectionTool
{
public DC_Controller Controller { get; private set; }
private DC_BaseSelector[] _selectors;
private DC_ControllerEditor _editor;
public DC_SelectionTool(DC_Controller controller)
{
Controller = controller;
_selectors = new DC_BaseSelector[]
{
new DC_CamerasSelector(this),
new DC_RenderersSelector(this),
new DC_LODGroupsSelector(this),
new DC_CustomSelector(this),
new DC_OccludersSelector(this),
new DC_IncompatiblesSelector(this)
};
}
public void Initialize(DC_Controller controller, DC_ControllerEditor editor)
{
Controller = controller;
_editor = editor;
}
public void OnInspectorGUI(ref bool sceneChanged)
{
for (int i = 0; i < _selectors.Length; i++)
{
if (_selectors[i].IsAvailable)
_selectors[i].OnInspectorGUI(ref sceneChanged);
}
if (sceneChanged) // || GUILayout.Button("Refresh"))
Refresh();
}
public void OnDrawGizmos()
{
for (int i = 0; i < _selectors.Length; i++)
{
DC_BaseSelector selector = _selectors[i];
if (selector.IsAvailable)
selector.OnDrawGizmos();
}
}
public void Refresh()
{
for (int i = 0; i < _selectors.Length; i++)
{
DC_BaseSelector selector = _selectors[i];
if (selector.IsAvailable)
selector.Refresh();
}
}
public void Repaint()
{
_editor?.Repaint();
}
}
}

View File

@ -0,0 +1,873 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
using UnityEditor.AnimatedValues;
namespace NGS.AdvancedCullingSystem.Dynamic
{
public abstract class DC_BaseSelector
{
protected static GUIStyle FoldoutGUIStyle { get; private set; }
protected static GUIStyle ButtonGUIStyle { get; private set; }
protected static readonly Color GreenColor = new Color(0.3f, 1f, 0.3f, 1f);
protected static readonly Color RedColor = new Color(1f, 0.3f, 0.3f, 1f);
public string Label { get; protected set; }
public abstract bool IsAvailable { get; }
protected DC_Controller Controller
{
get
{
return _parent.Controller;
}
}
private DC_SelectionTool _parent;
private AnimBool _foldout;
public DC_BaseSelector(DC_SelectionTool parent)
{
Label = "Default Label";
_parent = parent;
_foldout = new AnimBool(false);
_foldout.valueChanged.AddListener(parent.Repaint);
Refresh();
}
public abstract void Refresh();
public virtual void OnInspectorGUI(ref bool sceneChanged)
{
if (FoldoutGUIStyle == null || ButtonGUIStyle == null)
CreateGUIStyles();
_foldout.target = EditorGUILayout.Foldout(_foldout.target, Label, true, FoldoutGUIStyle);
if (EditorGUILayout.BeginFadeGroup(_foldout.faded))
{
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
DrawContent(ref sceneChanged);
}
EditorGUILayout.EndFadeGroup();
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
}
public abstract void OnDrawGizmos();
protected abstract void DrawContent(ref bool sceneChanged);
protected void DrawBounds(Bounds[] bounds, Color color)
{
Gizmos.color = color;
for (int i = 0; i < bounds.Length; i++)
Gizmos.DrawWireCube(bounds[i].center, bounds[i].size);
}
private void CreateGUIStyles()
{
FoldoutGUIStyle = new GUIStyle(EditorStyles.foldout);
FoldoutGUIStyle.fontSize = 15;
FoldoutGUIStyle.fontStyle = FontStyle.Bold;
FoldoutGUIStyle.normal.textColor = Color.white;
ButtonGUIStyle = new GUIStyle(GUI.skin.button);
ButtonGUIStyle.fontSize = 12;
ButtonGUIStyle.fixedHeight = 30;
ButtonGUIStyle.margin = new RectOffset(5, 5, 5, 5);
ButtonGUIStyle.border = new RectOffset(0, 0, 0, 0);
ButtonGUIStyle.padding = new RectOffset(5, 5, 5, 5);
}
}
public abstract class DC_SelectorTemplate1 : DC_BaseSelector
{
protected DC_SelectorTemplate1(DC_SelectionTool parent)
: base(parent)
{
}
protected override void DrawContent(ref bool sceneChanged)
{
Color backColor = GUI.backgroundColor;
bool picked = Selection.gameObjects.Length > 1 ||
(Selection.gameObjects.Length == 1 && Selection.activeGameObject != Controller.gameObject);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.BeginVertical();
GUI.backgroundColor = GreenColor;
if (GUILayout.Button("Assign Auto", ButtonGUIStyle))
{
AssignAuto();
sceneChanged = true;
}
GUI.backgroundColor = backColor;
EditorGUI.BeginDisabledGroup(!picked);
if (GUILayout.Button("Assign Selected", ButtonGUIStyle))
{
AssignSelectedGameObjects();
sceneChanged = true;
}
EditorGUI.EndDisabledGroup();
EditorGUILayout.EndVertical();
if (!ShouldDrawClearOptions())
{
EditorGUILayout.EndHorizontal();
return;
}
EditorGUILayout.BeginVertical();
GUI.backgroundColor = RedColor;
if (GUILayout.Button("Clear All", ButtonGUIStyle))
{
ClearAll();
sceneChanged = true;
}
GUI.backgroundColor = backColor;
EditorGUI.BeginDisabledGroup(!picked);
if (GUILayout.Button("Clear Selected", ButtonGUIStyle))
{
ClearSelected();
sceneChanged = true;
}
EditorGUI.EndDisabledGroup();
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
if (GUILayout.Button("Select", ButtonGUIStyle))
Select();
}
protected void AssignAuto()
{
GameObject[] gos = Object.FindObjectsOfType<GameObject>();
int count = 0;
for (int i = 0; i < gos.Length; i++)
{
GameObject go = gos[i];
if (AssignIteration(go))
count++;
}
Debug.Log("Assigned " + count + " objects");
}
protected void AssignSelectedGameObjects()
{
GameObject[] gos = Selection.gameObjects
.SelectMany(go => go.GetComponentsInChildren<Transform>()
.Select(t => t.gameObject))
.ToArray();
int count = 0;
for (int i = 0; i < gos.Length; i++)
{
GameObject go = gos[i];
if (AssignIteration(go))
count++;
}
Debug.Log("Assigned " + count + " objects");
}
protected void ClearSelected()
{
GameObject[] gos = Selection.gameObjects
.SelectMany(go => go.GetComponentsInChildren<Transform>()
.Select(t => t.gameObject))
.ToArray();
int count = 0;
for (int i = 0; i < gos.Length; i++)
{
GameObject go = gos[i];
if (ClearIteration(go))
count++;
}
Debug.Log("Cleared " + count + " objects");
}
protected abstract bool ShouldDrawClearOptions();
protected abstract bool AssignIteration(GameObject current);
protected abstract bool ClearIteration(GameObject current);
protected abstract void ClearAll();
protected abstract void Select();
}
public class DC_CamerasSelector : DC_SelectorTemplate1
{
public override bool IsAvailable
{
get
{
return !Application.isPlaying;
}
}
private DC_Camera[] _cameras;
public DC_CamerasSelector(DC_SelectionTool parent) : base(parent)
{
}
public override void Refresh()
{
_cameras = Object.FindObjectsOfType<DC_Camera>();
Label = "Cameras (" + _cameras.Length + ")";
}
public override void OnDrawGizmos()
{
}
protected override bool ShouldDrawClearOptions()
{
return _cameras.Length > 0;
}
protected override bool AssignIteration(GameObject current)
{
if (!current.activeInHierarchy)
return false;
if (current.TryGetComponent(out DC_Camera cullingCamera))
return false;
if (current.TryGetComponent(out Camera camera))
{
Controller.AddCamera(camera, 1500);
return true;
}
return false;
}
protected override void ClearAll()
{
for (int i = 0; i < _cameras.Length; i++)
{
Object.DestroyImmediate(_cameras[i]);
}
}
protected override bool ClearIteration(GameObject current)
{
if (current.TryGetComponent(out DC_Camera camera))
{
Object.DestroyImmediate(camera);
return true;
}
return false;
}
protected override void Select()
{
Selection.objects = _cameras.Select(c => c.gameObject).ToArray();
}
}
public class DC_RenderersSelector : DC_SelectorTemplate1
{
public override bool IsAvailable
{
get
{
return !Application.isPlaying;
}
}
private DC_SourceSettings[] _renderersSettings;
private Bounds[] _bounds;
private bool _drawGizmos;
public DC_RenderersSelector(DC_SelectionTool parent)
: base(parent)
{
}
public override void Refresh()
{
_renderersSettings = Object.FindObjectsOfType<DC_SourceSettings>()
.Where(s => s.SourceType == SourceType.SingleMesh && s.ControllerID == Controller.ControllerID)
.ToArray();
Bounds bounds = default;
_bounds = _renderersSettings
.Where(s => s.TryGetBounds(ref bounds))
.Select(r => bounds)
.ToArray();
Label = "Renderers (" + _renderersSettings.Length + ")";
}
protected override void DrawContent(ref bool sceneChanged)
{
_drawGizmos = EditorGUILayout.Toggle("Draw Gizmos", _drawGizmos);
base.DrawContent(ref sceneChanged);
}
public override void OnDrawGizmos()
{
if (!_drawGizmos || _bounds == null)
return;
DrawBounds(_bounds, Color.blue);
}
protected override bool ShouldDrawClearOptions()
{
return _renderersSettings.Length > 0;
}
protected override bool AssignIteration(GameObject current)
{
if (!current.activeInHierarchy)
return false;
if (current.GetComponent<DC_SourceSettings>() != null)
return false;
if (current.GetComponent<DC_Occluder>() != null)
return false;
MeshRenderer renderer = current.GetComponent<MeshRenderer>();
if (renderer == null || !renderer.enabled)
return false;
LODGroup group = current.GetComponentInParent<LODGroup>();
if (group != null && group.GetLODs().ContainsAny(r => r == renderer))
return false;
Controller.AddObjectForCulling(renderer).CheckCompatibility();
return true;
}
protected override bool ClearIteration(GameObject current)
{
if (current.TryGetComponent(out DC_SourceSettings settings))
{
if (settings.SourceType != SourceType.SingleMesh)
return false;
if (settings.ControllerID != Controller.ControllerID)
return false;
settings.ClearBakedData();
Object.DestroyImmediate(settings);
return true;
}
return false;
}
protected override void ClearAll()
{
for (int i = 0; i < _renderersSettings.Length; i++)
{
_renderersSettings[i].ClearBakedData();
Object.DestroyImmediate(_renderersSettings[i]);
}
}
protected override void Select()
{
Selection.objects = _renderersSettings.Select(s => s.gameObject).ToArray();
}
}
public class DC_LODGroupsSelector : DC_SelectorTemplate1
{
public override bool IsAvailable
{
get
{
return !Application.isPlaying;
}
}
private DC_SourceSettings[] _settings;
private Bounds[] _bounds;
private bool _drawGizmos;
public DC_LODGroupsSelector(DC_SelectionTool parent) : base(parent)
{
}
public override void Refresh()
{
_settings = Object.FindObjectsOfType<DC_SourceSettings>()
.Where(s => s.SourceType == SourceType.LODGroup && s.ControllerID == Controller.ControllerID)
.ToArray();
Bounds bounds = default;
_bounds = _settings
.Where(s => s.TryGetBounds(ref bounds))
.Select(r => bounds)
.ToArray();
Label = "LODGroups (" + _settings.Length + ")";
}
protected override void DrawContent(ref bool sceneChanged)
{
_drawGizmos = EditorGUILayout.Toggle("Draw Gizmos", _drawGizmos);
base.DrawContent(ref sceneChanged);
}
public override void OnDrawGizmos()
{
if (!_drawGizmos || _bounds == null)
return;
DrawBounds(_bounds, Color.yellow);
}
protected override bool ShouldDrawClearOptions()
{
return _settings.Length > 0;
}
protected override bool AssignIteration(GameObject current)
{
if (!current.activeInHierarchy)
return false;
if (current.GetComponent<DC_SourceSettings>() != null)
return false;
if (current.GetComponent<DC_Occluder>() != null)
return false;
LODGroup group = current.GetComponent<LODGroup>();
if (group == null)
return false;
Controller.AddObjectForCulling(group).CheckCompatibility();
return true;
}
protected override void ClearAll()
{
for (int i = 0; i < _settings.Length; i++)
{
_settings[i].ClearBakedData();
Object.DestroyImmediate(_settings[i]);
}
}
protected override bool ClearIteration(GameObject current)
{
if (current.TryGetComponent(out DC_SourceSettings settings))
{
if (settings.SourceType != SourceType.LODGroup)
return false;
if (settings.ControllerID != Controller.ControllerID)
return false;
settings.ClearBakedData();
Object.DestroyImmediate(settings);
return true;
}
return false;
}
protected override void Select()
{
Selection.objects = _settings.Select(s => s.gameObject).ToArray();
}
}
public class DC_CustomSelector : DC_BaseSelector
{
public override bool IsAvailable
{
get
{
return !Application.isPlaying;
}
}
private DC_SourceSettings[] _customSettings;
private Bounds[] _bounds;
private bool _drawGizmos;
public DC_CustomSelector(DC_SelectionTool parent) : base(parent)
{
}
public override void Refresh()
{
_customSettings = Object.FindObjectsOfType<DC_SourceSettings>()
.Where(s => s.SourceType == SourceType.Custom && s.ControllerID == Controller.ControllerID)
.ToArray();
Bounds bounds = default;
_bounds = _customSettings
.Where(s => s.TryGetBounds(ref bounds))
.Select(r => bounds)
.ToArray();
Label = "Custom (" + _customSettings.Length + ")";
}
protected override void DrawContent(ref bool sceneChanged)
{
_drawGizmos = EditorGUILayout.Toggle("Draw Gizmos", _drawGizmos);
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Select", ButtonGUIStyle))
Select();
Color backColor = GUI.backgroundColor;
GUI.backgroundColor = RedColor;
if (GUILayout.Button("Clear All", ButtonGUIStyle))
{
ClearAll();
sceneChanged = true;
}
GUI.backgroundColor = backColor;
EditorGUILayout.EndHorizontal();
}
public override void OnDrawGizmos()
{
if (!_drawGizmos || _bounds == null)
return;
DrawBounds(_bounds, Color.white);
}
private void ClearAll()
{
for (int i = 0; i < _customSettings.Length; i++)
Object.DestroyImmediate(_customSettings[i]);
}
private void Select()
{
Selection.objects = _customSettings.Select(o => o.gameObject).ToArray();
}
}
public class DC_OccludersSelector : DC_BaseSelector
{
public override bool IsAvailable
{
get
{
return !Application.isPlaying;
}
}
private DC_Occluder[] _occluders;
private Bounds[] _bounds;
private OccluderType _occluderType;
private bool _drawGizmos;
public DC_OccludersSelector(DC_SelectionTool parent) : base(parent)
{
}
public override void Refresh()
{
_occluders = Object.FindObjectsOfType<DC_Occluder>();
Bounds bounds = default;
_bounds = _occluders
.Where(o => o.TryGetBounds(ref bounds))
.Select(o => bounds)
.ToArray();
Label = "Occluders (" + _occluders.Length + ")";
}
protected override void DrawContent(ref bool sceneChanged)
{
_drawGizmos = EditorGUILayout.Toggle("Draw Gizmos", _drawGizmos);
_occluderType = (OccluderType) EditorGUILayout.EnumPopup("Occluder Type", _occluderType);
Color backColor = GUI.backgroundColor;
EditorGUILayout.BeginHorizontal();
GUI.backgroundColor = GreenColor;
if (GUILayout.Button("Assign Selected", ButtonGUIStyle))
{
AssignSelected();
sceneChanged = true;
}
GUI.backgroundColor = backColor;
if (_occluders.Length == 0)
{
EditorGUILayout.EndHorizontal();
return;
}
GUI.backgroundColor = RedColor;
if (GUILayout.Button("Clear Selected", ButtonGUIStyle))
{
ClearSelected();
sceneChanged = true;
}
GUI.backgroundColor = backColor;
EditorGUILayout.EndHorizontal();
if (GUILayout.Button("Clear All", ButtonGUIStyle))
{
ClearAll();
sceneChanged = true;
}
if (GUILayout.Button("Select", ButtonGUIStyle))
Select();
}
public override void OnDrawGizmos()
{
if (!_drawGizmos || _bounds == null)
return;
DrawBounds(_bounds, Color.green);
}
private void AssignSelected()
{
GameObject[] gos = Selection.gameObjects
.SelectMany(go => go.GetComponentsInChildren<Transform>()
.Select(t => t.gameObject))
.ToArray();
int count = 0;
for (int i = 0; i < gos.Length; i++)
{
GameObject go = gos[i];
if (go.TryGetComponent(out DC_SourceSettings settings))
continue;
if (_occluderType == OccluderType.Collider)
{
if (go.GetComponent<Collider>() != null)
{
go.AddComponent<DC_Occluder>();
count++;
}
}
else if (_occluderType == OccluderType.Mesh)
{
if (go.GetComponent<MeshRenderer>() != null)
{
go.AddComponent<DC_Occluder>();
count++;
}
}
else
{
if (go.GetComponent<LODGroup>() != null)
{
go.AddComponent<DC_Occluder>();
count++;
}
}
}
Debug.Log("Assigned " + count + " objects");
}
private void ClearSelected()
{
GameObject[] gos = Selection.gameObjects
.SelectMany(go => go.GetComponentsInChildren<Transform>()
.Select(t => t.gameObject))
.ToArray();
int count = 0;
for (int i = 0; i < gos.Length; i++)
{
GameObject go = gos[i];
if (go.TryGetComponent(out DC_Occluder occluder))
{
Object.DestroyImmediate(occluder);
count++;
}
}
Debug.Log("Clear " + count + " objects");
}
private void ClearAll()
{
for (int i = 0; i < _occluders.Length; i++)
Object.DestroyImmediate(_occluders[i]);
}
private void Select()
{
Selection.objects = _occluders.Select(o => o.gameObject).ToArray();
}
}
public class DC_IncompatiblesSelector : DC_BaseSelector
{
public override bool IsAvailable
{
get
{
return true;
}
}
private DC_SourceSettings[] _settings;
public DC_IncompatiblesSelector(DC_SelectionTool parent)
: base(parent)
{
}
public override void Refresh()
{
_settings = Object.FindObjectsOfType<DC_SourceSettings>()
.Where(s => s.IsIncompatible)
.ToArray();
Label = "Incompatible Sources (" + _settings.Length + ")";
}
public override void OnInspectorGUI(ref bool sceneChanged)
{
if (_settings.Length == 0)
return;
base.OnInspectorGUI(ref sceneChanged);
}
protected override void DrawContent(ref bool sceneChanged)
{
if (_settings.Length == 0)
{
EditorGUILayout.HelpBox("Incompatible sources not found :)", MessageType.Info);
return;
}
if (!Application.isPlaying)
{
Color back = GUI.backgroundColor;
GUI.backgroundColor = GreenColor;
if (GUILayout.Button("Clear All", ButtonGUIStyle))
{
ClearAll();
sceneChanged = true;
}
GUI.backgroundColor = back;
}
if (GUILayout.Button("Select", ButtonGUIStyle))
Select();
if (GUILayout.Button("Print", ButtonGUIStyle))
Print();
}
public override void OnDrawGizmos()
{
}
private void ClearAll()
{
for (int i = 0; i < _settings.Length; i++)
Object.DestroyImmediate(_settings[i]);
}
private void Select()
{
Selection.objects = _settings.Select(o => o.gameObject).ToArray();
}
private void Print()
{
for (int i = 0; i < _settings.Length; i++)
Debug.Log(_settings[i].gameObject.name + " " + _settings[i].IncompatibilityReason);
}
}
}

View File

@ -0,0 +1,343 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
namespace NGS.AdvancedCullingSystem.Dynamic
{
[CanEditMultipleObjects]
[CustomEditor(typeof(DC_SourceSettings))]
public class DC_SourceSettingsEditor : Editor
{
private new DC_SourceSettings target
{
get
{
return base.target as DC_SourceSettings;
}
}
private SerializedProperty _controllerIdProp;
private SerializedProperty _sourceTypeProp;
private SerializedProperty _isIncompatibleProp;
private SerializedProperty _incompatibilityReasonProp;
private SourceSettingsStrategyEditor _strategyEditor;
private void OnEnable()
{
_controllerIdProp = serializedObject.FindAutoProperty(nameof(target.ControllerID));
_sourceTypeProp = serializedObject.FindProperty("_sourceType");
_isIncompatibleProp = serializedObject.FindAutoProperty(nameof(target.IsIncompatible));
_incompatibilityReasonProp = serializedObject.FindAutoProperty(nameof(target.IncompatibilityReason));
}
public override void OnInspectorGUI()
{
serializedObject.Update();
_strategyEditor = GetSourceSettingsStrategyEditor();
_strategyEditor?.SetContext(serializedObject);
DrawHelpBox();
if (DrawProperties())
ApplyModifiedProperties();
EditorGUILayout.Space();
if (GUILayout.Button("Check Compatibility"))
CheckCompatibilities();
}
private void OnSceneGUI()
{
_strategyEditor?.OnSceneGUI(target);
}
private SourceSettingsStrategyEditor GetSourceSettingsStrategyEditor()
{
if (!_sourceTypeProp.hasMultipleDifferentValues)
{
SourceType sourceType = (SourceType)_sourceTypeProp.enumValueIndex;
if (sourceType == SourceType.SingleMesh)
{
if (_strategyEditor is RendererSourceSettingsStrategyEditor)
return _strategyEditor;
return new RendererSourceSettingsStrategyEditor();
}
if (sourceType == SourceType.LODGroup)
{
if (_strategyEditor is LODGroupSourceSettingsStrategyEditor)
return _strategyEditor;
return new LODGroupSourceSettingsStrategyEditor();
}
if (sourceType == SourceType.Custom)
{
if (_strategyEditor is CustomSourceSettingsStrategyEditor)
return _strategyEditor;
return new CustomSourceSettingsStrategyEditor();
}
}
return null;
}
private void DrawHelpBox()
{
if (_isIncompatibleProp.boolValue && !_isIncompatibleProp.hasMultipleDifferentValues)
{
string text = _incompatibilityReasonProp.stringValue;
EditorGUILayout.HelpBox(text, MessageType.Warning);
EditorGUILayout.Space();
}
}
private bool DrawProperties()
{
EditorGUI.BeginDisabledGroup(Application.isPlaying);
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_controllerIdProp);
EditorGUILayout.PropertyField(_sourceTypeProp);
_strategyEditor?.DrawProperties();
EditorGUI.EndDisabledGroup();
return EditorGUI.EndChangeCheck();
}
private void ApplyModifiedProperties()
{
_strategyEditor?.ApplyModifiedProperties(targets);
foreach (var target in targets)
{
DC_SourceSettings current = target as DC_SourceSettings;
if (!_controllerIdProp.hasMultipleDifferentValues)
current.ControllerID = _controllerIdProp.intValue;
if (!_sourceTypeProp.hasMultipleDifferentValues)
current.SourceType = (SourceType) _sourceTypeProp.enumValueIndex;
EditorUtility.SetDirty(target);
}
}
private void CheckCompatibilities()
{
foreach (var target in targets)
{
DC_SourceSettings current = target as DC_SourceSettings;
if (current.CheckCompatibility())
{
Debug.Log(current.name + " is compatible!");
}
else
{
Debug.Log(current.name + " is incompatible. Reason : " + current.IncompatibilityReason);
}
}
}
private abstract class SourceSettingsStrategyEditor
{
protected SerializedObject Context { get; private set; }
private bool _propertiesChanged;
public void SetContext(SerializedObject context)
{
Context = context;
OnContextSet();
}
public void DrawProperties()
{
EditorGUI.BeginChangeCheck();
DrawPropertiesInternal();
_propertiesChanged = EditorGUI.EndChangeCheck();
}
public void ApplyModifiedProperties(Object[] targets)
{
if (!_propertiesChanged)
return;
ApplyModifiedPropertiesInternal(targets);
_propertiesChanged = false;
}
public virtual void OnSceneGUI(DC_SourceSettings target)
{
}
protected abstract void OnContextSet();
protected abstract void DrawPropertiesInternal();
protected abstract void ApplyModifiedPropertiesInternal(Object[] targets);
}
private class RendererSourceSettingsStrategyEditor : SourceSettingsStrategyEditor
{
private SerializedProperty _cullingMethodProp;
private SerializedProperty _convexColliderProp;
protected override void OnContextSet()
{
SerializedProperty strategyProp = Context.FindProperty("_strategy");
_cullingMethodProp = strategyProp.FindPropertyRelative("_cullingMethod");
_convexColliderProp = strategyProp.FindPropertyRelative("_convexCollider");
}
protected override void DrawPropertiesInternal()
{
EditorGUILayout.PropertyField(_cullingMethodProp);
EditorGUILayout.PropertyField(_convexColliderProp);
}
protected override void ApplyModifiedPropertiesInternal(Object[] targets)
{
if (!_cullingMethodProp.hasMultipleDifferentValues)
{
foreach (var target in targets)
{
(target as DC_SourceSettings).GetStrategy<DC_RendererSourceSettingsStrategy>()
.CullingMethod = (CullingMethod)_cullingMethodProp.enumValueIndex;
}
}
if (!_convexColliderProp.hasMultipleDifferentValues)
{
foreach (var target in targets)
{
(target as DC_SourceSettings).GetStrategy<DC_RendererSourceSettingsStrategy>()
.ConvexCollider = _convexColliderProp.boolValue;
}
}
}
}
private class LODGroupSourceSettingsStrategyEditor : SourceSettingsStrategyEditor
{
private SerializedProperty _cullingMethodProp;
protected override void OnContextSet()
{
_cullingMethodProp = Context
.FindProperty("_strategy")
.FindPropertyRelative("_cullingMethod");
}
protected override void DrawPropertiesInternal()
{
EditorGUILayout.PropertyField(_cullingMethodProp);
}
protected override void ApplyModifiedPropertiesInternal(Object[] targets)
{
if (!_cullingMethodProp.hasMultipleDifferentValues)
{
foreach (var target in targets)
{
(target as DC_SourceSettings).GetStrategy<DC_LODGroupSourceSettingsStrategy>()
.CullingMethod = (CullingMethod)_cullingMethodProp.enumValueIndex;
}
}
}
}
private class CustomSourceSettingsStrategyEditor : SourceSettingsStrategyEditor
{
private static BoxBoundsHandle BoundsHandle;
private SerializedProperty _strategyProp;
private SerializedProperty _localBoundsProp;
private SerializedProperty _onVisibleEventProp;
private SerializedProperty _onInvisibleEventProp;
public override void OnSceneGUI(DC_SourceSettings target)
{
if (BoundsHandle == null)
BoundsHandle = new BoxBoundsHandle();
DC_CustomSourceSettingsStrategy strategy =
target.GetStrategy<DC_CustomSourceSettingsStrategy>();
Bounds localBounds = strategy.LocalBounds;
BoundsHandle.center = target.transform.position + localBounds.center;
BoundsHandle.size = localBounds.size;
BoundsHandle.DrawHandle();
localBounds.center = BoundsHandle.center - target.transform.position;
localBounds.size = BoundsHandle.size;
strategy.LocalBounds = localBounds;
}
protected override void OnContextSet()
{
_strategyProp = Context.FindProperty("_strategy");
_localBoundsProp = _strategyProp.FindPropertyRelative("_localBounds");
_onVisibleEventProp = _strategyProp.FindPropertyRelative("_onVisible");
_onInvisibleEventProp = _strategyProp.FindPropertyRelative("_onInvisible");
}
protected override void DrawPropertiesInternal()
{
EditorGUILayout.Space();
if (_strategyProp.hasMultipleDifferentValues)
{
EditorGUILayout.HelpBox("Multiediting is not supported for such SourceType", MessageType.Info, true);
return;
}
EditorGUILayout.PropertyField(_localBoundsProp);
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.PropertyField(_onVisibleEventProp);
EditorGUILayout.Space();
EditorGUILayout.PropertyField(_onInvisibleEventProp);
}
protected override void ApplyModifiedPropertiesInternal(Object[] targets)
{
if (_strategyProp.hasMultipleDifferentValues)
return;
Context.ApplyModifiedProperties();
}
}
}
}

View File

@ -0,0 +1,79 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
namespace NGS.AdvancedCullingSystem.Static
{
[CanEditMultipleObjects]
[CustomEditor(typeof(CameraZone))]
public class CameraZoneEditor : Editor
{
protected new CameraZone target
{
get
{
return base.target as CameraZone;
}
}
private static bool DrawGizmo = true;
private static BinaryTreeDrawer TreeDrawer;
private BoxBoundsHandle _boundsHandle;
private void OnEnable()
{
_boundsHandle = new BoxBoundsHandle();
if (TreeDrawer == null)
{
TreeDrawer = new BinaryTreeDrawer();
TreeDrawer.Color = Color.white;
}
}
public override void OnInspectorGUI()
{
if (target.VisibilityTree != null)
{
DrawGizmo = EditorGUILayout.Toggle("Draw Gizmo", DrawGizmo);
EditorGUILayout.HelpBox("Cells Count : " + target.CellsCount, MessageType.None);
if (GUILayout.Button("Clear"))
target.ClearVisibilityTree();
}
}
[DrawGizmo(GizmoType.Selected | GizmoType.Active)]
private static void OnDrawGizmos(CameraZone cameraZone, GizmoType gizmoType)
{
if (!DrawGizmo)
return;
if (cameraZone.VisibilityTree != null)
{
TreeDrawer.DrawTreeGizmos(cameraZone.VisibilityTree.Root);
}
}
private void OnSceneGUI()
{
if (target.VisibilityTree != null)
return;
Transform transform = target.transform;
_boundsHandle.center = transform.position;
_boundsHandle.size = transform.localScale;
_boundsHandle.DrawHandle();
transform.position = _boundsHandle.center;
transform.localScale = _boundsHandle.size;
}
}
}

View File

@ -0,0 +1,74 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace NGS.AdvancedCullingSystem.Static
{
[CustomEditor(typeof(StaticCullingCamera))]
public class StaticCullingCameraEditor : Editor
{
private static bool ShowFrustum;
protected new StaticCullingCamera target
{
get
{
return base.target as StaticCullingCamera;
}
}
private SerializedProperty _drawCellsProp;
private SerializedProperty _toleranceProp;
private Camera _camera;
private void OnEnable()
{
_drawCellsProp = serializedObject.FindProperty("_drawCells");
_toleranceProp = serializedObject.FindProperty("_tolerance");
_camera = target.GetComponent<Camera>();
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUI.BeginChangeCheck();
ShowFrustum = EditorGUILayout.Toggle("Show Frustum", ShowFrustum);
if (EditorGUI.EndChangeCheck())
ResetSceneCamerasCullingMatrices();
EditorGUILayout.PropertyField(_drawCellsProp);
_toleranceProp.floatValue = EditorGUILayout.Slider("Tolerance", _toleranceProp.floatValue, 0, 3);
serializedObject.ApplyModifiedProperties();
}
private void OnSceneGUI()
{
if (!Application.isPlaying)
return;
if (!ShowFrustum)
return;
foreach (var camera in SceneView.GetAllSceneCameras())
camera.cullingMatrix = _camera.cullingMatrix;
}
private void OnDisable()
{
ResetSceneCamerasCullingMatrices();
}
private void ResetSceneCamerasCullingMatrices()
{
foreach (var camera in SceneView.GetAllSceneCameras())
camera.ResetCullingMatrix();
}
}
}

View File

@ -0,0 +1,153 @@
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace NGS.AdvancedCullingSystem.Static
{
public class CameraZonesSelectionWindow : EditorWindow
{
private StaticCullingController _controller;
private static GUIStyle TitleLabelStyle;
private static GUIStyle HeaderLabelStyle;
private static GUIStyle ButtonGUIStyle;
public void Initialize(StaticCullingController controller)
{
_controller = controller;
}
private void OnGUI()
{
if (_controller == null)
Close();
if (Application.isPlaying)
{
Debug.Log("Can't open window in runtime");
Close();
}
if (TitleLabelStyle == null)
CreateGUIStyles();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Camera Zones", TitleLabelStyle);
EditorHelper.DrawSeparatorLine(1, 2);
EditorGUILayout.Space();
IReadOnlyList<CameraZone> cameraZones = _controller.CameraZones;
if (cameraZones != null)
{
int i = 0;
while (i < cameraZones.Count)
{
CameraZone zone = cameraZones[i];
EditorGUILayout.BeginHorizontal();
EditorGUILayout.ObjectField(cameraZones[i], typeof(CameraZone), false);
if (GUILayout.Button("Select"))
Select(zone);
if (GUILayout.Button("Clear"))
Clear(zone);
if (GUILayout.Button("Delete"))
Delete(zone);
EditorGUILayout.EndHorizontal();
i++;
}
}
EditorGUILayout.Space();
if (GUILayout.Button("Create New", ButtonGUIStyle))
CreateNew();
if (GUILayout.Button("Add Selected", ButtonGUIStyle))
AddSelected();
}
private void CreateGUIStyles()
{
TitleLabelStyle = new GUIStyle();
TitleLabelStyle.fontSize = 24;
TitleLabelStyle.fontStyle = FontStyle.Bold;
TitleLabelStyle.alignment = TextAnchor.MiddleCenter;
TitleLabelStyle.normal.textColor = Color.white;
HeaderLabelStyle = new GUIStyle();
HeaderLabelStyle.fontSize = 17;
HeaderLabelStyle.fontStyle = FontStyle.Bold;
HeaderLabelStyle.alignment = TextAnchor.MiddleLeft;
HeaderLabelStyle.normal.textColor = Color.white;
ButtonGUIStyle = new GUIStyle(GUI.skin.button);
ButtonGUIStyle.fontSize = 12;
ButtonGUIStyle.fixedHeight = 24;
ButtonGUIStyle.margin = new RectOffset(5, 5, 5, 5);
ButtonGUIStyle.border = new RectOffset(0, 0, 0, 0);
ButtonGUIStyle.padding = new RectOffset(5, 5, 5, 5);
}
private void Select(CameraZone zone)
{
Selection.activeObject = zone.gameObject;
}
private void Clear(CameraZone zone)
{
_controller.RemoveCameraZone(zone);
}
private void Delete(CameraZone zone)
{
_controller.RemoveCameraZone(zone);
DestroyImmediate(zone.gameObject);
}
private void CreateNew()
{
GameObject go = new GameObject("Camera Zone");
go.transform.localScale = Vector3.one * 10;
CameraZone zone = go.AddComponent<CameraZone>();
_controller.AddCameraZone(zone);
}
private void AddSelected()
{
int count = 0;
foreach (var go in Selection.gameObjects)
{
CameraZone[] zones = go.GetComponentsInChildren<CameraZone>();
if (zones == null)
continue;
foreach (var zone in zones)
{
if (_controller.AddCameraZone(zone))
count++;
}
}
Debug.Log("Added " + count + " new camera zones");
}
}
}

View File

@ -0,0 +1,961 @@
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace NGS.AdvancedCullingSystem.Static
{
public class SourcesSelectionWindow : EditorWindow
{
private static GUIStyle TitleLabelStyle;
private static GUIStyle HeaderLabelStyle;
private static GUIStyle ButtonGUIStyle;
private StaticCullingController _controller;
private string[] _tabNames;
private ITab[] _tabs;
private int _tabIndex = 0;
public void Initialize(StaticCullingController controller)
{
_controller = controller;
}
private void OnEnable()
{
name = "Objects Selection";
_tabNames = new string[] { "Cameras", "Renderers", "LODGroups", "Lights", "Custom" };
_tabs = new ITab[]
{
new CamerasTab(),
new RenderersTab(),
new LODGroupsTab(),
new LightsTab(),
new CustomTab()
};
foreach (var tab in _tabs)
tab.Refresh();
}
private void OnGUI()
{
if (_controller == null)
Close();
if (Application.isPlaying)
{
Close();
Debug.Log("Objects selection not available in runtime");
}
if (TitleLabelStyle == null)
CreateGUIStyles();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Objects Selection", TitleLabelStyle);
EditorHelper.DrawSeparatorLine(1, 2);
EditorGUILayout.Space();
_tabIndex = GUILayout.Toolbar(_tabIndex, _tabNames, ButtonGUIStyle);
EditorGUILayout.Space();
EditorGUILayout.Space();
bool sceneChanged = false;
_tabs[_tabIndex].OnInspectorGUI(ref sceneChanged);
if (sceneChanged)
{
foreach (var tab in _tabs)
tab.Refresh();
EditorUtility.SetDirty(_controller);
}
}
private void CreateGUIStyles()
{
TitleLabelStyle = new GUIStyle();
TitleLabelStyle.fontSize = 24;
TitleLabelStyle.fontStyle = FontStyle.Bold;
TitleLabelStyle.alignment = TextAnchor.MiddleCenter;
TitleLabelStyle.normal.textColor = Color.white;
HeaderLabelStyle = new GUIStyle();
HeaderLabelStyle.fontSize = 17;
HeaderLabelStyle.fontStyle = FontStyle.Bold;
HeaderLabelStyle.alignment = TextAnchor.MiddleLeft;
HeaderLabelStyle.normal.textColor = Color.white;
ButtonGUIStyle = new GUIStyle(GUI.skin.button);
ButtonGUIStyle.fontSize = 12;
ButtonGUIStyle.fixedHeight = 24;
ButtonGUIStyle.margin = new RectOffset(5, 5, 5, 5);
ButtonGUIStyle.border = new RectOffset(0, 0, 0, 0);
ButtonGUIStyle.padding = new RectOffset(5, 5, 5, 5);
}
private void DrawCustomTab()
{
EditorGUILayout.Space();
EditorGUILayout.HelpBox("To set a custom CullingSource you need to manually attach " +
"the 'StaticCullingSource' script to the object, specify the 'SourceType' as Custom, " +
"and then configure the 'StaticCullingSource' component.", MessageType.Info);
EditorGUILayout.Space();
EditorGUILayout.LabelField("Custom Sources : 124", HeaderLabelStyle);
EditorGUILayout.Space();
EditorGUILayout.Toggle("DrawGizmo", true);
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
GUILayout.Button("Clear All", ButtonGUIStyle);
GUILayout.Button("Clear Selected", ButtonGUIStyle);
EditorGUILayout.EndHorizontal();
GUILayout.Button("Select", ButtonGUIStyle);
EditorGUILayout.Space();
EditorGUILayout.LabelField("Not Valid Custom Sources : 124", HeaderLabelStyle);
EditorGUILayout.Space();
EditorGUILayout.BeginVertical();
EditorGUILayout.BeginHorizontal();
GUILayout.Button("Print", ButtonGUIStyle);
GUILayout.Button("Select", ButtonGUIStyle);
EditorGUILayout.EndHorizontal();
GUILayout.Button("Clear All", ButtonGUIStyle);
EditorGUILayout.EndVertical();
}
private interface ITab
{
void Refresh();
void OnInspectorGUI(ref bool sceneChanged);
}
private abstract class TabTemplate : ITab
{
protected abstract string SourceName { get; }
protected abstract bool CanExistsNotValidSources { get; }
protected abstract bool ShowOnlyStaticToggle { get; }
protected abstract bool ShowSelectButton { get; }
protected abstract bool ShowVerifyButton { get; }
protected bool AssignOnlyStatic { get; private set; }
protected int SourcesCount { get; private set; }
protected int NotValidSourcesCount { get; private set; }
public virtual void Refresh()
{
SourcesCount = 0;
NotValidSourcesCount = 0;
foreach (var go in FindObjectsOfType<GameObject>())
{
if (ContainsSource(go))
{
SourcesCount++;
if (CanExistsNotValidSources && GetValidationError(go) != "")
NotValidSourcesCount++;
}
}
}
public virtual void OnInspectorGUI(ref bool sceneChanged)
{
BeforeOnGUI();
EditorGUILayout.LabelField(SourceName + " : " + SourcesCount, HeaderLabelStyle);
EditorGUILayout.Space();
EditorGUILayout.Space();
if (ShowVerifyButton)
{
if (GUILayout.Button("Verify Sources", ButtonGUIStyle))
VerifySources(ref sceneChanged);
EditorGUILayout.Space();
}
BeforeDrawContent();
if (ShowOnlyStaticToggle)
AssignOnlyStatic = EditorGUILayout.Toggle("Assign Only Static", AssignOnlyStatic);
EditorGUILayout.Space();
DrawSourcesButtons(ref sceneChanged);
if (CanExistsNotValidSources)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Not Valid " + SourceName + " : " + NotValidSourcesCount,
HeaderLabelStyle);
DrawNotValidSourcesButtons(ref sceneChanged);
}
AfterOnGUI();
}
protected virtual void BeforeOnGUI()
{
}
protected virtual void BeforeDrawContent()
{
}
protected virtual void DrawSourcesButtons(ref bool sceneChanged)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.BeginVertical();
if (GUILayout.Button("Assign Auto", ButtonGUIStyle))
AssignAutoButtonClick(ref sceneChanged);
if (GUILayout.Button("Clear All", ButtonGUIStyle))
ClearAllButtonClick(ref sceneChanged);
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical();
if (GUILayout.Button("Assign Selected", ButtonGUIStyle))
AssignSelectedButtonClick(ref sceneChanged);
if (GUILayout.Button("Clear Selected", ButtonGUIStyle))
ClearSelectedButtonClick(ref sceneChanged);
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
if (ShowSelectButton)
{
if (GUILayout.Button("Select", ButtonGUIStyle))
SelectButtonClick(ref sceneChanged);
}
}
protected virtual void DrawNotValidSourcesButtons(ref bool sceneChanged)
{
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.BeginVertical();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Print", ButtonGUIStyle))
NotValidPrintButtonClick(ref sceneChanged);
if (GUILayout.Button("Select", ButtonGUIStyle))
NotValidSelectButtonClick(ref sceneChanged);
EditorGUILayout.EndHorizontal();
if (GUILayout.Button("Clear All", ButtonGUIStyle))
NotValidClearButtonClick(ref sceneChanged);
EditorGUILayout.EndVertical();
}
protected virtual void AfterOnGUI()
{
}
protected abstract bool ContainsSource(GameObject go);
protected abstract bool CanAssignTo(GameObject go);
protected abstract void AssignSourceTo(GameObject go);
protected abstract void ClearSourceFrom(GameObject go);
protected abstract bool ValidateSource(GameObject go, out string error);
protected abstract string GetValidationError(GameObject go);
protected void VerifySources(ref bool sceneChanged)
{
foreach (var go in FindObjectsOfType<GameObject>().Where(go => ContainsSource(go)))
ValidateSource(go, out string error);
sceneChanged = true;
}
protected void AssignAutoButtonClick(ref bool sceneChanged)
{
int count = 0;
foreach (var go in FindObjectsOfType<GameObject>())
{
if (ContainsSource(go))
continue;
if (AssignOnlyStatic && !go.isStatic)
continue;
if (go.GetComponent<StaticCullingSource>() != null)
continue;
if (go.GetComponent<CullingTarget>() != null)
continue;
if (CanAssignTo(go))
{
AssignSourceTo(go);
sceneChanged = true;
count++;
}
}
Debug.Log("Assigned " + count + " new sources");
}
protected void AssignSelectedButtonClick(ref bool sceneChanged)
{
GameObject[] gos = Selection.gameObjects
.SelectMany(go => go.GetComponentsInChildren<Transform>()
.Select(t => t.gameObject))
.ToArray();
int count = 0;
foreach (var go in gos)
{
if (ContainsSource(go))
continue;
if (AssignOnlyStatic && !go.isStatic)
continue;
if (go.GetComponent<StaticCullingSource>() != null)
continue;
if (go.GetComponent<CullingTarget>() != null)
continue;
if (CanAssignTo(go))
{
AssignSourceTo(go);
sceneChanged = true;
count++;
}
}
Debug.Log("Assigned " + count + " new sources");
}
protected void ClearAllButtonClick(ref bool sceneChanged)
{
int count = 0;
foreach (var go in FindObjectsOfType<GameObject>())
{
if (ContainsSource(go))
{
ClearSourceFrom(go);
sceneChanged = true;
count++;
}
}
Debug.Log("Cleared " + count + " sources");
}
protected void ClearSelectedButtonClick(ref bool sceneChanged)
{
GameObject[] gos = Selection.gameObjects
.SelectMany(go => go.GetComponentsInChildren<Transform>()
.Select(t => t.gameObject))
.ToArray();
int count = 0;
foreach (var go in gos)
{
if (ContainsSource(go))
{
ClearSourceFrom(go);
sceneChanged = true;
count++;
}
}
Debug.Log("Cleared " + count + " sources");
}
protected void SelectButtonClick(ref bool sceneChanged)
{
GameObject[] gos = FindObjectsOfType<GameObject>()
.Where(go => ContainsSource(go))
.ToArray();
Selection.objects = gos;
}
protected void NotValidPrintButtonClick(ref bool sceneChanged)
{
foreach (var go in FindObjectsOfType<GameObject>())
{
if (ContainsSource(go))
{
string error = GetValidationError(go);
if (error == "")
continue;
Debug.Log(go.name + " : " + error);
}
}
}
protected void NotValidClearButtonClick(ref bool sceneChanged)
{
int count = 0;
foreach (var go in FindObjectsOfType<GameObject>())
{
if (ContainsSource(go))
{
if (!ValidateSource(go, out string error))
{
ClearSourceFrom(go);
sceneChanged = true;
count++;
}
}
}
Debug.Log("Cleared " + count + " not valid sources");
}
protected void NotValidSelectButtonClick(ref bool sceneChanged)
{
List<UnityEngine.Object> notValidGos = new List<UnityEngine.Object>();
foreach (var go in FindObjectsOfType<GameObject>())
{
if (ContainsSource(go))
{
string error = GetValidationError(go);
if (error != "")
notValidGos.Add(go);
}
}
Selection.objects = notValidGos.ToArray();
}
}
private class CamerasTab : TabTemplate
{
protected override string SourceName
{
get
{
return "Cameras";
}
}
protected override bool ShowOnlyStaticToggle
{
get
{
return false;
}
}
protected override bool CanExistsNotValidSources
{
get
{
return false;
}
}
protected override bool ShowVerifyButton
{
get
{
return false;
}
}
protected override bool ShowSelectButton
{
get
{
return true;
}
}
protected override void BeforeDrawContent()
{
StaticCullingCamera.DrawGizmo = EditorGUILayout.Toggle("Draw Gizmo",
StaticCullingCamera.DrawGizmo);
}
protected override bool ContainsSource(GameObject go)
{
return go.GetComponent<StaticCullingCamera>() != null;
}
protected override bool CanAssignTo(GameObject go)
{
return go.activeInHierarchy && go.GetComponent<Camera>() != null;
}
protected override void AssignSourceTo(GameObject go)
{
go.AddComponent<StaticCullingCamera>();
}
protected override void ClearSourceFrom(GameObject go)
{
DestroyImmediate(go.GetComponent<StaticCullingCamera>());
}
protected override string GetValidationError(GameObject go)
{
throw new NotSupportedException();
}
protected override bool ValidateSource(GameObject go, out string error)
{
throw new NotSupportedException();
}
}
private class RenderersTab : TabTemplate
{
protected override string SourceName
{
get
{
return "Renderers";
}
}
protected override bool ShowOnlyStaticToggle
{
get
{
return true;
}
}
protected override bool CanExistsNotValidSources
{
get
{
return true;
}
}
protected override bool ShowVerifyButton
{
get
{
return true;
}
}
protected override bool ShowSelectButton
{
get
{
return false;
}
}
protected override void BeforeDrawContent()
{
StaticCullingSource.DrawGizmoRenderers = EditorGUILayout.Toggle("Draw Gizmo",
StaticCullingSource.DrawGizmoRenderers);
}
protected override void AssignSourceTo(GameObject go)
{
StaticCullingSource source = go.AddComponent<StaticCullingSource>();
source.SourceType = SourceType.MeshRenderer;
}
protected override bool CanAssignTo(GameObject go)
{
MeshRenderer renderer = go.GetComponent<MeshRenderer>();
return go.activeInHierarchy && renderer != null && renderer.enabled &&
go.GetComponentInParent<LODGroup>() == null;
}
protected override void ClearSourceFrom(GameObject go)
{
DestroyImmediate(go.GetComponent<StaticCullingSource>());
}
protected override string GetValidationError(GameObject go)
{
return go.GetComponent<StaticCullingSource>().ValidationError;
}
protected override bool ContainsSource(GameObject go)
{
StaticCullingSource source = go.GetComponent<StaticCullingSource>();
return source != null && source.SourceType == SourceType.MeshRenderer;
}
protected override bool ValidateSource(GameObject go, out string error)
{
StaticCullingSource source = go.GetComponent<StaticCullingSource>();
bool isValid = source.Validate();
error = source.ValidationError;
return isValid;
}
}
private class LODGroupsTab : TabTemplate
{
protected override string SourceName
{
get
{
return "LODGroups";
}
}
protected override bool CanExistsNotValidSources
{
get
{
return true;
}
}
protected override bool ShowOnlyStaticToggle
{
get
{
return true;
}
}
protected override bool ShowSelectButton
{
get
{
return false;
}
}
protected override bool ShowVerifyButton
{
get
{
return true;
}
}
protected override void BeforeDrawContent()
{
StaticCullingSource.DrawGizmoLODGroups = EditorGUILayout.Toggle("Draw Gizmo",
StaticCullingSource.DrawGizmoLODGroups);
}
protected override bool ValidateSource(GameObject go, out string error)
{
StaticCullingSource source = go.GetComponent<StaticCullingSource>();
bool isValid = source.Validate();
error = source.ValidationError;
return isValid;
}
protected override string GetValidationError(GameObject go)
{
return go.GetComponent<StaticCullingSource>().ValidationError;
}
protected override bool ContainsSource(GameObject go)
{
StaticCullingSource source = go.GetComponent<StaticCullingSource>();
return source != null && source.SourceType == SourceType.LODGroup;
}
protected override bool CanAssignTo(GameObject go)
{
return go.activeInHierarchy && go.GetComponent<LODGroup>() != null;
}
protected override void AssignSourceTo(GameObject go)
{
StaticCullingSource source = go.AddComponent<StaticCullingSource>();
source.SourceType = SourceType.LODGroup;
}
protected override void ClearSourceFrom(GameObject go)
{
DestroyImmediate(go.GetComponent<StaticCullingSource>());
}
}
private class LightsTab : TabTemplate
{
protected override string SourceName
{
get
{
return "Lights";
}
}
protected override bool CanExistsNotValidSources
{
get
{
return true;
}
}
protected override bool ShowOnlyStaticToggle
{
get
{
return false;
}
}
protected override bool ShowSelectButton
{
get
{
return true;
}
}
protected override bool ShowVerifyButton
{
get
{
return true;
}
}
protected override void BeforeOnGUI()
{
EditorGUILayout.HelpBox("To avoid errors, you can only add PointLights in this window. " +
"To add other light sources - you need to manually " +
"attach 'StaticCullingSource' script " +
"to your Light, then specify SourceType as 'Light' " +
"and set up the bounding box.", MessageType.Info);
EditorGUILayout.Space();
}
protected override void BeforeDrawContent()
{
StaticCullingSource.DrawGizmoLights = EditorGUILayout.Toggle("Draw Gizmo",
StaticCullingSource.DrawGizmoLights);
}
protected override bool ValidateSource(GameObject go, out string error)
{
StaticCullingSource source = go.GetComponent<StaticCullingSource>();
bool isValid = source.Validate();
error = source.ValidationError;
return isValid;
}
protected override string GetValidationError(GameObject go)
{
return go.GetComponent<StaticCullingSource>().ValidationError;
}
protected override bool ContainsSource(GameObject go)
{
StaticCullingSource source = go.GetComponent<StaticCullingSource>();
return source != null && source.SourceType == SourceType.Light;
}
protected override bool CanAssignTo(GameObject go)
{
Light light = go.GetComponent<Light>();
return light != null && light.type == LightType.Point;
}
protected override void AssignSourceTo(GameObject go)
{
StaticCullingSource source = go.AddComponent<StaticCullingSource>();
source.SourceType = SourceType.Light;
}
protected override void ClearSourceFrom(GameObject go)
{
DestroyImmediate(go.GetComponent<StaticCullingSource>());
}
}
private class CustomTab : TabTemplate
{
protected override string SourceName
{
get
{
return "Custom";
}
}
protected override bool CanExistsNotValidSources
{
get
{
return true;
}
}
protected override bool ShowOnlyStaticToggle
{
get
{
return false;
}
}
protected override bool ShowSelectButton
{
get
{
return true;
}
}
protected override bool ShowVerifyButton
{
get
{
return true;
}
}
protected override void BeforeOnGUI()
{
EditorGUILayout.HelpBox("To set a custom CullingSource you need to manually attach " +
"the 'StaticCullingSource' script to the object, specify the 'SourceType' as Custom, " +
"and then configure the 'StaticCullingSource' component.", MessageType.Info);
EditorGUILayout.Space();
}
protected override void BeforeDrawContent()
{
StaticCullingSource.DrawGizmoCustom = EditorGUILayout.Toggle("Draw Gizmo",
StaticCullingSource.DrawGizmoCustom);
}
protected override void DrawSourcesButtons(ref bool sceneChanged)
{
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Clear All", ButtonGUIStyle))
ClearAllButtonClick(ref sceneChanged);
if (GUILayout.Button("Clear Selected", ButtonGUIStyle))
ClearSelectedButtonClick(ref sceneChanged);
EditorGUILayout.EndHorizontal();
if (ShowSelectButton)
{
if (GUILayout.Button("Select", ButtonGUIStyle))
SelectButtonClick(ref sceneChanged);
}
}
protected override bool ContainsSource(GameObject go)
{
StaticCullingSource source = go.GetComponent<StaticCullingSource>();
return source != null && source.SourceType == SourceType.Custom;
}
protected override bool CanAssignTo(GameObject go)
{
throw new NotSupportedException();
}
protected override void AssignSourceTo(GameObject go)
{
throw new NotSupportedException();
}
protected override void ClearSourceFrom(GameObject go)
{
DestroyImmediate(go.GetComponent<StaticCullingSource>());
}
protected override string GetValidationError(GameObject go)
{
return go.GetComponent<StaticCullingSource>().ValidationError;
}
protected override bool ValidateSource(GameObject go, out string error)
{
StaticCullingSource source = go.GetComponent<StaticCullingSource>();
bool isValid = source.Validate();
error = source.ValidationError;
return isValid;
}
}
}
}

View File

@ -0,0 +1,236 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.EditorTools;
namespace NGS.AdvancedCullingSystem.Static
{
[CustomEditor(typeof(StaticCullingController))]
public class StaticCullingControllerEditor : Editor
{
protected new StaticCullingController target
{
get
{
return (StaticCullingController)base.target;
}
}
private static GUIStyle TitleLabelStyle;
private static GUIStyle HeaderLabelStyle;
private static GUIStyle ButtonGUIStyle;
private bool _sceneContainsBakedData;
[MenuItem("Tools/NGSTools/Advanced Culling System/Static")]
private static void CreateController()
{
GameObject go = new GameObject("StaticCullingController");
go.AddComponent<StaticCullingController>();
Selection.activeGameObject = go;
}
private void OnEnable()
{
CreateLayerIfNotExist();
Refresh();
}
public override void OnInspectorGUI()
{
if (TitleLabelStyle == null)
CreateGUIStyles();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Static Culling", TitleLabelStyle);
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Step 1. Objects Selection", HeaderLabelStyle);
EditorHelper.DrawSeparatorLine(1, 2);
DrawStep1();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Step 2. Scene Partitioning", HeaderLabelStyle);
EditorHelper.DrawSeparatorLine(1, 2);
DrawStep2();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Step 3. Camera Zones", HeaderLabelStyle);
EditorHelper.DrawSeparatorLine(1, 2);
DrawStep3();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Step 4. Baking", HeaderLabelStyle);
EditorHelper.DrawSeparatorLine(1, 2);
DrawStep4();
}
private void Refresh()
{
_sceneContainsBakedData = false;
if (FindObjectsOfType<CullingTarget>().Length > 0)
{
_sceneContainsBakedData = true;
return;
}
foreach (var zone in FindObjectsOfType<CameraZone>())
{
if (zone.VisibilityTree != null && zone.VisibilityTree.CullingTargets != null)
{
_sceneContainsBakedData = true;
return;
}
}
}
private void CreateLayerIfNotExist()
{
string layer = StaticCullingPreferences.LayerName;
if (!LayersHelper.IsLayerExist(layer))
{
LayersHelper.CreateLayer(layer);
LayersHelper.DisableCollisions(LayerMask.NameToLayer(layer));
}
}
private void CreateGUIStyles()
{
TitleLabelStyle = new GUIStyle();
TitleLabelStyle.fontSize = 24;
TitleLabelStyle.fontStyle = FontStyle.Bold;
TitleLabelStyle.alignment = TextAnchor.MiddleCenter;
TitleLabelStyle.normal.textColor = Color.white;
HeaderLabelStyle = new GUIStyle();
HeaderLabelStyle.fontSize = 17;
HeaderLabelStyle.fontStyle = FontStyle.Bold;
HeaderLabelStyle.alignment = TextAnchor.MiddleLeft;
HeaderLabelStyle.normal.textColor = Color.white;
ButtonGUIStyle = new GUIStyle(GUI.skin.button);
ButtonGUIStyle.fontSize = 12;
ButtonGUIStyle.fixedHeight = 24;
ButtonGUIStyle.margin = new RectOffset(5, 5, 5, 5);
ButtonGUIStyle.border = new RectOffset(0, 0, 0, 0);
ButtonGUIStyle.padding = new RectOffset(5, 5, 5, 5);
}
private void DrawStep1()
{
EditorGUILayout.HelpBox("Add cameras and objects to be culled", MessageType.None);
if (GUILayout.Button("Open Selection Tool", ButtonGUIStyle))
{
EditorWindow.GetWindow<SourcesSelectionWindow>().Initialize(target);
}
}
private void DrawStep2()
{
EditorGUILayout.HelpBox("Partition the scene into cells of optimal size. " +
"If a cell is visible, all objects inside this cell will be enabled. " +
"The more cells - the more objects will be culled, " +
"but the longer the baking time will be.", MessageType.None);
target.DrawGeometryTreeGizmo = EditorGUILayout.Toggle("Draw Gizmo",
target.DrawGeometryTreeGizmo);
EditorGUI.BeginChangeCheck();
target.GeometryTreeDepth = EditorGUILayout.IntSlider("Partition",
target.GeometryTreeDepth, 7, 20);
if (EditorGUI.EndChangeCheck())
EditorUtility.SetDirty(target);
EditorGUILayout.Space();
if (GUILayout.Button("Update", ButtonGUIStyle))
target.CreatePreviewGeometryTree();
}
private void DrawStep3()
{
EditorGUILayout.HelpBox("Select the areas where cameras can be located during gameplay. " +
"Divide these areas into cells. " +
"The smaller the cell, the more accurate the objects will be culled, " +
"but the longer the baking time.", MessageType.None);
target.DrawCameraZones = EditorGUILayout.Toggle("Draw Gizmo", target.DrawCameraZones);
EditorGUI.BeginChangeCheck();
target.CellSize = EditorGUILayout.FloatField("Cell Size", target.CellSize);
if (EditorGUI.EndChangeCheck())
EditorUtility.SetDirty(target);
EditorGUILayout.HelpBox("Total Cells Count : " + target.TotalCellsCount, MessageType.None);
EditorGUILayout.Space();
if (GUILayout.Button("Update", ButtonGUIStyle))
target.CreatePreviewCameraZones();
if (GUILayout.Button("Open Selection Tool", ButtonGUIStyle))
{
var window = EditorWindow.GetWindow<CameraZonesSelectionWindow>();
window.Initialize(target);
}
}
private void DrawStep4()
{
EditorGUILayout.HelpBox("Check the settings in each step again. " +
"Specify the number of rays per unit and press bake.", MessageType.None);
EditorGUI.BeginChangeCheck();
target.RaysPerUnit = EditorGUILayout.FloatField("Rays Per Unit", target.RaysPerUnit);
target.MaxRaysPerSource = EditorGUILayout.IntField("Max Rays Per Source", target.MaxRaysPerSource);
EditorGUILayout.Space();
if (GUILayout.Button("Bake", ButtonGUIStyle))
{
target.Bake();
Refresh();
}
EditorGUI.BeginDisabledGroup(!_sceneContainsBakedData);
if (GUILayout.Button("Clear", ButtonGUIStyle))
{
target.Clear();
Refresh();
}
EditorGUI.EndDisabledGroup();
if (EditorGUI.EndChangeCheck())
EditorUtility.SetDirty(target);
}
}
}

View File

@ -0,0 +1,198 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
namespace NGS.AdvancedCullingSystem.Static
{
[CanEditMultipleObjects]
[CustomEditor(typeof(StaticCullingSource))]
public class StaticCullingSourceEditor : Editor
{
protected new StaticCullingSource target
{
get
{
return base.target as StaticCullingSource;
}
}
private SerializedProperty _validationErrorProp;
private SerializedProperty _sourceTypeProp;
private SerializedProperty _strategyProp;
private BoxBoundsHandle _boundsHandle;
public void OnEnable()
{
_boundsHandle = new BoxBoundsHandle();
_validationErrorProp = serializedObject.FindProperty("_validationError");
_sourceTypeProp = serializedObject.FindProperty("_sourceType");
_strategyProp = serializedObject.FindProperty("_strategy");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
DrawHelpBoxes();
if (DrawProperties())
ApplyModifiedProperties();
EditorGUILayout.Space();
serializedObject.Update();
DrawStrategyProperties();
serializedObject.ApplyModifiedProperties();
EditorGUILayout.Space();
if (GUILayout.Button("Verify"))
{
foreach (var target in targets)
{
StaticCullingSource current = target as StaticCullingSource;
if (current.Validate())
Debug.Log(current.gameObject.name + " is valid");
else
Debug.Log(current.gameObject.name + " not valid");
}
}
}
private void OnSceneGUI()
{
SourceType type = target.SourceType;
Bounds localBounds = default;
if (type == SourceType.Light)
localBounds = ((LightStaticCullingSourceStrategy)target.Strategy).LocalBounds;
else if (type == SourceType.Custom)
localBounds = ((CustomStaticCullingSourceStrategy)target.Strategy).LocalBounds;
else
return;
_boundsHandle.center = target.transform.position + localBounds.center;
_boundsHandle.size = localBounds.size;
_boundsHandle.DrawHandle();
localBounds.center = _boundsHandle.center - target.transform.position;
localBounds.size = _boundsHandle.size;
if (type == SourceType.Light)
((LightStaticCullingSourceStrategy)target.Strategy).LocalBounds = localBounds;
else if (type == SourceType.Custom)
((CustomStaticCullingSourceStrategy)target.Strategy).LocalBounds = localBounds;
}
private void DrawHelpBoxes()
{
if (!_validationErrorProp.hasMultipleDifferentValues)
{
string validationError = _validationErrorProp.stringValue;
if (validationError != "")
EditorGUILayout.HelpBox(validationError, MessageType.Warning);
}
}
private bool DrawProperties()
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_sourceTypeProp);
return EditorGUI.EndChangeCheck();
}
private void ApplyModifiedProperties()
{
foreach (var target in targets)
{
StaticCullingSource current = target as StaticCullingSource;
if (!_sourceTypeProp.hasMultipleDifferentValues)
current.SourceType = (SourceType) _sourceTypeProp.enumValueIndex;
}
}
private void DrawStrategyProperties()
{
if (_sourceTypeProp.hasMultipleDifferentValues)
return;
SourceType type = (SourceType) _sourceTypeProp.enumValueIndex;
if (type == SourceType.MeshRenderer)
DrawMeshRendererSourceStrategy();
else if (type == SourceType.LODGroup)
DrawLODGroupSourceStrategy();
else if (type == SourceType.Light)
DrawLightSourceStrategy();
else if (type == SourceType.Custom)
DrawCustomSourceStrategy();
else
throw new System.NotSupportedException();
}
private void DrawMeshRendererSourceStrategy()
{
SerializedProperty cullingMethodProp = _strategyProp.FindPropertyRelative("_cullingMethod");
SerializedProperty isOccluderProp = _strategyProp.FindPropertyRelative("_isOccluder");
EditorGUILayout.PropertyField(cullingMethodProp);
EditorGUILayout.PropertyField(isOccluderProp);
}
private void DrawLODGroupSourceStrategy()
{
SerializedProperty isOccluderProp = _strategyProp.FindPropertyRelative("_isOccluder");
SerializedProperty cullingMethodProp = _strategyProp.FindPropertyRelative("_cullingMethod");
EditorGUILayout.PropertyField(cullingMethodProp);
EditorGUILayout.PropertyField(isOccluderProp);
}
private void DrawLightSourceStrategy()
{
}
private void DrawCustomSourceStrategy()
{
SerializedProperty isOccluderProp = _strategyProp.FindPropertyRelative("_isOccluder");
SerializedProperty onVisibleProp = _strategyProp.FindPropertyRelative("_onVisible");
SerializedProperty onInvisibleProp = _strategyProp.FindPropertyRelative("_onInvisible");
EditorGUILayout.PropertyField(isOccluderProp);
if (!isOccluderProp.hasMultipleDifferentValues && isOccluderProp.boolValue)
{
SerializedProperty collidersProp = _strategyProp.FindPropertyRelative("_colliders");
EditorGUILayout.PropertyField(collidersProp);
}
EditorGUILayout.Space();
EditorGUILayout.PropertyField(onVisibleProp);
EditorGUILayout.PropertyField(onInvisibleProp);
}
}
}

View File

@ -0,0 +1,24 @@
{
"name": "AdvancedCullingSystem.Runtime",
"rootNamespace": "",
"references": [
"GUID:d8b63aba1907145bea998dd612889d6b",
"GUID:e0cd26848372d4e5c891c569017e11f1",
"GUID:2665a8d13d1b3f18800f46e256720795"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.collections",
"expression": "1.3.1",
"define": "COLLECTIONS_1_3_1_OR_NEWER"
}
],
"noEngineReferences": false
}

View File

@ -0,0 +1,240 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace NGS.AdvancedCullingSystem
{
public abstract class BinaryTree<TNode, TData> where TNode : BinaryTreeNode
{
public BinaryTreeNode Root
{
get
{
return RootInternal;
}
}
[field: SerializeReference]
protected TNode RootInternal { get; private set; }
[field: SerializeField]
public int Height { get; private set; }
[field : SerializeField]
public float CellSize { get; private set; }
private int _maxDepth = -1;
public BinaryTree(float cellSize)
{
CellSize = Mathf.Max(cellSize, 0.1f);
}
public BinaryTree(IList<TData> datas, int maxDepth)
{
if (maxDepth <= 1)
throw new ArgumentException("Max depth should be greater than 1");
_maxDepth = maxDepth;
Vector3 min = Vector3.one * float.MaxValue;
Vector3 max = Vector3.one * float.MinValue;
foreach (var data in datas)
{
Bounds dBounds = GetBounds(data);
Vector3 dMin = dBounds.min;
Vector3 dMax = dBounds.max;
min.x = Mathf.Min(min.x, dMin.x);
min.y = Mathf.Min(min.y, dMin.y);
min.z = Mathf.Min(min.z, dMin.z);
max.x = Mathf.Max(max.x, dMax.x);
max.y = Mathf.Max(max.y, dMax.y);
max.z = Mathf.Max(max.z, dMax.z);
}
RootInternal = CreateNode(min + ((max - min) / 2), max - min + Vector3.one * 0.01f, false);
Height = 1;
foreach (var data in datas)
Add(data);
}
public void Add(TData data)
{
if (Root == null)
{
RootInternal = CreateNode(GetBounds(data).center, Vector3.one * CellSize, true);
Height = 1;
}
if (!Includes(RootInternal, data))
GrowTreeUp(data);
AddInternal(RootInternal, data, 1);
}
private TNode ExpandRoot(TNode root, TData target)
{
Bounds rootBounds = root.Bounds;
Bounds targetBounds = GetBounds(target);
Vector3 parentCenter = Vector3.zero;
Vector3 parentSize = Vector3.zero;
Vector3 childCenter = Vector3.zero;
bool rootIsLeft = false;
for (int i = 0; i < 3; i++)
{
if (targetBounds.min[i] < rootBounds.min[i])
{
parentSize = rootBounds.size;
parentSize[i] *= 2;
parentCenter = rootBounds.center;
parentCenter[i] -= rootBounds.size[i] / 2;
childCenter = rootBounds.center;
childCenter[i] -= rootBounds.size[i];
break;
}
if (targetBounds.max[i] > rootBounds.max[i])
{
parentSize = rootBounds.size;
parentSize[i] *= 2;
parentCenter = rootBounds.center;
parentCenter[i] += rootBounds.size[i] / 2;
childCenter = rootBounds.center;
childCenter[i] += rootBounds.size[i];
rootIsLeft = true;
break;
}
}
TNode parent = CreateNode(parentCenter, parentSize, false);
TNode child = CreateNode(childCenter, rootBounds.size, root.IsLeaf);
if (rootIsLeft)
SetChildsToNode(parent, RootInternal, child);
else
SetChildsToNode(parent, child, RootInternal);
return parent;
}
protected void GrowTreeUp(TData target)
{
if (Includes(RootInternal, target))
return;
RootInternal = ExpandRoot(RootInternal, target);
Height++;
GrowTreeUp(target);
}
protected void GrowTreeDown(TNode node, TData target, int depth)
{
if (node.HasChilds)
throw new Exception("GrowTreeDown::" + depth + " node already has childs");
Bounds nodeBounds = node.Bounds;
Vector3 offset;
Vector3 size;
if (nodeBounds.size.x >= nodeBounds.size.y && nodeBounds.size.x >= nodeBounds.size.z)
{
offset = new Vector3(nodeBounds.size.x / 4, 0, 0);
size = new Vector3(nodeBounds.size.x / 2, nodeBounds.size.y, nodeBounds.size.z);
}
else if (nodeBounds.size.y >= nodeBounds.size.x && nodeBounds.size.y >= nodeBounds.size.z)
{
offset = new Vector3(0, nodeBounds.size.y / 4, 0);
size = new Vector3(nodeBounds.size.x, nodeBounds.size.y / 2, nodeBounds.size.z);
}
else
{
offset = new Vector3(0, 0, nodeBounds.size.z / 4);
size = new Vector3(nodeBounds.size.x, nodeBounds.size.y, nodeBounds.size.z / 2);
}
bool isLeafs = (depth == _maxDepth) ||
(size.x <= CellSize && size.y <= CellSize && size.z <= CellSize);
TNode left = CreateNode(nodeBounds.center - offset, size, isLeafs);
TNode right = CreateNode(nodeBounds.center + offset, size, isLeafs);
SetChildsToNode(node, left, right);
if (isLeafs)
{
if (Height < depth)
Height = depth;
if (CellSize == 0)
CellSize = Mathf.Min(size.x, size.y, size.z);
return;
}
if (Intersects(left, target))
GrowTreeDown(left, target, depth + 1);
if (Intersects(right, target))
GrowTreeDown(right, target, depth + 1);
}
protected bool Intersects(TNode node, TData data)
{
return node.Bounds.Intersects(GetBounds(data));
}
protected bool Includes(TNode node, TData data)
{
return node.Bounds.Contains(GetBounds(data));
}
protected virtual void AddInternal(TNode node, TData data, int depth)
{
if (node.IsLeaf)
{
AddDataToNode(node, data);
return;
}
if (!node.HasChilds)
GrowTreeDown(node, data, depth + 1);
TNode left = (TNode)node.GetLeft();
TNode right = (TNode)node.GetRight();
if (Intersects(left, data))
AddInternal(left, data, depth + 1);
if (Intersects(right, data))
AddInternal(right, data, depth + 1);
}
protected abstract Bounds GetBounds(TData data);
protected abstract TNode CreateNode(Vector3 center, Vector3 size, bool isLeaf);
protected abstract void SetChildsToNode(TNode parent, TNode leftChild, TNode rightChild);
protected abstract void AddDataToNode(TNode node, TData data);
}
}

View File

@ -0,0 +1,25 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace NGS.AdvancedCullingSystem
{
public class BinaryTreeDrawer
{
public Color Color { get; set; }
public void DrawTreeGizmos(BinaryTreeNode root)
{
if (root == null)
return;
Bounds bounds = root.Bounds;
Gizmos.color = Color;
Gizmos.DrawWireCube(bounds.center, bounds.size);
DrawTreeGizmos(root.GetLeft());
DrawTreeGizmos(root.GetRight());
}
}
}

View File

@ -0,0 +1,59 @@
using UnityEngine;
namespace NGS.AdvancedCullingSystem
{
public abstract class BinaryTreeNode
{
public Vector3 Center
{
get
{
return _bounds.center;
}
}
public Vector3 Size
{
get
{
return _bounds.size;
}
}
public Bounds Bounds
{
get
{
return _bounds;
}
}
public bool HasChilds
{
get
{
return GetLeft() != null;
}
}
public bool IsLeaf
{
get
{
return _isLeaf;
}
}
[SerializeField]
private Bounds _bounds;
[SerializeField]
private bool _isLeaf;
public BinaryTreeNode(Vector3 center, Vector3 size, bool isLeaf)
{
_bounds = new Bounds(center, size);
_isLeaf = isLeaf;
}
public abstract BinaryTreeNode GetLeft();
public abstract BinaryTreeNode GetRight();
}
}

View File

@ -0,0 +1,14 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace NGS.AdvancedCullingSystem
{
public static class BoundsHelper
{
public static bool Contains(this Bounds bounds, Bounds target)
{
return bounds.Contains(target.min) && bounds.Contains(target.max);
}
}
}

Some files were not shown because too many files have changed in this diff Show More