138 lines
4.6 KiB
C#
138 lines
4.6 KiB
C#
using UnityEngine;
|
|
#if ENABLE_INPUT_SYSTEM
|
|
using UnityEngine.InputSystem;
|
|
#endif
|
|
|
|
// Basic touch/mouse movement controller suitable for top-down 2D or 3D overworld
|
|
// Attach to the player GameObject. Works with or without Rigidbody/Rigidbody2D.
|
|
public class PlayerTouchController : MonoBehaviour
|
|
{
|
|
public float moveSpeed = 5f;
|
|
public float stopDistance = 0.1f;
|
|
|
|
// If true and a Rigidbody/Rigidbody2D is present, movement will use physics MovePosition.
|
|
public bool useRigidbody = true;
|
|
|
|
Vector3 targetPosition;
|
|
bool hasTarget = false;
|
|
|
|
Rigidbody rb3d;
|
|
Rigidbody2D rb2d;
|
|
|
|
void Awake()
|
|
{
|
|
rb3d = GetComponent<Rigidbody>();
|
|
rb2d = GetComponent<Rigidbody2D>();
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
// Initialize target to current position so object doesn't snap
|
|
targetPosition = transform.position;
|
|
hasTarget = false;
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
HandleInput();
|
|
if (hasTarget)
|
|
{
|
|
MoveTowardsTarget();
|
|
}
|
|
}
|
|
|
|
void HandleInput()
|
|
{
|
|
#if ENABLE_INPUT_SYSTEM
|
|
// Using the new Unity Input System (InputSystem package) only.
|
|
// Touch input (mobile)
|
|
if (Touchscreen.current != null && Touchscreen.current.touches.Count > 0)
|
|
{
|
|
var touch = Touchscreen.current.touches[0];
|
|
// press indicates the touch is down; use position even while moved/held
|
|
if (touch.press != null && touch.press.isPressed)
|
|
{
|
|
Vector2 pos = touch.position.ReadValue();
|
|
SetTargetFromScreenPoint(new Vector3(pos.x, pos.y, 0f));
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Mouse support (Editor/PC)
|
|
if (Mouse.current != null && Mouse.current.leftButton != null && Mouse.current.leftButton.isPressed)
|
|
{
|
|
Vector2 mpos = Mouse.current.position.ReadValue();
|
|
SetTargetFromScreenPoint(new Vector3(mpos.x, mpos.y, 0f));
|
|
}
|
|
#else
|
|
// Input System package not yet enabled/installed. Provide a helpful runtime message.
|
|
// This branch ensures the script compiles until the package is installed and Player Settings are set.
|
|
if (Application.isPlaying)
|
|
{
|
|
Debug.LogError("PlayerTouchController: New Input System is not enabled. Install 'com.unity.inputsystem' and set Active Input Handling to 'Input System Package' (or Both) in Player Settings, then restart the Editor.");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void SetTargetFromScreenPoint(Vector3 screenPoint)
|
|
{
|
|
Camera cam = Camera.main;
|
|
if (cam == null)
|
|
{
|
|
Debug.LogWarning("PlayerTouchController: No Camera.main found.");
|
|
return;
|
|
}
|
|
|
|
// Convert screen point to world point at the player's depth
|
|
Vector3 worldPoint = cam.ScreenToWorldPoint(new Vector3(screenPoint.x, screenPoint.y, cam.WorldToScreenPoint(transform.position).z));
|
|
// For 2D top-down games using orthographic camera, z will be player's z already.
|
|
targetPosition = worldPoint;
|
|
hasTarget = true;
|
|
}
|
|
|
|
void MoveTowardsTarget()
|
|
{
|
|
// Keep original y (or z for 2D) depending on scene setup. We assume the player moves on the plane defined by its current transform.
|
|
Vector3 current = transform.position;
|
|
|
|
// Create a target that preserves the movement plane (so we don't change vertical axis unexpectedly)
|
|
Vector3 planarTarget = targetPosition;
|
|
|
|
// If the camera is orthographic top-down (y is up), preserve y
|
|
// Heuristic: if camera forward is (0,-1,0) then y is up and we should preserve y
|
|
Camera cam = Camera.main;
|
|
if (cam != null && Vector3.Dot(cam.transform.forward, Vector3.down) > 0.5f)
|
|
{
|
|
planarTarget.y = current.y;
|
|
}
|
|
else
|
|
{
|
|
// Otherwise assume z is depth for 2D setups and preserve z
|
|
planarTarget.z = current.z;
|
|
}
|
|
|
|
float step = moveSpeed * Time.deltaTime;
|
|
Vector3 next = Vector3.MoveTowards(current, planarTarget, step);
|
|
|
|
// If using Rigidbody, move via physics when present
|
|
if (useRigidbody && rb2d != null)
|
|
{
|
|
rb2d.MovePosition(new Vector2(next.x, next.y));
|
|
transform.position = new Vector3(next.x, next.y, transform.position.z); // ensure transform matches
|
|
}
|
|
else if (useRigidbody && rb3d != null)
|
|
{
|
|
rb3d.MovePosition(next);
|
|
}
|
|
else
|
|
{
|
|
transform.position = next;
|
|
}
|
|
|
|
if (Vector3.Distance(transform.position, planarTarget) <= stopDistance)
|
|
{
|
|
hasTarget = false;
|
|
}
|
|
}
|
|
}
|