유니티3D 프로그래밍

Unity NGUI 클릭 움직임 구현 (21.04.28) 본문

Unity/수업내용

Unity NGUI 클릭 움직임 구현 (21.04.28)

tjdgus9955 2021. 4. 28. 17:02

 

 

화면을 클릭해 클릭한 방향으로 움직이는 것을 구현한다.

 

현재 화면을 구성하는 오브젝트. 비활성화된 오브젝트는 현재 상황에 필요없는 UI들이다.

 

이 3가지 스크립트 중 Hero, Test가 움직임을 구현하는 스크립트다.

Hero 스크립트

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Hero : MonoBehaviour
{
    public Transform hudGaugeTrans;
    public GameObject gaugeGo;
    public Animator anim;
    public float speed = 2f;
    private Coroutine routine;

    private void Start()
    {
        this.anim.Play("idle");
    }

    void Update()
    {
        //https://www.tasharen.com/forum/index.php?topic=14754.0
        //https://www.tasharen.com/ngui/docs/class_n_g_u_i_math.html
        Vector3 overlay = NGUIMath.WorldToLocalPoint(this.hudGaugeTrans.position, Camera.main, UICamera.mainCamera, gaugeGo.transform);
        overlay.z = 0.0f;
        //Debug.Log(overlay);
        gaugeGo.transform.localPosition = overlay;
    }

    public void Move(Vector3 tpos)
    {
        if (this.routine != null)
        {
            StopCoroutine(this.routine);
        }
        this.routine = StartCoroutine(this.MoveImpl(tpos));
    }

    private IEnumerator MoveImpl(Vector3 tpos)
    {
        this.anim.Play("run");
        if (this.transform.position.x < tpos.x)
        {
            this.transform.localScale = Vector3.one;
        }
        else
        {
            this.transform.localScale = new Vector3(-1f, 1f, 1f);
        }
        while (true)
        {
            var dir = (tpos - this.transform.position).normalized;
            this.transform.Translate(dir * speed * Time.deltaTime);
            var distance = Vector3.Distance(tpos, this.transform.position);
            if (distance <= 0.1f)
            {
                this.anim.Play("idle");
                break;
            }
            yield return null;
        }
    }
}

overlay를 통해 Hp바의 위치가 Hero의 움직임을 따라간다. Coroutine을 이용하여 파라미터로 입력 받은 벡터 값으로 가야할 위치를 계산 후 움직인다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    public GameObject gaugeGo;
    public Hero hero;

    void Start()
    {

    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            Debug.DrawRay(ray.origin, ray.direction * 1000, Color.red, 1.0f);

            
            var hit = Physics2D.Raycast(ray.origin, ray.direction, 1000);
            Debug.Log(hit);
            if (hit)
            {
                Debug.Log(hit.point);
                this.hero.Move(hit.point);
            }
        }
    }
}

마우스를 화면에 클릭하면 ray를 통해 그 위치를 받아오고 Raycast로 벡터 값을 구한 뒤 그 값을 Hero 스크립트가 있는 오브젝트로 그 값을 넘겨준다.

 

캐릭터 동적 생성

 

위의 내용을 바탕으로 캐릭터를 미리 만들어 둔 것이 아닌 Json파일을 통해 캐릭터의 특성을 정해두고 그 특성을 바탕으로 동적 생성을 한다.

 

동적 생성 전

 

동적 생성 후

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CharacterData
{
    public int id;
    public string name;
    public int max_hp;
    public int damage;
    public float move_speed;
    public float attack_range;
    public string prefab_name;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Hero : MonoBehaviour
{
    //public Transform hudGaugeTrans;
    //public Transform hudDamageTrans;
    //public GameObject gaugeGo;
    public Animator anim;
    //public float speed = 2f;
    private Coroutine routine;
    private GameObject model;
    private CharacterData data;

    public void Init(GameObject model, CharacterData data)
    {
        this.data = data;
        this.model = model;
        this.anim = this.model.GetComponent<Animator>();
        this.anim.Play("idle");
    }

    void Update()
    {
        //https://www.tasharen.com/forum/index.php?topic=14754.0
        //https://www.tasharen.com/ngui/docs/class_n_g_u_i_math.html
        //Vector3 overlay = NGUIMath.WorldToLocalPoint(this.hudGaugeTrans.position, Camera.main, UICamera.mainCamera, gaugeGo.transform);
        //overlay.z = 0.0f;
        //Debug.Log(overlay);
        //gaugeGo.transform.localPosition = overlay;
    }

    public void Move(Vector3 tpos)
    {
        if (this.routine != null)
        {
            StopCoroutine(this.routine);
        }
        this.routine = StartCoroutine(this.MoveImpl(tpos));
    }

    private IEnumerator MoveImpl(Vector3 tpos)
    {
        this.anim.Play("run");
        if (this.transform.position.x < tpos.x)
        {
            this.transform.localScale = Vector3.one;
        }
        else
        {
            this.transform.localScale = new Vector3(-1f, 1f, 1f);
        }
        while (true)
        {
            var dir = (tpos - this.transform.position).normalized;
            this.transform.Translate(dir * this.data.move_speed * Time.deltaTime);
            var distance = Vector3.Distance(tpos, this.transform.position);
            if (distance <= 0.1f)
            {
                this.anim.Play("idle");
                break;
            }
            yield return null;
        }
    }
}
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HudText : MonoBehaviour
{
    public UILabel label;
    public void Init(int damage)
    {
        this.label.text = damage.ToString();

        var endpos = this.label.transform.position.y + 200;

        float myFloat = 1f;
        var color = this.label.color;
        DOTween.To(() => myFloat, x => myFloat = x, 0f, 0.5f).onUpdate = () => {
            color.a = myFloat;
            this.label.color = color;
        };

        this.label.transform.DOScale(2, 0.2f).onComplete = () => {
            this.label.transform.DOScale(1, 0.2f);
        };
        this.label.transform.DOLocalMoveY(endpos, 0.5f).SetEase(Ease.OutQuad).onComplete = () => {
            Debug.Log("easing complete!");
            Destroy(this.gameObject);
        };
    }
}
using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class Test : MonoBehaviour
{
    public GameObject gaugeGo;
    public Hero hero;
    //    public UIButton btn;
    //    public GameObject labelPrefab;
    //    public UIPanel panel;
    //public GameObject labelGo;
    private Dictionary<int, CharacterData> dicCharacterDatas;
    private Dictionary<int, GameObject> dicPrefabs = new Dictionary<int, GameObject>();

    void Start()
    {
        var json = Resources.Load<TextAsset>("hero_data").text;
        this.dicCharacterDatas = JsonConvert.DeserializeObject<CharacterData[]>(json).ToDictionary(x => x.id);

        foreach(var pair in this.dicCharacterDatas)
        {
            var go = Resources.Load<GameObject>(pair.Value.prefab_name);
            this.dicPrefabs.Add(pair.Value.id, go);
        }

        this.CreateHero(100);
        //this.btn.onClick.Add(new EventDelegate(() => {
        //    GameObject go = NGUITools.AddChild(this.panel.gameObject, labelPrefab);
        //    Vector3 overlay = NGUIMath.WorldToLocalPoint(
        //        this.hero.hudDamageTrans.position,
        //        Camera.main,
        //        UICamera.mainCamera,
        //        go.transform);
        //    overlay.z = 0.0f;
        //    go.transform.localPosition = overlay;

        //    var hud = go.GetComponent<HudText>();
        //    hud.Init(9999);

        //}));
    }

    public void CreateHero(int id)
    {
        GameObject go = new GameObject();
        var data = this.dicCharacterDatas[id];
        go.name = data.prefab_name;

        var model = Instantiate<GameObject>(this.dicPrefabs[id]);
        model.transform.SetParent(go.transform);
        model.name = "model";

        this.hero = go.AddComponent<Hero>();
        this.hero.Init(model, data);
    }
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            Debug.DrawRay(ray.origin, ray.direction * 1000, Color.red, 1.0f);

            
            var hit = Physics2D.Raycast(ray.origin, ray.direction, 1000);
            Debug.Log(hit);
            if (hit)
            {
                Debug.Log(hit.point);
                this.hero.Move(hit.point);
            }
        }
    }

}