I am trying to get the movement path (line renderer) being previewed while hovering, and the character moves only when the player clicks to confirm the destination, but it only works once. When I try to do it afterwards, the OnTouchInputPerformed and OnTouchInputCanceled methods never get executed (TouchInput action in the Unity Input system). Apologies for the long code. Code:
[SerializeField] private InputActionAsset inputActions;
private InputAction touchAction;
private InputAction touchPressAction;
private bool isDragging = false;
private Vector3 targetPosition;
private GameManager gameManager;
private List<Vector3> currentPath = new List<Vector3>();
private int currentMovementPoints;
[SerializeField] private LineRenderer lineRenderer;
[SerializeField] private float touchDragThreshold = 20f;
private void Awake()
{
var touchActionMap = inputActions.FindActionMap("Touch");
touchAction = touchActionMap.FindAction("TouchInput");
touchPressAction = touchActionMap.FindAction("TouchPress");
touchAction.performed += OnTouchInputPerformed;
touchAction.canceled += OnTouchInputCanceled;
touchPressAction.performed += OnTouchPress;
lineRenderer.positionCount = 0;
InitializeLineRenderer();
}
private void OnTouchInputPerformed(InputAction.CallbackContext context)
{
Debug.Log("TouchInput performed.");
isDragging = true; // Start dragging when touch begins
Vector2 touchPosition = touchAction.ReadValue<Vector2>();
Debug.Log("Touch input performed at position: " + touchPosition);
ProcessTouchInput(touchPosition, isDragging);
}
private void OnTouchInputCanceled(InputAction.CallbackContext context)
{
Debug.Log("TouchInput canceled.");
isDragging = false; // Stop dragging when touch ends
ClearPathPreview(); // Clear the preview when touch is released
}
private void OnTouchPress(InputAction.CallbackContext context)
{
Debug.Log("TouchPress detected.");
if (currentPath.Count > 0)
{
Debug.Log("currentPath.Count in OnTouchPress: " + currentPath.Count);
StartCoroutine(MoveAlongPath(gameManager.currentState == GameManager.GameState.Combat));
}
else
{
Debug.Log("No path to move.");
}
}
private void ProcessTouchInput(Vector2 touchPosition, bool isDragging)
{Debug.Log("ProcessTouchInput is here");
// Check game state before processing touch input
if (gameManager.currentState != GameManager.GameState.Exploration && gameManager.currentState != GameManager.GameState.Combat)
{
Debug.LogWarning("Invalid game state for processing touch input.");
return;
}
Ray ray = Camera.main.ScreenPointToRay(touchPosition);
if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity))
{
Vector3Int targetGridPosition = GridManager.instance.GetGridPosition(hit.point);
Debug.Log("Target Grid Position: " + targetGridPosition);
if (isDragging)
{
if (currentPath.Count == 0 || targetGridPosition != GridManager.instance.GetGridPosition(currentPath.Last()))
{
currentPath = CalculatePath(hit.point);
Debug.Log("Dragging: Calculated new path with " + currentPath.Count + " points.");
ShowPathPreview(currentPath);
}
}
else
{
List<Vector3> path = CalculatePath(hit.point);
Debug.Log("Hovering: Calculated path preview with " + path.Count + " points.");
ShowPathPreview(path);
}
}
}
private List<Vector3> CalculatePath(Vector3 targetPosition)
{ Debug.Log("CalculatePath is here");
Vector3Int startGridPos = GridManager.instance.GetGridPosition(transform.position);
Vector3Int endGridPos = GridManager.instance.GetGridPosition(targetPosition);
Debug.Log("Calculating path from " + startGridPos + " to " + endGridPos);
List<Vector3Int> path = AStarSearch(startGridPos, endGridPos);
if (path == null)
{
Debug.LogWarning("No path found.");
return new List<Vector3>();
}
List<Vector3> worldPath = path.Select(GridManager.instance.GetWorldPosition).ToList();
Debug.Log("Calculated path with " + worldPath.Count + " points.");
return worldPath;
}
private int Heuristic(Vector3Int a, Vector3Int b)
{ Debug.Log("Heuristic is here.");
return Mathf.Abs(a.x - b.x) + Mathf.Abs(a.z - b.z);
}
private List<Vector3Int> AStarSearch(Vector3Int start, Vector3Int end)
{ Debug.Log("AStarSearch is here.");
PriorityQueue<Vector3Int, int> frontier = new PriorityQueue<Vector3Int, int>();
frontier.Enqueue(start, 0);
Dictionary<Vector3Int, Vector3Int> cameFrom = new Dictionary<Vector3Int, Vector3Int>();
Dictionary<Vector3Int, int> costSoFar = new Dictionary<Vector3Int, int>();
cameFrom[start] = start;
costSoFar[start] = 0;
while (frontier.Count > 0)
{
Vector3Int current = frontier.Dequeue();
Debug.Log("Exploring node: " + current);
if (current.Equals(end))
{
Debug.Log("Reached end node.");
return ReconstructPath(cameFrom, end, start);
}
foreach (Vector3Int next in GridManager.instance.GetNeighbors(current))
{
int newCost = costSoFar[current] + GridManager.instance.GetMovementCost(next);
if (!costSoFar.ContainsKey(next) || newCost < costSoFar[next])
{
costSoFar[next] = newCost;
int priority = newCost + Heuristic(end, next);
frontier.Enqueue(next, priority);
cameFrom[next] = current;
}
}
}
Debug.LogWarning("No path found from " + start + " to " + end);
return null;
}
private List<Vector3Int> ReconstructPath(Dictionary<Vector3Int, Vector3Int> cameFrom, Vector3Int end, Vector3Int start)
{ Debug.LogWarning("ReconstructPath is here.");
List<Vector3Int> path = new List<Vector3Int>();
Vector3Int current = end;
while (!current.Equals(cameFrom[current]))
{
path.Add(current);
current = cameFrom[current];
}
path.Add(start);
path.Reverse();
return path;
}
private void ShowPathPreview(List<Vector3> path)
{Debug.LogWarning("ShowPathPreview is here.");
if (lineRenderer != null)
{
lineRenderer.positionCount = path.Count;
lineRenderer.SetPositions(path.ToArray());
Debug.Log("LineRenderer path preview updated with " + path.Count + " points.");
}
else
{
Debug.LogWarning("LineRenderer is not assigned.");
}
}
private void ClearPathPreview()
{Debug.LogWarning("ClearPathPreview is here.");
if (lineRenderer != null)
{ isDragging = true; // Stop dragging when touch ends
lineRenderer.positionCount = 0;
}
}
private IEnumerator MoveAlongPath(bool isCombat)
{ Debug.Log("MoveAlongPath is here.");
if (currentPath == null || currentPath.Count == 0)
{
Debug.Log("No path available to move along.");
yield break;
}
isMoving = true;
gameManager.movingCharacters.Add(this);
while (currentPath.Count > 0)
{
Vector3 targetWorldPosition = currentPath[0];
yield return MoveAndAnimateRoutine(targetWorldPosition, null);
if (currentPath.Count > 0)
{
currentPath.RemoveAt(0);
}
UpdatePathPreview(currentPath);
yield return null;
}
isMoving = false;
if (!isCombat)
{
currentMovementPoints = stats.maxAP;
}
gameManager.movingCharacters.Remove(this);
currentPath.Clear();
CompleteAction();
ClearPathPreview();
}
private void UpdatePathPreview(List<Vector3> path)
{
ClearPathPreview();
ShowPathPreview(path);
}
I have tried to change the TouchInput action multiple times from changing the action type from Value to Button, Button to Pass Through, but that actually makes it worse and stops it from working completely. I have removed the Hold Interaction, which oddly enough doesn’t do anything. I don’t know if it’s an issue with the code because it works the first go, so usually that’s an issue with the Input Action, right?