From 7339c012c3394190d622fed3b7592deccbbcbb8c Mon Sep 17 00:00:00 2001 From: hzmt Date: Sat, 31 Jan 2026 20:17:28 -0600 Subject: [PATCH] Removing barriers, adding trick logic, and making players pick-up-able --- Assets/Physics.meta | 8 + .../Physics/TrickNoFriction.physicsMaterial2D | 11 + .../TrickNoFriction.physicsMaterial2D.meta | 8 + Assets/Prefabs/Trick.prefab | 22 +- Assets/Scenes/Experiment.unity | 392 +++++------------- Assets/Scripts/PlayerPickupController.cs | 26 +- Assets/Scripts/TrickCollisionManager.cs | 29 ++ Assets/Scripts/TrickCollisionManager.cs.meta | 11 + Assets/Scripts/TrickController.cs | 167 +++++++- ProjectSettings/TagManager.asset | 4 +- 10 files changed, 381 insertions(+), 297 deletions(-) create mode 100644 Assets/Physics.meta create mode 100644 Assets/Physics/TrickNoFriction.physicsMaterial2D create mode 100644 Assets/Physics/TrickNoFriction.physicsMaterial2D.meta create mode 100644 Assets/Scripts/TrickCollisionManager.cs create mode 100644 Assets/Scripts/TrickCollisionManager.cs.meta diff --git a/Assets/Physics.meta b/Assets/Physics.meta new file mode 100644 index 0000000..3a779f0 --- /dev/null +++ b/Assets/Physics.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 58ffb2142b4f20f4388243f51a413e0e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Physics/TrickNoFriction.physicsMaterial2D b/Assets/Physics/TrickNoFriction.physicsMaterial2D new file mode 100644 index 0000000..b040ecd --- /dev/null +++ b/Assets/Physics/TrickNoFriction.physicsMaterial2D @@ -0,0 +1,11 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!62 &6200000 +PhysicsMaterial2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: TrickNoFriction + friction: 0 + bounciness: 0 diff --git a/Assets/Physics/TrickNoFriction.physicsMaterial2D.meta b/Assets/Physics/TrickNoFriction.physicsMaterial2D.meta new file mode 100644 index 0000000..18f1845 --- /dev/null +++ b/Assets/Physics/TrickNoFriction.physicsMaterial2D.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 71737e52316f484b8c59e24137491385 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 6200000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Trick.prefab b/Assets/Prefabs/Trick.prefab index 8ade7d4..3ea6e6d 100644 --- a/Assets/Prefabs/Trick.prefab +++ b/Assets/Prefabs/Trick.prefab @@ -13,7 +13,7 @@ GameObject: - component: {fileID: 700000003} - component: {fileID: 700000004} - component: {fileID: 700000005} - m_Layer: 0 + m_Layer: 3 m_Name: Trick m_TagString: Interactable m_Icon: {fileID: 0} @@ -110,7 +110,7 @@ Rigidbody2D: m_LinearDamping: 0 m_AngularDamping: 0.05 m_GravityScale: 0 - m_Material: {fileID: 0} + m_Material: {fileID: 6200000, guid: 71737e52316f484b8c59e24137491385, type: 2} m_IncludeLayers: serializedVersion: 2 m_Bits: 0 @@ -131,7 +131,7 @@ BoxCollider2D: m_Enabled: 1 serializedVersion: 3 m_Density: 1 - m_Material: {fileID: 0} + m_Material: {fileID: 6200000, guid: 71737e52316f484b8c59e24137491385, type: 2} m_IncludeLayers: serializedVersion: 2 m_Bits: 0 @@ -184,4 +184,18 @@ MonoBehaviour: targetRefreshInterval: 0.4 consumeDistance: 0.35 wanderInterval: 1.2 - trickPrefab: {fileID: 700000000, guid: 8bf8957665594a718535d06aba0cdee7, type: 3} + consumeCooldown: 1.5 + trickPrefab: {fileID: 700000005} + avoidPlayerRadius: 1.2 + avoidTrickRadius: 0.8 + treatSeekWeight: 1 + avoidPlayerWeight: 0.25 + avoidTrickWeight: 0.2 + wanderWeight: 0.4 + jumpImpulse: 6 + jumpCooldown: 1 + jumpChancePerSecond: 0.5 + groundMask: + serializedVersion: 2 + m_Bits: 4294967295 + groundCheckDistance: 0.05 diff --git a/Assets/Scenes/Experiment.unity b/Assets/Scenes/Experiment.unity index 5960e50..42d02ed 100644 --- a/Assets/Scenes/Experiment.unity +++ b/Assets/Scenes/Experiment.unity @@ -686,84 +686,6 @@ Rigidbody2D: m_SleepingMode: 1 m_CollisionDetection: 0 m_Constraints: 0 ---- !u!1 &477169534 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 477169536} - - component: {fileID: 477169535} - m_Layer: 0 - m_Name: Right Barrier - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!61 &477169535 -BoxCollider2D: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 477169534} - m_Enabled: 1 - serializedVersion: 3 - m_Density: 1 - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_ForceSendLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_ForceReceiveLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_ContactCaptureLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_CallbackLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_IsTrigger: 0 - m_UsedByEffector: 0 - m_CompositeOperation: 0 - m_CompositeOrder: 0 - m_Offset: {x: 0, y: 1.4146457} - m_SpriteTilingProperty: - border: {x: 0, y: 0, z: 0, w: 0} - pivot: {x: 0, y: 0} - oldSize: {x: 0, y: 0} - newSize: {x: 0, y: 0} - adaptiveTilingThreshold: 0 - drawMode: 0 - adaptiveTiling: 0 - m_AutoTiling: 0 - m_Size: {x: 1, y: 6.956403} - m_EdgeRadius: 0 ---- !u!4 &477169536 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 477169534} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 6.8, y: 1.94, 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 &486463122 GameObject: m_ObjectHideFlags: 0 @@ -1039,84 +961,6 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 90} ---- !u!1 &689117238 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 689117240} - - component: {fileID: 689117239} - m_Layer: 0 - m_Name: Left Barrier - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!61 &689117239 -BoxCollider2D: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 689117238} - m_Enabled: 1 - serializedVersion: 3 - m_Density: 1 - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_ForceSendLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_ForceReceiveLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_ContactCaptureLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_CallbackLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_IsTrigger: 0 - m_UsedByEffector: 0 - m_CompositeOperation: 0 - m_CompositeOrder: 0 - m_Offset: {x: 0, y: 1.4146457} - m_SpriteTilingProperty: - border: {x: 0, y: 0, z: 0, w: 0} - pivot: {x: 0, y: 0} - oldSize: {x: 0, y: 0} - newSize: {x: 0, y: 0} - adaptiveTilingThreshold: 0 - drawMode: 0 - adaptiveTiling: 0 - m_AutoTiling: 0 - m_Size: {x: 1, y: 6.956403} - m_EdgeRadius: 0 ---- !u!4 &689117240 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 689117238} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -6.82, y: 1.25, 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 &707098062 GameObject: m_ObjectHideFlags: 0 @@ -1643,6 +1487,9 @@ MonoBehaviour: m_EditorClassIdentifier: Assembly-CSharp::Spawner objectToSpawn: {fileID: 262983251238298495, guid: 80c527a86ad6fc34dbc73ee80c1f2951, type: 3} spawnInterval: 5 + maxAlive: 0 + spawnOnStart: 1 + repeatSpawns: 1 --- !u!4 &908853550 Transform: m_ObjectHideFlags: 0 @@ -2026,6 +1873,9 @@ MonoBehaviour: m_EditorClassIdentifier: Assembly-CSharp::Spawner objectToSpawn: {fileID: 262983251238298495, guid: 80c527a86ad6fc34dbc73ee80c1f2951, type: 3} spawnInterval: 5 + maxAlive: 0 + spawnOnStart: 1 + repeatSpawns: 1 --- !u!4 &1466477813 Transform: m_ObjectHideFlags: 0 @@ -2041,84 +1891,6 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1518904086 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1518904088} - - component: {fileID: 1518904087} - m_Layer: 0 - m_Name: Top Barrier - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!61 &1518904087 -BoxCollider2D: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1518904086} - m_Enabled: 1 - serializedVersion: 3 - m_Density: 1 - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_ForceSendLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_ForceReceiveLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_ContactCaptureLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_CallbackLayers: - serializedVersion: 2 - m_Bits: 4294967295 - m_IsTrigger: 0 - m_UsedByEffector: 0 - m_CompositeOperation: 0 - m_CompositeOrder: 0 - m_Offset: {x: 0, y: 1.4146457} - m_SpriteTilingProperty: - border: {x: 0, y: 0, z: 0, w: 0} - pivot: {x: 0, y: 0} - oldSize: {x: 0, y: 0} - newSize: {x: 0, y: 0} - adaptiveTilingThreshold: 0 - drawMode: 0 - adaptiveTiling: 0 - m_AutoTiling: 0 - m_Size: {x: 1, y: 6.956403} - m_EdgeRadius: 0 ---- !u!4 &1518904088 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1518904086} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0.7071068, w: 0.7071068} - m_LocalPosition: {x: 4.19, y: 5.55, z: 0} - m_LocalScale: {x: 1, y: 2.94, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 90} --- !u!1 &1654086541 GameObject: m_ObjectHideFlags: 0 @@ -2385,6 +2157,9 @@ MonoBehaviour: m_EditorClassIdentifier: Assembly-CSharp::Spawner objectToSpawn: {fileID: 262983251238298495, guid: 80c527a86ad6fc34dbc73ee80c1f2951, type: 3} spawnInterval: 5 + maxAlive: 0 + spawnOnStart: 1 + repeatSpawns: 1 --- !u!4 &1759124604 Transform: m_ObjectHideFlags: 0 @@ -2431,6 +2206,9 @@ MonoBehaviour: m_EditorClassIdentifier: Assembly-CSharp::Spawner objectToSpawn: {fileID: 262983251238298495, guid: 80c527a86ad6fc34dbc73ee80c1f2951, type: 3} spawnInterval: 5 + maxAlive: 0 + spawnOnStart: 1 + repeatSpawns: 1 --- !u!4 &1830238253 Transform: m_ObjectHideFlags: 0 @@ -2722,6 +2500,99 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &2100000000 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2100000001} + - component: {fileID: 2100000002} + m_Layer: 0 + m_Name: NPC Spawner + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2100000001 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2100000000} + 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_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2100000002 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2100000000} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 14b0bf07aa1abc44a8ebd00cecacd6f4, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Spawner + objectToSpawn: {fileID: 700000000, guid: 8bf8957665594a718535d06aba0cdee7, type: 3} + spawnInterval: 3 + maxAlive: 1 + spawnOnStart: 1 + repeatSpawns: 0 +--- !u!1 &2100000100 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2100000101} + - component: {fileID: 2100000102} + m_Layer: 0 + m_Name: Trick Collision Manager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2100000101 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2100000100} + 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_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2100000102 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2100000100} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 44f2fea877e8498fa4898917356fb2e6, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1001 &1760117322204329348 PrefabInstance: m_ObjectHideFlags: 0 @@ -2795,55 +2666,6 @@ PrefabInstance: m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 99cce68fc82caea44b5a140697be00a8, type: 3} ---- !u!1 &2100000000 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2100000001} - - component: {fileID: 2100000002} - m_Layer: 0 - m_Name: NPC Spawner - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &2100000001 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2100000000} - 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_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &2100000002 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2100000000} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 14b0bf07aa1abc44a8ebd00cecacd6f4, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::Spawner - objectToSpawn: {fileID: 700000000, guid: 8bf8957665594a718535d06aba0cdee7, type: 3} - spawnInterval: 3 - maxAlive: 1 - spawnOnStart: 1 - repeatSpawns: 0 --- !u!1660057539 &9223372036854775807 SceneRoots: m_ObjectHideFlags: 0 @@ -2859,9 +2681,6 @@ SceneRoots: - {fileID: 808792726} - {fileID: 495541366} - {fileID: 1118230347} - - {fileID: 477169536} - - {fileID: 1518904088} - - {fileID: 689117240} - {fileID: 1760117322204329348} - {fileID: 1277412258} - {fileID: 1227312797} @@ -2875,3 +2694,4 @@ SceneRoots: - {fileID: 29258076} - {fileID: 375061916} - {fileID: 2100000001} + - {fileID: 2100000101} diff --git a/Assets/Scripts/PlayerPickupController.cs b/Assets/Scripts/PlayerPickupController.cs index 539c120..6f50eb8 100644 --- a/Assets/Scripts/PlayerPickupController.cs +++ b/Assets/Scripts/PlayerPickupController.cs @@ -83,7 +83,14 @@ public class PlayerPickupController : MonoBehaviour Debug.Log(colliders.Length + " colliders found in range"); foreach (var col in colliders) { - if (!col.TryGetComponent(out var trick) && !col.CompareTag("Interactable")) + if (col.gameObject == gameObject) + { + continue; + } + + var hasTrick = col.TryGetComponent(out var trick); + var hasPlayer = col.TryGetComponent(out var playerController); + if (!hasTrick && !hasPlayer && !col.CompareTag("Interactable")) { continue; } @@ -108,6 +115,15 @@ public class PlayerPickupController : MonoBehaviour trick.SetCarried(true); } + if (playerController != null) + { + playerController.enabled = false; + if (heldObject.TryGetComponent(out var heldPickup)) + { + heldPickup.enabled = false; + } + } + if (col != null) col.enabled = false; break; } @@ -125,6 +141,14 @@ public class PlayerPickupController : MonoBehaviour { trick.SetCarried(false); } + if (heldObject.TryGetComponent(out var playerController)) + { + playerController.enabled = true; + if (heldObject.TryGetComponent(out var heldPickup)) + { + heldPickup.enabled = true; + } + } Collider2D col = heldObject.GetComponent(); if (col != null) col.enabled = true; diff --git a/Assets/Scripts/TrickCollisionManager.cs b/Assets/Scripts/TrickCollisionManager.cs new file mode 100644 index 0000000..621ee01 --- /dev/null +++ b/Assets/Scripts/TrickCollisionManager.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class TrickCollisionManager : MonoBehaviour +{ + private bool initialized; + + private void Awake() + { + Initialize(); + } + + private void Initialize() + { + if (initialized) + { + return; + } + + var trickLayer = LayerMask.NameToLayer("Trick"); + if (trickLayer == -1) + { + Debug.LogWarning("Trick layer not found. Create a layer named 'Trick' and assign it to Trick prefab."); + return; + } + + Physics2D.IgnoreLayerCollision(trickLayer, trickLayer, true); + initialized = true; + } +} diff --git a/Assets/Scripts/TrickCollisionManager.cs.meta b/Assets/Scripts/TrickCollisionManager.cs.meta new file mode 100644 index 0000000..5ce1d5a --- /dev/null +++ b/Assets/Scripts/TrickCollisionManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 44f2fea877e8498fa4898917356fb2e6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/TrickController.cs b/Assets/Scripts/TrickController.cs index aeff187..5b8e11c 100644 --- a/Assets/Scripts/TrickController.cs +++ b/Assets/Scripts/TrickController.cs @@ -12,6 +12,17 @@ public class TrickController : MonoBehaviour [SerializeField] private float wanderInterval = 1.2f; [SerializeField] private float consumeCooldown = 1.5f; [SerializeField] private TrickController trickPrefab; + [SerializeField] private float avoidPlayerRadius = 1.2f; + [SerializeField] private float avoidTrickRadius = 0.8f; + [SerializeField] private float treatSeekWeight = 1f; + [SerializeField] private float avoidPlayerWeight = 0.25f; + [SerializeField] private float avoidTrickWeight = 0.2f; + [SerializeField] private float wanderWeight = 0.4f; + [SerializeField] private float jumpImpulse = 6f; + [SerializeField] private float jumpCooldown = 1f; + [SerializeField] private float jumpChancePerSecond = 0.5f; + [SerializeField] private LayerMask groundMask = ~0; + [SerializeField] private float groundCheckDistance = 0.05f; private Rigidbody2D body; private Transform target; @@ -20,6 +31,8 @@ public class TrickController : MonoBehaviour private float nextWanderTime; private bool isCarried; private float nextConsumeTime; + private float desiredXVelocity; + private float nextJumpTime; private void Awake() { @@ -31,6 +44,7 @@ public class TrickController : MonoBehaviour body.interpolation = RigidbodyInterpolation2D.Interpolate; } + private void Update() { if (isCarried) @@ -54,7 +68,7 @@ public class TrickController : MonoBehaviour nextTargetTime = Time.time + targetRefreshInterval; } - if (target == null && Time.time >= nextWanderTime) + if (Time.time >= nextWanderTime) { wanderDirection = Random.insideUnitCircle.normalized; if (wanderDirection.sqrMagnitude < 0.01f) @@ -76,20 +90,43 @@ public class TrickController : MonoBehaviour Vector2 desiredVelocity; var stopForTreat = false; - if (target != null) + var avoidPlayerDirection = GetAvoidPlayerDirection(); + var avoidTrickDirection = GetAvoidTrickDirection(); + var hasTarget = target != null; + var canConsume = Time.time >= nextConsumeTime; + + var desiredX = 0f; + if (hasTarget) { var direction = ((Vector2)target.position - (Vector2)transform.position).normalized; - desiredVelocity = new Vector2(direction.x * moveSpeed, 0f); + desiredX += direction.x * treatSeekWeight; stopForTreat = Vector2.Distance(transform.position, target.position) <= consumeDistance; } else { - desiredVelocity = new Vector2(wanderDirection.x * (moveSpeed * 0.6f), 0f); + desiredX += wanderDirection.x * wanderWeight; } + if (!hasTarget || !canConsume) + { + desiredX += avoidPlayerDirection * avoidPlayerWeight; + } + desiredX += avoidTrickDirection * avoidTrickWeight; + + if (Mathf.Abs(desiredX) < 0.01f) + { + desiredX = wanderDirection.x * 0.2f; + } + + desiredVelocity = new Vector2(Mathf.Clamp(desiredX, -1f, 1f) * moveSpeed, 0f); + var velocity = body.linearVelocity; - velocity.x = stopForTreat ? 0f : desiredVelocity.x; + desiredXVelocity = stopForTreat ? 0f : desiredVelocity.x; + velocity.x = Mathf.Lerp(velocity.x, desiredXVelocity, 0.25f); body.linearVelocity = velocity; + + var isMoving = Mathf.Abs(desiredXVelocity) > 0.1f; + TryJump(isMoving); } private Transform FindNearestTreat() @@ -175,6 +212,126 @@ public class TrickController : MonoBehaviour Instantiate(gameObject, position, Quaternion.identity); } + private float GetAvoidPlayerDirection() + { + var players = FindObjectsByType(FindObjectsSortMode.None); + if (players == null || players.Length == 0) + { + return 0f; + } + + Transform closest = null; + var closestDist = float.MaxValue; + var origin = transform.position; + for (var i = 0; i < players.Length; i++) + { + var candidate = players[i]; + if (candidate == null || !candidate.gameObject.activeInHierarchy) + { + continue; + } + + var dist = Vector2.Distance(origin, candidate.transform.position); + if (dist < closestDist) + { + closestDist = dist; + closest = candidate.transform; + } + } + + if (closest == null || closestDist > avoidPlayerRadius) + { + return 0f; + } + + return Mathf.Sign(origin.x - closest.position.x); + } + + private float GetAvoidTrickDirection() + { + var tricks = FindObjectsByType(FindObjectsSortMode.None); + if (tricks == null || tricks.Length <= 1) + { + return 0f; + } + + Transform closest = null; + var closestDist = float.MaxValue; + var origin = transform.position; + for (var i = 0; i < tricks.Length; i++) + { + var candidate = tricks[i]; + if (candidate == null || candidate == this || !candidate.gameObject.activeInHierarchy) + { + continue; + } + + var dist = Vector2.Distance(origin, candidate.transform.position); + if (dist < closestDist) + { + closestDist = dist; + closest = candidate.transform; + } + } + + if (closest == null || closestDist > avoidTrickRadius) + { + return 0f; + } + + return Mathf.Sign(origin.x - closest.position.x); + } + + private void TryJump(bool isMoving) + { + if (!isMoving || Time.time < nextJumpTime) + { + return; + } + + if (!IsGrounded()) + { + return; + } + + var chance = jumpChancePerSecond * Time.fixedDeltaTime; + if (Random.value > chance) + { + return; + } + + var velocity = body.linearVelocity; + velocity.y = 0f; + body.linearVelocity = velocity; + body.AddForce(Vector2.up * jumpImpulse, ForceMode2D.Impulse); + nextJumpTime = Time.time + jumpCooldown; + } + + private bool IsGrounded() + { + var collider = GetComponent(); + if (collider == null) + { + return false; + } + + var bounds = collider.bounds; + var checkSize = new Vector2(bounds.size.x * 0.9f, groundCheckDistance * 2f); + var checkCenter = new Vector2(bounds.center.x, bounds.min.y - groundCheckDistance); + var hits = Physics2D.OverlapBoxAll(checkCenter, checkSize, 0f, groundMask); + for (var i = 0; i < hits.Length; i++) + { + var hit = hits[i]; + if (hit != null && hit != collider) + { + return true; + } + } + + return false; + } + + public void SetCarried(bool carried) { isCarried = carried; diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset index e3bd134..8374309 100644 --- a/ProjectSettings/TagManager.asset +++ b/ProjectSettings/TagManager.asset @@ -9,7 +9,7 @@ TagManager: - Default - TransparentFX - Ignore Raycast - - + - Trick - Water - UI - @@ -42,3 +42,5 @@ TagManager: - name: Default uniqueID: 0 locked: 0 + m_RenderingLayers: + - Default