From 48c499251789e19b851758f0df8971214e21a048 Mon Sep 17 00:00:00 2001 From: Michal Pikulski Date: Tue, 2 Sep 2025 13:20:17 +0200 Subject: [PATCH] [Player] Add simple Pulver point-based following behind Trafalgar. Leave option for manually-directed movement. --- .../Prefabs/Characters/PlayerCharacter.prefab | 8 +- .../Prefabs/Characters/PulverCharacter.prefab | 24 ++- Assets/Scenes/AppleHillsOverworld.unity | 16 +- Assets/Scripts/FollowerController.cs | 149 +++++++++++++++++- ProjectSettings/Physics2DSettings.asset | 24 +-- ProjectSettings/TagManager.asset | 4 +- 6 files changed, 199 insertions(+), 26 deletions(-) diff --git a/Assets/Prefabs/Characters/PlayerCharacter.prefab b/Assets/Prefabs/Characters/PlayerCharacter.prefab index c9a2a47f..9841d205 100644 --- a/Assets/Prefabs/Characters/PlayerCharacter.prefab +++ b/Assets/Prefabs/Characters/PlayerCharacter.prefab @@ -15,9 +15,9 @@ GameObject: - component: {fileID: 2999879259114430221} - component: {fileID: 7393789300602426170} - component: {fileID: 1676944588148945034} - m_Layer: 0 + m_Layer: 7 m_Name: PlayerCharacter - m_TagString: Untagged + m_TagString: Player m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 @@ -221,6 +221,10 @@ PrefabInstance: propertyPath: m_Name value: Trafalgar objectReference: {fileID: 0} + - target: {fileID: 784715772773378889, guid: 361ccc9ef82acef4784b24b72013d971, type: 3} + propertyPath: m_Layer + value: 7 + objectReference: {fileID: 0} - target: {fileID: 7877460049793670011, guid: 361ccc9ef82acef4784b24b72013d971, type: 3} propertyPath: m_LocalScale.x value: 0.5 diff --git a/Assets/Prefabs/Characters/PulverCharacter.prefab b/Assets/Prefabs/Characters/PulverCharacter.prefab index 06b474e7..2d32198b 100644 --- a/Assets/Prefabs/Characters/PulverCharacter.prefab +++ b/Assets/Prefabs/Characters/PulverCharacter.prefab @@ -11,7 +11,8 @@ GameObject: - component: {fileID: 6668392923879433376} - component: {fileID: 2732140975288177209} - component: {fileID: 566650525959955209} - m_Layer: 0 + - component: {fileID: 7160527734420460260} + m_Layer: 8 m_Name: PulverCharacter m_TagString: Untagged m_Icon: {fileID: 0} @@ -125,3 +126,24 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!114 &7160527734420460260 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1102468210854536367} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f82afe7b57bd4e0b9f51a1cca06765f1, type: 3} + m_Name: + m_EditorClassIdentifier: + followDistance: 2 + debugDrawTarget: 1 + followUpdateInterval: 0.1 + manualMoveSmooth: 5 + acceleration: 10 + deceleration: 12 + thresholdFar: 5 + thresholdNear: 3 + stopThreshold: 0.25 diff --git a/Assets/Scenes/AppleHillsOverworld.unity b/Assets/Scenes/AppleHillsOverworld.unity index 9532e7ea..466e09d5 100644 --- a/Assets/Scenes/AppleHillsOverworld.unity +++ b/Assets/Scenes/AppleHillsOverworld.unity @@ -495,11 +495,11 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 7046219584904338117, guid: 5e0579453a4cbae438cf2422f6786a48, type: 3} propertyPath: m_LocalPosition.x - value: -4.53 + value: -8.54 objectReference: {fileID: 0} - target: {fileID: 7046219584904338117, guid: 5e0579453a4cbae438cf2422f6786a48, type: 3} propertyPath: m_LocalPosition.y - value: -0.5 + value: -1.01 objectReference: {fileID: 0} - target: {fileID: 7046219584904338117, guid: 5e0579453a4cbae438cf2422f6786a48, type: 3} propertyPath: m_LocalPosition.z @@ -552,11 +552,11 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 7046219584904338117, guid: 5e0579453a4cbae438cf2422f6786a48, type: 3} propertyPath: m_LocalPosition.x - value: 4.49 + value: 5.6 objectReference: {fileID: 0} - target: {fileID: 7046219584904338117, guid: 5e0579453a4cbae438cf2422f6786a48, type: 3} propertyPath: m_LocalPosition.y - value: 3.49 + value: 4.5 objectReference: {fileID: 0} - target: {fileID: 7046219584904338117, guid: 5e0579453a4cbae438cf2422f6786a48, type: 3} propertyPath: m_LocalPosition.z @@ -614,11 +614,11 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 7046219584904338117, guid: 5e0579453a4cbae438cf2422f6786a48, type: 3} propertyPath: m_LocalPosition.x - value: -1.42 + value: -4.43 objectReference: {fileID: 0} - target: {fileID: 7046219584904338117, guid: 5e0579453a4cbae438cf2422f6786a48, type: 3} propertyPath: m_LocalPosition.y - value: 3.37 + value: 6.43 objectReference: {fileID: 0} - target: {fileID: 7046219584904338117, guid: 5e0579453a4cbae438cf2422f6786a48, type: 3} propertyPath: m_LocalPosition.z @@ -22743,11 +22743,11 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 6668392923879433376, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3} propertyPath: m_LocalPosition.x - value: -3.03 + value: -2.83 objectReference: {fileID: 0} - target: {fileID: 6668392923879433376, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3} propertyPath: m_LocalPosition.y - value: -1.2 + value: -1.89 objectReference: {fileID: 0} - target: {fileID: 6668392923879433376, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3} propertyPath: m_LocalPosition.z diff --git a/Assets/Scripts/FollowerController.cs b/Assets/Scripts/FollowerController.cs index e02abfc9..51f880ed 100644 --- a/Assets/Scripts/FollowerController.cs +++ b/Assets/Scripts/FollowerController.cs @@ -1 +1,148 @@ - +using UnityEngine; +using Pathfinding; + +public class FollowerController : MonoBehaviour +{ + [Header("Follower Settings")] + public float followDistance = 1.5f; // Desired distance behind player + public bool debugDrawTarget = true; + public float followUpdateInterval = 0.1f; // How often to update follow logic + public float manualMoveSmooth = 8f; // Smoothing factor for manual movement + + private Transform playerTransform; + private AIPath playerAIPath; + private AIPath aiPath; + private Vector3 targetPoint; + private float timer; + private bool usePathfinding = false; + private bool isManualFollowing = true; // Default to manual following + private Vector3 lastMoveDir = Vector3.right; // Default direction + private float currentSpeed = 0f; + + [Header("Speed Settings")] + public float acceleration = 10f; + public float deceleration = 12f; + public float thresholdFar = 2.5f; + public float thresholdNear = 0.5f; + public float stopThreshold = 0.1f; // Stop moving when within this distance + private float playerMaxSpeed = 5f; + + void Awake() + { + aiPath = GetComponent(); + } + + void Start() + { + // Find player by tag + GameObject playerObj = GameObject.FindGameObjectWithTag("Player"); + if (playerObj != null) + { + playerTransform = playerObj.transform; + playerAIPath = playerObj.GetComponent(); + // Fetch player's max speed + if (playerAIPath != null) + { + playerMaxSpeed = playerAIPath.maxSpeed; + } + } + else + { + Debug.LogError("FollowerController: Player object with tag 'Player' not found."); + } + } + + void UpdateFollowTarget() + { + // Determine direction: use player's velocity if available, else lastMoveDir + Vector3 playerPos = playerTransform.position; + Vector3 moveDir = Vector3.zero; + if (playerAIPath != null && playerAIPath.velocity.magnitude > 0.01f) + { + moveDir = playerAIPath.velocity.normalized; + lastMoveDir = moveDir; // Update last valid direction + } + else + { + moveDir = lastMoveDir; // Use last direction if stationary + } + // Calculate target point behind player + targetPoint = playerPos - moveDir * followDistance; + targetPoint.z = 0; // For 2D + + // Always use manual following unless GoToPoint is called + isManualFollowing = true; + if (aiPath != null) + { + aiPath.enabled = false; + } + } + + void Update() + { + if (playerTransform == null) + return; + + timer += Time.deltaTime; + if (timer >= followUpdateInterval) + { + timer = 0f; + UpdateFollowTarget(); + } + + // Manual movement logic with acceleration/deceleration and stop threshold + if (isManualFollowing) + { + float dist = Vector3.Distance(transform.position, targetPoint); + if (dist > stopThreshold) + { + float desiredSpeed = playerMaxSpeed; + if (dist > thresholdFar) + { + // Accelerate to player's max speed + desiredSpeed = Mathf.Min(currentSpeed + acceleration * Time.deltaTime, playerMaxSpeed); + } + else if (dist <= thresholdNear && dist > stopThreshold) + { + // Decelerate as approaching target, but keep moving until stopThreshold + desiredSpeed = Mathf.Max(currentSpeed - deceleration * Time.deltaTime, 0.5f); + } + else + { + // Maintain player's max speed + desiredSpeed = playerMaxSpeed; + } + currentSpeed = desiredSpeed; + Vector3 dir = (targetPoint - transform.position).normalized; + transform.position += dir * currentSpeed * Time.deltaTime; + } + else + { + // Stop moving when close enough + currentSpeed = 0f; + } + } + } + + // Command follower to go to a specific point (pathfinding mode) + public void GoToPoint(Vector2 worldPosition) + { + isManualFollowing = false; + if (aiPath != null) + { + aiPath.enabled = true; + aiPath.destination = new Vector3(worldPosition.x, worldPosition.y, 0); + } + } + + void OnDrawGizmos() + { + if (debugDrawTarget && Application.isPlaying) + { + Gizmos.color = Color.cyan; + Gizmos.DrawSphere(targetPoint, 0.2f); + Gizmos.color = Color.yellow; + Gizmos.DrawLine(transform.position, targetPoint); + } + } +} diff --git a/ProjectSettings/Physics2DSettings.asset b/ProjectSettings/Physics2DSettings.asset index 6cfcddaa..2f011ef7 100644 --- a/ProjectSettings/Physics2DSettings.asset +++ b/ProjectSettings/Physics2DSettings.asset @@ -3,12 +3,12 @@ --- !u!19 &1 Physics2DSettings: m_ObjectHideFlags: 0 - serializedVersion: 5 + serializedVersion: 6 m_Gravity: {x: 0, y: -9.81} m_DefaultMaterial: {fileID: 0} m_VelocityIterations: 8 m_PositionIterations: 3 - m_VelocityThreshold: 1 + m_BounceThreshold: 1 m_MaxLinearCorrection: 0.2 m_MaxAngularCorrection: 8 m_MaxTranslationSpeed: 100 @@ -19,6 +19,7 @@ Physics2DSettings: m_LinearSleepTolerance: 0.01 m_AngularSleepTolerance: 2 m_DefaultContactOffset: 0.01 + m_ContactThreshold: 0 m_JobOptions: serializedVersion: 2 useMultithreading: 0 @@ -39,18 +40,17 @@ Physics2DSettings: m_IslandSolverBodiesPerJob: 50 m_IslandSolverContactsPerJob: 50 m_SimulationMode: 0 + m_SimulationLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_MaxSubStepCount: 4 + m_MinSubStepFPS: 30 + m_UseSubStepping: 0 + m_UseSubStepContacts: 0 m_QueriesHitTriggers: 1 m_QueriesStartInColliders: 1 m_CallbacksOnDisable: 1 m_ReuseCollisionCallbacks: 1 m_AutoSyncTransforms: 0 - m_AlwaysShowColliders: 0 - m_ShowColliderSleep: 1 - m_ShowColliderContacts: 0 - m_ShowColliderAABB: 0 - m_ContactArrowScale: 0.2 - m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} - m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} - m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} - m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} - m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + m_GizmoOptions: 10 + m_LayerCollisionMatrix: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset index fa916ce8..fa293395 100644 --- a/ProjectSettings/TagManager.asset +++ b/ProjectSettings/TagManager.asset @@ -12,8 +12,8 @@ TagManager: - Water - UI - WorldObstacle - - - - + - Player + - Pulver - - -