Untitled
unknown
csharp
8 months ago
6.4 kB
10
Indexable
using UnityEngine;
public class DragonController : MonoBehaviour
{
[Header("Movement")]
public float moveSpeed = 3f;
public float arriveThreshold = 0.1f;
[Header("Wander")]
public bool enableWander = true;
public float wanderRadius = 2.5f;
public float wanderInterval = 2.0f;
[Header("Drag / Touch")]
public bool draggable = true;
public float dragSmooth = 15f; // how smoothly it follows finger/mouse
[Header("Screen Clamp")]
public float margin = 0.2f; // padding from screen edges in world units
[Header("Optional")]
public Animator animator; // put your Animator here, set float "Speed"
// internal
Vector3 targetPos;
bool hasTarget = false;
float wanderTimer = 0f;
bool isDragging = false;
Camera mainCam;
Vector3 dragOffset;
void Start()
{
mainCam = Camera.main;
targetPos = transform.position;
wanderTimer = wanderInterval;
}
void Update()
{
HandleInput();
if (isDragging) return; // dragging logic moves in HandleInput (smoothed)
if (hasTarget)
{
MoveTowardsTarget();
}
else if (enableWander)
{
WanderBehaviour();
}
ClampToScreen();
UpdateAnimator();
FlipSpriteBasedOnVelocity();
}
void HandleInput()
{
// Mouse (Editor / PC)
#if UNITY_EDITOR || UNITY_STANDALONE || UNITY_WEBGL
if (draggable)
{
if (Input.GetMouseButtonDown(0))
{
Vector3 wp = ScreenToWorld(Input.mousePosition);
if (PointHitsThis(wp))
{
isDragging = true;
dragOffset = transform.position - wp;
}
else
{
// clicked elsewhere -> move there
targetPos = wp;
hasTarget = true;
}
}
else if (Input.GetMouseButton(0) && isDragging)
{
Vector3 wp = ScreenToWorld(Input.mousePosition);
Vector3 desired = wp + dragOffset;
transform.position = Vector3.Lerp(transform.position, desired, Time.deltaTime * dragSmooth);
hasTarget = false;
}
else if (Input.GetMouseButtonUp(0) && isDragging)
{
isDragging = false;
}
}
else
{
if (Input.GetMouseButtonDown(0))
{
targetPos = ScreenToWorld(Input.mousePosition);
hasTarget = true;
}
}
#endif
// Touch (Mobile)
if (Input.touchCount > 0)
{
Touch t = Input.GetTouch(0);
Vector3 wp = ScreenToWorld(t.position);
if (t.phase == TouchPhase.Began)
{
if (draggable && PointHitsThis(wp))
{
isDragging = true;
dragOffset = transform.position - wp;
}
else
{
targetPos = wp;
hasTarget = true;
isDragging = false;
}
}
else if ((t.phase == TouchPhase.Moved || t.phase == TouchPhase.Stationary) && isDragging)
{
Vector3 desired = wp + dragOffset;
transform.position = Vector3.Lerp(transform.position, desired, Time.deltaTime * dragSmooth);
hasTarget = false;
}
else if (t.phase == TouchPhase.Ended || t.phase == TouchPhase.Canceled)
{
isDragging = false;
}
}
}
void MoveTowardsTarget()
{
Vector3 pos = transform.position;
Vector3 dir = (targetPos - pos);
dir.z = 0;
float dist = dir.magnitude;
if (dist <= arriveThreshold)
{
hasTarget = false;
return;
}
Vector3 move = dir.normalized * moveSpeed * Time.deltaTime;
transform.position += move;
}
void WanderBehaviour()
{
wanderTimer -= Time.deltaTime;
if (wanderTimer <= 0f)
{
wanderTimer = wanderInterval;
// pick random point nearby
Vector2 rnd = Random.insideUnitCircle * wanderRadius;
targetPos = transform.position + new Vector3(rnd.x, rnd.y, 0f);
hasTarget = true;
}
}
void ClampToScreen()
{
if (mainCam == null) return;
Vector3 min = mainCam.ViewportToWorldPoint(new Vector3(0, 0, mainCam.nearClipPlane));
Vector3 max = mainCam.ViewportToWorldPoint(new Vector3(1, 1, mainCam.nearClipPlane));
Vector3 p = transform.position;
p.x = Mathf.Clamp(p.x, min.x + margin, max.x - margin);
p.y = Mathf.Clamp(p.y, min.y + margin, max.y - margin);
transform.position = p;
}
void UpdateAnimator()
{
if (animator != null)
{
float spd = 0f;
if (isDragging) spd = (dragSmooth * 0.1f);
else if (hasTarget) spd = moveSpeed;
else spd = 0f;
animator.SetFloat("Speed", Mathf.Abs(spd));
}
}
void FlipSpriteBasedOnVelocity()
{
// Flip by comparing target x vs current x
if (hasTarget || isDragging)
{
float dx = (targetPos.x - transform.position.x);
if (isDragging)
{
// approximate direction by last input
// do nothing if too small
if (Mathf.Abs(dx) > 0.01f)
GetComponent<SpriteRenderer>().flipX = dx < 0;
}
else
{
if (Mathf.Abs(dx) > 0.01f)
GetComponent<SpriteRenderer>().flipX = dx < 0;
}
}
}
Vector3 ScreenToWorld(Vector3 screenPos)
{
Vector3 wp = mainCam.ScreenToWorldPoint(screenPos);
wp.z = 0f;
return wp;
}
bool PointHitsThis(Vector3 worldPoint)
{
// basic point check using collider
Collider2D col = GetComponent<Collider2D>();
if (col == null) return false;
return col.OverlapPoint(worldPoint);
}
}Editor is loading...
Leave a Comment