Untitled

 avatar
unknown
csharp
9 months ago
6.4 kB
12
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