diff --git a/unity/Assets/2.5D Engine/Enemy.prefab b/unity/Assets/2.5D Engine/Enemy.prefab index d66132a..4cf9307 100644 --- a/unity/Assets/2.5D Engine/Enemy.prefab +++ b/unity/Assets/2.5D Engine/Enemy.prefab @@ -1,16 +1,17 @@ %YAML 1.1 -%TAG !u! tag:unity3d.com,2011: +%TAG !u! tag:yousandi.cn,2023: --- !u!1 &1886377545685493984 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - serializedVersion: 6 + serializedVersion: 7 m_Component: - component: {fileID: 2387478274195477212} - component: {fileID: 4515059975710397565} m_Layer: 6 + m_HasEditorInfo: 1 m_Name: GFX m_TagString: Untagged m_Icon: {fileID: 0} @@ -50,9 +51,9 @@ SpriteRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 0 m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 + m_virtualGeometry: 0 + m_virtualGeometryShadow: 0 + m_ShadingRate: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -94,15 +95,16 @@ GameObject: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - serializedVersion: 6 + serializedVersion: 7 m_Component: - component: {fileID: 8894851355281676783} - component: {fileID: 8063991991785530743} - component: {fileID: 2347645663305997974} - component: {fileID: 8968468909950613264} - - component: {fileID: 6969309557155133232} - - component: {fileID: 5546728832623823812} + - component: {fileID: 6802842831935334424} + - component: {fileID: 2877034408413616420} m_Layer: 6 + m_HasEditorInfo: 1 m_Name: Enemy m_TagString: Enemy m_Icon: {fileID: 0} @@ -127,7 +129,7 @@ Transform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!95 &8063991991785530743 Animator: - serializedVersion: 7 + serializedVersion: 6 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -138,10 +140,11 @@ Animator: m_Controller: {fileID: 9100000, guid: 22545c7435b1b5b498af21fd0674b6f8, type: 2} m_CullingMode: 0 m_UpdateMode: 0 + m_UpdateFrequencyMode: 0 + m_UpdateFrequency: 0 m_ApplyRootMotion: 0 m_LinearVelocityBlending: 0 m_StabilizeFeet: 0 - m_AnimatePhysics: 0 m_WarningMessage: m_HasTransformHierarchy: 1 m_AllowConstantClipSamplingOptimization: 1 @@ -197,7 +200,7 @@ CapsuleCollider: m_Height: 0.7533474 m_Direction: 1 m_Center: {x: 0, y: 0.42667365, z: 0} ---- !u!114 &6969309557155133232 +--- !u!114 &6802842831935334424 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -206,13 +209,18 @@ MonoBehaviour: m_GameObject: {fileID: 2150025513644625521} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f9e36f6d2e0ea0541bad29e784e0841b, type: 3} + m_Script: {fileID: 11500000, guid: 7f90acf2a29992043bbd5c73f2a563bc, type: 3} m_Name: m_EditorClassIdentifier: - maxHealth: 20 - deathEffect: {fileID: 4806121257990350900, guid: 8ba56a88eb8db7342a07b8f07085b2f8, type: 3} - isPlayer: 0 ---- !u!114 &5546728832623823812 + playerTarget: {fileID: 0} + detectionRange: 8 + chaseSpeed: 3 + stopDistance: 1.2 + chasePersistTime: 3 + listenRange: 15 + bellMoveSpeed: 4 + bellMoveTime: 1.5 +--- !u!114 &2877034408413616420 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -221,23 +229,24 @@ MonoBehaviour: m_GameObject: {fileID: 2150025513644625521} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 04126beb49efb8c49a7ecc822750a0c7, type: 3} + m_Script: {fileID: 11500000, guid: 9665e5f4b5ee9a146a465e4571b5868b, type: 3} m_Name: m_EditorClassIdentifier: - speed: 2 - damageAmount: 20 - spriteRenderer: {fileID: 4515059975710397565} + lockYAxis: 1 + smoothRotation: 0 + rotationSpeed: 8 --- !u!1 &8532340994753211982 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - serializedVersion: 6 + serializedVersion: 7 m_Component: - component: {fileID: 6137875234305197413} - component: {fileID: 5261201738890672811} m_Layer: 6 + m_HasEditorInfo: 1 m_Name: Shadow m_TagString: Untagged m_Icon: {fileID: 0} @@ -276,9 +285,9 @@ SpriteRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 0 m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 + m_virtualGeometry: 0 + m_virtualGeometryShadow: 0 + m_ShadingRate: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: diff --git a/unity/Assets/2.5D Engine/Scripts/EnemyAI.cs b/unity/Assets/2.5D Engine/Scripts/EnemyAI.cs deleted file mode 100644 index 24f0edf..0000000 --- a/unity/Assets/2.5D Engine/Scripts/EnemyAI.cs +++ /dev/null @@ -1,52 +0,0 @@ -using UnityEngine; - -namespace IndianOceanAssets.Engine2_5D -{ - // Controls enemy behavior: follows player and handles collision. - public class EnemyAI : MonoBehaviour - { - private Transform target; // Reference to the player - [SerializeField] private float speed; // Movement speed - [SerializeField] private int damageAmount; // Damage dealt to player - [SerializeField] private SpriteRenderer spriteRenderer; // For flipping sprite - - // Called on start - public void Start() - { - Invoke("AssignPlayer", 1f); // Delay to ensure player exists - } - - // Finds and assigns the player as target - public void AssignPlayer() - { - target = GameObject.FindGameObjectWithTag("Player").transform; - } - - // Called every frame - public void Update() - { - if (target) - { - // Flip sprite based on direction to player - if (target.position.x > transform.position.x) - spriteRenderer.flipX = false; - else - spriteRenderer.flipX = true; - - // Move towards player - transform.position = Vector3.MoveTowards(transform.position, target.position, Time.deltaTime * speed); - } - } - - // Handles collision with player - void OnCollisionEnter(Collision collision) - { - if (collision.collider.CompareTag("Player")) - { - // Damage player and kill self - collision.collider.GetComponent().Damage(damageAmount); - GetComponent().Die(); - } - } - } -} \ No newline at end of file diff --git a/unity/Assets/2.5D Engine/Scripts/EnemySpawner.cs b/unity/Assets/2.5D Engine/Scripts/EnemySpawner.cs deleted file mode 100644 index a75f273..0000000 --- a/unity/Assets/2.5D Engine/Scripts/EnemySpawner.cs +++ /dev/null @@ -1,46 +0,0 @@ -using UnityEngine; -namespace IndianOceanAssets.Engine2_5D -{ - // Spawns enemies at random positions and intervals - public class EnemySpawner : MonoBehaviour - { - [SerializeField] - private GameObject enemyEntity; // Enemy prefab - - [SerializeField] - private Transform[] spawnPosition; // Possible spawn points - - [SerializeField] - private float spawnTime = 4f; // Time between spawns - - // Starts repeated spawning - private void Start() - { - InvokeRepeating("SpawnEnemies", 0f, spawnTime); - } - - // Spawns a random number of enemies at random positions - public void SpawnEnemies() - { - int enemyNo = Random.Range(1, 4); - - for (int i = 0; i < enemyNo; i++) - { - int randomSpawnPosition = Random.Range(0, spawnPosition.Length); - - if (spawnPosition[randomSpawnPosition]) - { - // Randomize spawn position slightly - Vector3 randomUnitCircle = new Vector3(Random.Range(-1f, 1f), .5f, Random.Range(-1f, 1f)); - Instantiate(enemyEntity, spawnPosition[randomSpawnPosition].position + randomUnitCircle, Quaternion.identity); - } - } - - // Decrease spawn time to increase difficulty, but not below 2 seconds - spawnTime -= .5f; - - if (spawnTime <= 2f) - spawnTime = 2f; - } - } -} \ No newline at end of file diff --git a/unity/Assets/Scenes/Test.unity b/unity/Assets/Scenes/Test.unity index 5893a8d..b616ffe 100644 --- a/unity/Assets/Scenes/Test.unity +++ b/unity/Assets/Scenes/Test.unity @@ -1031,7 +1031,7 @@ GameObject: serializedVersion: 7 m_Component: - component: {fileID: 340526137} - - component: {fileID: 340526136} + - component: {fileID: 340526138} m_Layer: 0 m_HasEditorInfo: 1 m_Name: Enemy Spawner @@ -1040,134 +1040,6 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!114 &340526136 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 340526135} - m_Enabled: 0 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c755496b98cf3a743b854c203125bdff, type: 3} - m_Name: - m_EditorClassIdentifier: - enemyEntity: {fileID: 2150025513644625521, guid: 451fa6a449d47ab46bc71e9749ee8c1b, type: 3} - spawnPosition: - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - - {fileID: 0} - spawnTime: 4 --- !u!4 &340526137 Transform: m_ObjectHideFlags: 0 @@ -1183,6 +1055,20 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &340526138 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 340526135} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9b6011250d2465d41b96c4b2219a159f, type: 3} + m_Name: + m_EditorClassIdentifier: + enemyPrefab: {fileID: 2150025513644625521, guid: 451fa6a449d47ab46bc71e9749ee8c1b, type: 3} + spawnOnStart: 1 --- !u!1 &410087039 GameObject: m_ObjectHideFlags: 0 @@ -1775,6 +1661,52 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &609157175 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 7 + m_Component: + - component: {fileID: 609157177} + - component: {fileID: 609157176} + m_Layer: 0 + m_HasEditorInfo: 1 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &609157176 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 609157175} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4d00cf2db1a25dd4ea45937d987e9104, type: 3} + m_Name: + m_EditorClassIdentifier: + gizmoRadius: 3 +--- !u!4 &609157177 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 609157175} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 7.05, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &610005743 GameObject: m_ObjectHideFlags: 0 @@ -1823,7 +1755,7 @@ Transform: - {fileID: 906418046} - {fileID: 689051075} - {fileID: 511862705} - - {fileID: 1356835562} + - {fileID: 743379411} - {fileID: 288515180} - {fileID: 1404747136} - {fileID: 1190607345} @@ -1833,8 +1765,7 @@ Transform: - {fileID: 833215253} - {fileID: 46683150} - {fileID: 1698232721} - - {fileID: 1954965855} - - {fileID: 779616850} + - {fileID: 2374143409467999212} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &635639815 @@ -2265,6 +2196,171 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 713509613} m_CullTransparentMesh: 1 +--- !u!1 &743379410 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 7 + m_Component: + - component: {fileID: 743379411} + - component: {fileID: 743379416} + - component: {fileID: 743379415} + - component: {fileID: 743379414} + - component: {fileID: 743379413} + - component: {fileID: 743379412} + m_Layer: 7 + m_HasEditorInfo: 1 + m_Name: "tree1\uFF081\uFF09" + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &743379411 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 743379410} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -4.6, y: -1.2, z: 2.83} + m_LocalScale: {x: 1.0619, y: 1.0619, z: 1.0619} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 762659327} + m_Father: {fileID: 610005744} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &743379412 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 743379410} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9665e5f4b5ee9a146a465e4571b5868b, type: 3} + m_Name: + m_EditorClassIdentifier: + lockYAxis: 1 + smoothRotation: 1 + rotationSpeed: 1 +--- !u!114 &743379413 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 743379410} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 53d1d05b715330a4ca6ca79f6457e809, type: 3} + m_Name: + m_EditorClassIdentifier: + plantationCutParticles: {fileID: 4518760045590776412, guid: a229182daa01f8d46aba985071d94530, type: 3} +--- !u!65 &743379414 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 743379410} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 1 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 13.08, y: 11.36, z: 0.2} + m_Center: {x: 0, y: 5.68, z: 0} +--- !u!95 &743379415 +Animator: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 743379410} + m_Enabled: 1 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 9100000, guid: 51972fb86b8c0fb4e926c97424d06dc3, type: 2} + m_CullingMode: 0 + m_UpdateMode: 0 + m_UpdateFrequencyMode: 0 + m_UpdateFrequency: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_StabilizeFeet: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorStateOnDisable: 0 + m_WriteDefaultValuesOnDisable: 0 +--- !u!212 &743379416 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 743379410} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_virtualGeometry: 0 + m_virtualGeometryShadow: 0 + m_ShadingRate: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 6dd18d2379aff3040813ab8005b1898a, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 1 + m_Sprite: {fileID: 21300000, guid: 9e86f261a1e9198449b0ab7510a5eb98, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 11.08, y: 8.65} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 --- !u!1 &748309588 GameObject: m_ObjectHideFlags: 0 @@ -2441,7 +2537,7 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 ---- !u!1 &779616849 +--- !u!1 &762659326 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -2449,38 +2545,38 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 7 m_Component: - - component: {fileID: 779616850} - - component: {fileID: 779616851} + - component: {fileID: 762659327} + - component: {fileID: 762659328} m_Layer: 0 m_HasEditorInfo: 1 - m_Name: sky + m_Name: Shadow m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &779616850 +--- !u!4 &762659327 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 779616849} + m_GameObject: {fileID: 762659326} serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 5.75, y: -1.86, z: 24.1} - m_LocalScale: {x: 0.9535843, y: 0.5650535, z: 0.5650535} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 610005744} + m_Father: {fileID: 743379411} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!212 &779616851 +--- !u!212 &762659328 SpriteRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 779616849} + m_GameObject: {fileID: 762659326} m_Enabled: 1 m_CastShadows: 1 m_ReceiveShadows: 1 @@ -2517,8 +2613,8 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 0 m_SortingLayer: 0 - m_SortingOrder: 1 - m_Sprite: {fileID: 21300000, guid: 14b84436288313b46bd9acda3ae2ac4d, type: 3} + m_SortingOrder: 0 + m_Sprite: {fileID: 21300000, guid: 9e86f261a1e9198449b0ab7510a5eb98, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 m_FlipY: 0 @@ -2803,7 +2899,6 @@ GameObject: m_Component: - component: {fileID: 1043014446} - component: {fileID: 1043014445} - - component: {fileID: 1043014444} m_Layer: 0 m_HasEditorInfo: 1 m_Name: EventSystem @@ -2812,18 +2907,6 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!114 &1043014444 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1043014443} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!114 &1043014445 MonoBehaviour: m_ObjectHideFlags: 0 @@ -3338,94 +3421,6 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 ---- !u!1 &1356835561 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 7 - m_Component: - - component: {fileID: 1356835562} - - component: {fileID: 1356835563} - m_Layer: 0 - m_HasEditorInfo: 1 - m_Name: "tree1\uFF081\uFF09" - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1356835562 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1356835561} - serializedVersion: 2 - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -4.6, y: -1.2, z: 2.83} - m_LocalScale: {x: 1.0619, y: 1.0619, z: 1.0619} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 610005744} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!212 &1356835563 -SpriteRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1356835561} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 0 - m_RayTraceProcedural: 0 - m_virtualGeometry: 0 - m_virtualGeometryShadow: 0 - m_ShadingRate: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: -876546973899608171, guid: be3236dea9f1e304da1a5e3a513dad5e, type: 3} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 0 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 1 - m_Sprite: {fileID: 21300000, guid: 9e86f261a1e9198449b0ab7510a5eb98, type: 3} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_FlipX: 0 - m_FlipY: 0 - m_DrawMode: 0 - m_Size: {x: 11.08, y: 8.65} - m_AdaptiveModeThreshold: 0.5 - m_SpriteTileMode: 0 - m_WasSpriteAssigned: 1 - m_MaskInteraction: 0 - m_SpriteSortPoint: 0 --- !u!1 &1390677416 GameObject: m_ObjectHideFlags: 0 @@ -3778,94 +3773,6 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 ---- !u!1 &1954965854 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 7 - m_Component: - - component: {fileID: 1954965855} - - component: {fileID: 1954965856} - m_Layer: 0 - m_HasEditorInfo: 1 - m_Name: grass (4) - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1954965855 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1954965854} - serializedVersion: 2 - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -3.453, y: 0, z: 1.14} - m_LocalScale: {x: 0.2747675, y: 0.2747675, z: 0.2747675} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 610005744} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!212 &1954965856 -SpriteRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1954965854} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 0 - m_RayTraceProcedural: 0 - m_virtualGeometry: 0 - m_virtualGeometryShadow: 0 - m_ShadingRate: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: -876546973899608171, guid: be3236dea9f1e304da1a5e3a513dad5e, type: 3} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 0 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 1 - m_Sprite: {fileID: 21300000, guid: d2289c47948a3cc40bd1d82676391b50, type: 3} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_FlipX: 0 - m_FlipY: 0 - m_DrawMode: 0 - m_Size: {x: 11.08, y: 8.65} - m_AdaptiveModeThreshold: 0.5 - m_SpriteTileMode: 0 - m_WasSpriteAssigned: 1 - m_MaskInteraction: 0 - m_SpriteSortPoint: 0 --- !u!1 &1990363366 GameObject: m_ObjectHideFlags: 0 @@ -4328,6 +4235,243 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!114 &902340834149089514 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6829946785112418295} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 53d1d05b715330a4ca6ca79f6457e809, type: 3} + m_Name: + m_EditorClassIdentifier: + plantationCutParticles: {fileID: 4518760045590776412, guid: a229182daa01f8d46aba985071d94530, type: 3} +--- !u!212 &1703735994160561314 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3143302650254845289} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_virtualGeometry: 0 + m_virtualGeometryShadow: 0 + m_ShadingRate: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: -876546973899608171, guid: be3236dea9f1e304da1a5e3a513dad5e, type: 3} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Sprite: {fileID: 21300000, guid: d2289c47948a3cc40bd1d82676391b50, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 11.08, y: 8.65} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!4 &2374143409467999212 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6829946785112418295} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -3.453, y: 0, z: 1.14} + m_LocalScale: {x: 0.2747675, y: 0.2747675, z: 0.2747675} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 4066492961171794473} + m_Father: {fileID: 610005744} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &2917233676302377280 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6829946785112418295} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 1 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 13.08, y: 11.36, z: 0.2} + m_Center: {x: 0, y: 5.68, z: 0} +--- !u!1 &3143302650254845289 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 7 + m_Component: + - component: {fileID: 4066492961171794473} + - component: {fileID: 1703735994160561314} + m_Layer: 0 + m_HasEditorInfo: 1 + m_Name: Shadow + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4066492961171794473 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3143302650254845289} + 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: 2374143409467999212} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!95 &5433923550863291886 +Animator: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6829946785112418295} + m_Enabled: 1 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 9100000, guid: 51972fb86b8c0fb4e926c97424d06dc3, type: 2} + m_CullingMode: 0 + m_UpdateMode: 0 + m_UpdateFrequencyMode: 0 + m_UpdateFrequency: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_StabilizeFeet: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorStateOnDisable: 0 + m_WriteDefaultValuesOnDisable: 0 +--- !u!1 &6829946785112418295 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 7 + m_Component: + - component: {fileID: 2374143409467999212} + - component: {fileID: 7609060905728962241} + - component: {fileID: 5433923550863291886} + - component: {fileID: 2917233676302377280} + - component: {fileID: 902340834149089514} + m_Layer: 7 + m_HasEditorInfo: 1 + m_Name: grass (4) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!212 &7609060905728962241 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6829946785112418295} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_virtualGeometry: 0 + m_virtualGeometryShadow: 0 + m_ShadingRate: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 6dd18d2379aff3040813ab8005b1898a, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 1 + m_Sprite: {fileID: 21300000, guid: d2289c47948a3cc40bd1d82676391b50, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 11.08, y: 8.65} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 --- !u!1660057539 &9223372036854775807 SceneRoots: m_ObjectHideFlags: 0 @@ -4343,3 +4487,4 @@ SceneRoots: - {fileID: 338266643} - {fileID: 8914096} - {fileID: 444470370} + - {fileID: 609157177} diff --git a/unity/Assets/eco/EchoSystem.cs b/unity/Assets/eco/EchoSystem.cs index a48eb8f..2c1abe7 100644 --- a/unity/Assets/eco/EchoSystem.cs +++ b/unity/Assets/eco/EchoSystem.cs @@ -1,3 +1,4 @@ +using System; using UnityEngine; namespace IndianOceanAssets.Engine2_5D @@ -18,6 +19,12 @@ namespace IndianOceanAssets.Engine2_5D /// public class EchoSystem : MonoBehaviour { + /// + /// 按 E 释放回声(摇铃)时触发,参数为释放时的玩家世界位置。 + /// 敌人聆听系统等可订阅此事件。 + /// + public static event Action OnEchoReleased; + [Header("按键")] [SerializeField] private KeyCode echoKey = KeyCode.E; @@ -105,6 +112,9 @@ namespace IndianOceanAssets.Engine2_5D // 记录释放时刻的玩家位置(回声中心固定,不跟随移动) Vector3 p = transform.position; _center = new Vector2(p.x, p.z); + + // 通知订阅者(敌人聆听等) + OnEchoReleased?.Invoke(p); } private void UpdateExpanding() @@ -153,4 +163,4 @@ namespace IndianOceanAssets.Engine2_5D public bool IsActive => _state != State.Idle; } -} \ No newline at end of file +} diff --git a/unity/Assets/enemy.meta b/unity/Assets/enemy.meta new file mode 100644 index 0000000..1277965 --- /dev/null +++ b/unity/Assets/enemy.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: XikWvCmlUXp3molBS0dkPpRqAmEWPxgDy8pQ05QgOF4mepv/U4Mikd0= +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity/Assets/enemy/BillboardSprite.cs b/unity/Assets/enemy/BillboardSprite.cs new file mode 100644 index 0000000..8388d6e --- /dev/null +++ b/unity/Assets/enemy/BillboardSprite.cs @@ -0,0 +1,60 @@ +using UnityEngine; + +namespace IndianOceanAssets.Engine2_5D +{ + /// + /// 场景物件面向摄像机脚本(饥荒风格)。 + /// 让物体始终朝摄像机方向旋转,默认只绕 Y 轴(保持竖直不倒)。 + /// + /// 用法:挂到需要面向摄像机的精灵/物件上即可。 + /// 适合:树木、岩石、角色、道具等 2D 精灵在 3D 场景中的朝向修正。 + /// + public class BillboardSprite : MonoBehaviour + { + [Tooltip("只绕Y轴旋转(饥荒风格,保持竖直不倒)。关闭则完全面向摄像机。")] + [SerializeField] private bool lockYAxis = true; + + [Tooltip("平滑旋转(lerp过渡),关闭则瞬间转向")] + [SerializeField] private bool smoothRotation = false; + + [Tooltip("平滑旋转速度")] + [SerializeField] private float rotationSpeed = 8f; + + private Camera _mainCamera; + private Transform _camTransform; + + private void Start() + { + _mainCamera = Camera.main; + if (_mainCamera != null) + _camTransform = _mainCamera.transform; + } + + private void LateUpdate() + { + if (_camTransform == null) + { + // 摄像机丢失时重新获取(场景切换等情况) + _mainCamera = Camera.main; + if (_mainCamera != null) + _camTransform = _mainCamera.transform; + if (_camTransform == null) return; + } + + Vector3 dir = _camTransform.position - transform.position; + + if (lockYAxis) + dir.y = 0f; // 保持竖直 + + if (dir.sqrMagnitude < 0.0001f) return; + + Quaternion targetRot = Quaternion.LookRotation(dir); + + if (smoothRotation) + transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, + rotationSpeed * Time.deltaTime); + else + transform.rotation = targetRot; + } + } +} diff --git a/unity/Assets/2.5D Engine/Scripts/EnemySpawner.cs.meta b/unity/Assets/enemy/BillboardSprite.cs.meta similarity index 76% rename from unity/Assets/2.5D Engine/Scripts/EnemySpawner.cs.meta rename to unity/Assets/enemy/BillboardSprite.cs.meta index 61c1acb..e1e31ff 100644 --- a/unity/Assets/2.5D Engine/Scripts/EnemySpawner.cs.meta +++ b/unity/Assets/enemy/BillboardSprite.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c755496b98cf3a743b854c203125bdff +guid: BnwZsH+oBX9o8/qrlvnDZyZeLvCxOPjzKkntbYOjVXovzGFc2g6PBfk= MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/unity/Assets/enemy/EnemyAI.cs b/unity/Assets/enemy/EnemyAI.cs new file mode 100644 index 0000000..ff1e0e9 --- /dev/null +++ b/unity/Assets/enemy/EnemyAI.cs @@ -0,0 +1,222 @@ +using UnityEngine; + +namespace IndianOceanAssets.Engine2_5D +{ + /// + /// 敌人AI —— 检测/追击/脱离持续/摇铃聆听响应。 + /// + /// 状态流程: + /// - Idle:站岗。主角进入 detectionRange → Chasing + /// - Chasing:追击主角。主角离开 detectionRange → ChasingPersist + /// - ChasingPersist:脱离后继续追击 chasePersistTime 秒。 + /// 主角重新进入范围 → 回到 Chasing;超时 → Idle(停在当前位置,不回出生点) + /// - BellResponding:主角在 listenRange 内按E摇铃时触发, + /// 朝主角方向移动 bellMoveTime 秒(距离 = 速度 × 时间),然后停下 → Idle + /// + /// 挂载位置:敌人预制体上 + /// 需要:场景中有 EchoSystem(用于摇铃事件)、玩家物体带 "Player" 标签 + /// (或手动把玩家拖到 playerTarget 字段) + /// + public class EnemyAI : MonoBehaviour + { + [Header("目标")] + [Tooltip("玩家目标(留空则自动查找 Player 标签)")] + [SerializeField] private Transform playerTarget; + + [Header("检测与追击")] + [Tooltip("发现主角的范围")] + [SerializeField] private float detectionRange = 8f; + + [Tooltip("追击速度")] + [SerializeField] private float chaseSpeed = 3f; + + [Tooltip("靠近主角到此距离时停下")] + [SerializeField] private float stopDistance = 1.2f; + + [Tooltip("主角脱离检测范围后,继续追击的时间(秒)")] + [SerializeField] private float chasePersistTime = 3f; + + [Header("聆听(摇铃响应)")] + [Tooltip("聆听范围:主角在此范围内按E摇铃时,敌人会朝主角方向移动")] + [SerializeField] private float listenRange = 15f; + + [Tooltip("摇铃响应移动速度")] + [SerializeField] private float bellMoveSpeed = 4f; + + [Tooltip("摇铃响应移动时间(距离 = 速度 × 时间)")] + [SerializeField] private float bellMoveTime = 1.5f; + + private enum State { Idle, Chasing, ChasingPersist, BellResponding } + private State _state = State.Idle; + private float _stateTimer; + private Vector3 _bellDirection; + + private void Start() + { + if (playerTarget == null) + { + var player = GameObject.FindWithTag("Player"); + if (player != null) + playerTarget = player.transform; + } + } + + private void OnEnable() + { + EchoSystem.OnEchoReleased += OnBell; + } + + private void OnDisable() + { + EchoSystem.OnEchoReleased -= OnBell; + } + + private void Update() + { + switch (_state) + { + case State.Idle: UpdateIdle(); break; + case State.Chasing: UpdateChasing(); break; + case State.ChasingPersist: UpdateChasingPersist(); break; + case State.BellResponding: UpdateBellResponding(); break; + } + } + + // ===== Idle:站岗,等主角进入检测范围 ===== + private void UpdateIdle() + { + if (playerTarget == null) return; + if (XZDistance(transform.position, playerTarget.position) <= detectionRange) + { + _state = State.Chasing; + } + } + + // ===== Chasing:追击主角 ===== + private void UpdateChasing() + { + if (playerTarget == null) return; + float dist = XZDistance(transform.position, playerTarget.position); + + // 主角脱离检测范围 → 继续追击一段时间 + if (dist > detectionRange) + { + _state = State.ChasingPersist; + _stateTimer = chasePersistTime; + return; + } + + // 靠近到停止距离时停下(但仍处于追击状态) + if (dist > stopDistance) + MoveToward(playerTarget.position, chaseSpeed); + } + + // ===== ChasingPersist:脱离后继续追击,倒计时 ===== + private void UpdateChasingPersist() + { + if (playerTarget == null) return; + _stateTimer -= Time.deltaTime; + + // 超时 → 停在当前位置,回到 Idle(不回出生点) + if (_stateTimer <= 0f) + { + _state = State.Idle; + return; + } + + float dist = XZDistance(transform.position, playerTarget.position); + + // 主角重新进入检测范围 → 回到正常追击 + if (dist <= detectionRange) + { + _state = State.Chasing; + return; + } + + if (dist > stopDistance) + MoveToward(playerTarget.position, chaseSpeed); + } + + // ===== BellResponding:摇铃响应,朝主角方向移动固定时间 ===== + private void UpdateBellResponding() + { + _stateTimer -= Time.deltaTime; + if (_stateTimer <= 0f) + { + _state = State.Idle; + return; + } + // 沿摇铃时刻的方向移动(距离 = 速度 × 时间) + Vector3 move = _bellDirection * bellMoveSpeed * Time.deltaTime; + transform.position += new Vector3(move.x, 0f, move.z); + } + + // ===== 摇铃事件回调(由 EchoSystem.OnEchoReleased 触发)===== + private void OnBell(Vector3 bellPos) + { + if (playerTarget == null) return; + + // 只有在聆听范围内才响应 + if (XZDistance(transform.position, bellPos) > listenRange) return; + + // 计算朝主角方向(摇铃时刻的位置) + _bellDirection = new Vector3( + bellPos.x - transform.position.x, + 0f, + bellPos.z - transform.position.z + ); + if (_bellDirection.sqrMagnitude > 0.001f) + _bellDirection.Normalize(); + else + _bellDirection = transform.forward; // 重叠时用当前朝向 + + // 摇铃响应可打断任何当前状态 + _state = State.BellResponding; + _stateTimer = bellMoveTime; + } + + // ===== 工具方法 ===== + + private void MoveToward(Vector3 target, float speed) + { + Vector3 dir = new Vector3( + target.x - transform.position.x, + 0f, + target.z - transform.position.z + ); + float dist = dir.magnitude; + if (dist < 0.01f) return; + + dir /= dist; + Vector3 move = dir * speed * Time.deltaTime; + if (move.magnitude > dist) move = dir * dist; // 不越过目标 + transform.position += new Vector3(move.x, 0f, move.z); + } + + private float XZDistance(Vector3 a, Vector3 b) + { + float dx = a.x - b.x; + float dz = a.z - b.z; + return Mathf.Sqrt(dx * dx + dz * dz); + } + + // ===== 编辑器可视化 ===== + private void OnDrawGizmosSelected() + { + // 检测范围(黄色) + Gizmos.color = new Color(1f, 0.85f, 0f, 0.6f); + Gizmos.DrawWireSphere(transform.position, detectionRange); + + // 聆听范围(青色) + Gizmos.color = new Color(0f, 0.85f, 1f, 0.6f); + Gizmos.DrawWireSphere(transform.position, listenRange); + + // 停止距离(红色) + Gizmos.color = new Color(1f, 0.3f, 0.3f, 0.6f); + Gizmos.DrawWireSphere(transform.position, stopDistance); + } + + /// 当前状态(调试用) + public string CurrentState => _state.ToString(); + } +} diff --git a/unity/Assets/2.5D Engine/Scripts/EnemyAI.cs.meta b/unity/Assets/enemy/EnemyAI.cs.meta similarity index 76% rename from unity/Assets/2.5D Engine/Scripts/EnemyAI.cs.meta rename to unity/Assets/enemy/EnemyAI.cs.meta index 3da34b7..ec308ad 100644 --- a/unity/Assets/2.5D Engine/Scripts/EnemyAI.cs.meta +++ b/unity/Assets/enemy/EnemyAI.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 04126beb49efb8c49a7ecc822750a0c7 +guid: CCwWtXv+BXlMo6hf6dmE2xTAlfSRx2PCnRzyAU6iQWgz40mcEU424HU= MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/unity/Assets/enemy/EnemyManager.cs b/unity/Assets/enemy/EnemyManager.cs new file mode 100644 index 0000000..8ecae5f --- /dev/null +++ b/unity/Assets/enemy/EnemyManager.cs @@ -0,0 +1,85 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace IndianOceanAssets.Engine2_5D +{ + /// + /// 敌人管理器 —— 在游戏开始时,于场景中所有 EnemySpawnPoint 处生成敌人。 + /// + /// 用法: + /// 1. 在场景中放置空物体,挂 EnemySpawnPoint 组件,作为出生点 + /// 2. 在场景中创建空物体,挂此 EnemyManager 脚本 + /// 3. 把敌人预制体拖到 enemyPrefab 字段 + /// 4. 运行时自动在所有出生点生成敌人 + /// + public class EnemyManager : MonoBehaviour + { + public static EnemyManager Instance { get; private set; } + + [Header("敌人物体预制体")] + [SerializeField] private GameObject enemyPrefab; + + [Tooltip("勾选后游戏开始时自动在所有出生点生成敌人")] + [SerializeField] private bool spawnOnStart = true; + + private readonly List _enemies = new List(); + + private void Awake() + { + if (Instance != null && Instance != this) + { + Destroy(this); + return; + } + Instance = this; + } + + private void Start() + { + if (spawnOnStart) + SpawnAll(); + } + + /// + /// 在所有 EnemySpawnPoint 处生成敌人 + /// + [ContextMenu("Spawn All")] + public void SpawnAll() + { + var spawnPoints = FindObjectsByType(FindObjectsSortMode.None); + foreach (var sp in spawnPoints) + { + SpawnEnemy(sp.transform.position, sp.transform.rotation); + } + Debug.Log($"[EnemyManager] 在 {spawnPoints.Length} 个出生点生成了 {_enemies.Count} 个敌人"); + } + + /// + /// 在指定位置生成一个敌人 + /// + public GameObject SpawnEnemy(Vector3 position, Quaternion rotation) + { + if (enemyPrefab == null) + { + Debug.LogWarning("[EnemyManager] enemyPrefab 未设置!"); + return null; + } + + var enemy = Instantiate(enemyPrefab, position, rotation); + var ai = enemy.GetComponent(); + if (ai != null && !_enemies.Contains(ai)) + _enemies.Add(ai); + + return enemy; + } + + /// + /// 获取所有活跃敌人(自动清理已销毁的) + /// + public List GetActiveEnemies() + { + _enemies.RemoveAll(e => e == null); + return _enemies; + } + } +} diff --git a/unity/Assets/enemy/EnemyManager.cs.meta b/unity/Assets/enemy/EnemyManager.cs.meta new file mode 100644 index 0000000..1e5f9bc --- /dev/null +++ b/unity/Assets/enemy/EnemyManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: BigZtSusUX7LyMDm+vuceZYAyL3PPYdY87jCezHOaujUlI0euVs5iBo= +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity/Assets/enemy/EnemySpawnPoint.cs b/unity/Assets/enemy/EnemySpawnPoint.cs new file mode 100644 index 0000000..25ab238 --- /dev/null +++ b/unity/Assets/enemy/EnemySpawnPoint.cs @@ -0,0 +1,24 @@ +using UnityEngine; + +namespace IndianOceanAssets.Engine2_5D +{ + /// + /// 敌人出生点标记 —— 挂到场景中的空物体上,标记敌人出生位置。 + /// EnemyManager 会在游戏开始时找到所有出生点并生成敌人。 + /// + /// 用法:在场景中放置空物体,挂上此组件,调整位置即可。 + /// Scene 视图中显示红色线框球 + 竖线,方便辨认。 + /// + public class EnemySpawnPoint : MonoBehaviour + { + [Tooltip("Gizmo 球体半径(仅编辑器可视化)")] + [SerializeField] private float gizmoRadius = 0.5f; + + private void OnDrawGizmos() + { + Gizmos.color = Color.red; + Gizmos.DrawWireSphere(transform.position, gizmoRadius); + Gizmos.DrawLine(transform.position, transform.position + Vector3.up * 2f); + } + } +} diff --git a/unity/Assets/enemy/EnemySpawnPoint.cs.meta b/unity/Assets/enemy/EnemySpawnPoint.cs.meta new file mode 100644 index 0000000..526b4d3 --- /dev/null +++ b/unity/Assets/enemy/EnemySpawnPoint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: Cy4ftXn7US8AThuZOHodRQB7iRTlR2Qu7Jt/xviDZ91RolRZd+3dykw= +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity/UserSettings/EditorUserSettings.asset b/unity/UserSettings/EditorUserSettings.asset index 344b50f..11ddbd8 100644 --- a/unity/UserSettings/EditorUserSettings.asset +++ b/unity/UserSettings/EditorUserSettings.asset @@ -18,10 +18,10 @@ EditorUserSettings: value: 5b090d000402580a5c5b087648735e4445151e737b717334757b1832b1b93261 flags: 0 RecentlyUsedSceneGuid-4: - value: 5055070050010c5a0e5d0d27497a0e441016412c2f7d206178714f61b3b8326b + value: 5a5757560101590a5d0c0e24427b5d44434e4c7a7b7a23677f2b4565b7b5353a flags: 0 RecentlyUsedSceneGuid-5: - value: 5a5757560101590a5d0c0e24427b5d44434e4c7a7b7a23677f2b4565b7b5353a + value: 5055070050010c5a0e5d0d27497a0e441016412c2f7d206178714f61b3b8326b flags: 0 RecentlyUsedSceneGuid-6: value: 5a55515156575a0b0f56592346260f444f16197c7e7f24697d2a4a32b1b0353e