로그라이크나 탑다운 슈팅 게임에서 사용할 수 있는 스크립트 입니다.

벽에 가려지지 않은 몬스터들 중에서 가장 가까운 몬스터를 반환하는 스크립트입니다.

 


[전체 코드]

    public Transform Target()
    {
        Transform result = null;
        GameObject[] activating_monsters = GameObject.FindGameObjectsWithTag("Monster");
        List<GameObject> ray_hitted_monsters = new List<GameObject>();

        foreach (GameObject monster in activating_monsters)
        {
            RaycastHit2D ray_hit = Physics2D.Raycast(transform.position, monster.transform.position - transform.position, 1000, (-1) - (1 << LayerMask.NameToLayer("Player")));

            if (ray_hit.collider.tag == "Monster")
            {
                ray_hitted_monsters.Add(ray_hit.collider.gameObject);
            }
        }

        if (ray_hitted_monsters.Count > 0)
        {
            result = ray_hitted_monsters[0].transform;

            float distance_with_monster = Vector2.Distance(transform.position, result.transform.position);

            foreach (GameObject monster in ray_hitted_monsters)
            {
                float distance = Vector2.Distance(transform.position, monster.transform.position);

                if (distance < distance_with_monster)
                {
                    result = monster.transform;
                    distance_with_monster = distance;
                }
            }
        }

        return result;
    }

 


        Transform result = null;
        GameObject[] activating_monsters = GameObject.FindGameObjectsWithTag("Monster");
        List<GameObject> ray_hitted_monsters = new List<GameObject>();

 

result = 반환해야하는 값

activating_monsters = 현재 씬에 Monster 태그가 붙어있는 모든 몬스터들

  • 로그라이크에 사용하려면 맵 이동 시에 activating_monsters를 설정해주면 됩니다.
  • 현재는 테스트 중이므로 임의로 사용한 코드입니다.

ray_hitted_monsters = 벽에 가려져있지 않은 몬스터들

 


        foreach (GameObject monster in activating_monsters)
        {
            RaycastHit2D ray_hit = Physics2D.Raycast(transform.position, monster.transform.position - transform.position, 1000, (-1) - (1 << LayerMask.NameToLayer("Player")));

            if (ray_hit.collider.tag == "Monster")
            {
                ray_hitted_monsters.Add(ray_hit.collider.gameObject);
            }
        }

 

모든 몬스터들 중 RaycastHit2D를 활용하여 Monster 태그가 붙어있으면 ray_hitted_monsters에 저장합니다.

무기가 플레이어 자식 오브젝트로, 플레이어 중심으로 실행되기 때문에 Player 레이어는 제외하고 실행합니다.

 


        if (ray_hitted_monsters.Count > 0)
        {
            result = ray_hitted_monsters[0].transform;

            float distance_with_monster = Vector2.Distance(transform.position, result.transform.position);

            foreach (GameObject monster in ray_hitted_monsters)
            {
                float distance = Vector2.Distance(transform.position, monster.transform.position);

                if (distance < distance_with_monster)
                {
                    result = monster.transform;
                    distance_with_monster = distance;
                }
            }
        }

 

만약 모든 몬스터 중 벽에 가려지지 않은 몬스터가 있다면 실행되는 코드입니다.

ray_hitted_monsters 중 가장 가까운 거리의 몬스터를 찾는 스크립트 입니다.

'Unity' 카테고리의 다른 글

[Unity] 조이스틱으로 플레이어 이동  (2) 2023.11.10

- 플레이어 이동 코드는 예시로 작성하였습니다. 플레이어 이동 코드는 stick_direction 변수를 사용하여 만드시면 됩니다.

 


[전체 코드]

using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;

public class Joy_Stick : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler
{
    public Transform stick;
    public Transform player;

    private Vector3 stick_offset_position;
    private Vector3 stick_direction;
    private float joy_stick_radius;

    void Start()
    {
        Set_Radius();
    }

    private IEnumerator Move_Player()
    {
        while (true)
        {
            player.Translate(stick_direction * Time.deltaTime * 10.0f);

            yield return null;
        }
    }

    private void Set_Radius()
    {
        joy_stick_radius = GetComponent<RectTransform>().sizeDelta.y * 0.5f;

        float canvas_radius = transform.parent.GetComponent<RectTransform>().localScale.x;
        joy_stick_radius *= canvas_radius;
    }

    public void OnDrag(PointerEventData eventData)
    {
        Vector3 touch_position = Camera.main.ScreenToWorldPoint(eventData.position);
        touch_position.z = 0;

        stick_direction = (touch_position - stick_offset_position).normalized;

        float touch_distance = Vector3.Distance(touch_position, stick_offset_position);

        if (touch_distance < joy_stick_radius)
        {
            stick.position = stick_offset_position + stick_direction * touch_distance;
        }
        else
        {
            stick.position = stick_offset_position + stick_direction * joy_stick_radius;
        }
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        stick_offset_position = stick.transform.position;

        StartCoroutine(Move_Player());
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        StopAllCoroutines();

        stick.position = stick_offset_position;
        stick_direction = Vector3.zero;
    }
}

    public void OnPointerDown(PointerEventData eventData)
    {
        stick_offset_position = stick.transform.position;

        StartCoroutine(Move_Player());
    }​

- 조이스틱을 터치 하였을 때 스틱의 초기 위치를 설정.

- 플레이어 이동 코루틴 실행

 


    public void OnPointerUp(PointerEventData eventData)
    {
        StopAllCoroutines();

        stick.position = stick_offset_position;
        stick_direction = Vector3.zero;
    }

- 조이스틱을 누른 후 손가락을 화면에서 때었을 때 실행.

- 모든 코루틴을 정지

- 스틱을 초기 위치에 설정.

- 조이스틱 방향 초기화

 


    public void OnDrag(PointerEventData eventData)
    {
        Vector3 touch_position = Camera.main.ScreenToWorldPoint(eventData.position);
        touch_position.z = 0;

        stick_direction = (touch_position - stick_offset_position).normalized;

        float touch_distance = Vector3.Distance(touch_position, stick_offset_position);

        if (touch_distance < joy_stick_radius)
        {
            stick.position = stick_offset_position + stick_direction * touch_distance;
        }
        else
        {
            stick.position = stick_offset_position + stick_direction * joy_stick_radius;
        }
    }

        Vector3 touch_position = Camera.main.ScreenToWorldPoint(eventData.position);
        touch_position.z = 0;

- 터치 한 곳의 위치값을 받아온 후 z값을 0으로 변경.


        stick_direction = (touch_position - stick_offset_position).normalized;

- 현재 터치 중인 위치와 스틱의 초기 위치를 사용하여 현재 터치 위치의 방향을 받아옴.


        float touch_distance = Vector3.Distance(touch_position, stick_offset_position);

        if (touch_distance < joy_stick_radius)
        {
            stick.position = stick_offset_position + stick_direction * touch_distance;
        }
        else
        {
            stick.position = stick_offset_position + stick_direction * joy_stick_radius;
        }

- 터치 중인 위치와 스틱의 초기 위치에 비례한 거리와 조이스틱의 반지름 크기를 비교하여 더 작다면 스틱을 현재 터치 중인 곳으로, 더 크다면 위치를 조이스틱의 반지름 크기에 비례하여 이동.

 

 


    private void Set_Radius()
    {
        joy_stick_radius = GetComponent<RectTransform>().sizeDelta.y * 0.5f;

        float canvas_radius = transform.parent.GetComponent<RectTransform>().localScale.x;
        joy_stick_radius *= canvas_radius;
    }

 

Set_Radius()

- 조이스틱의 크기와 캔버스의 크기에 비례해서 반지름을 계산.

- 인 게임 중에서는 처음에 한 번만 불러오기 때문에 Awake나 Start에서 사용.

 

 

 

 

 

 

 

 

'Unity' 카테고리의 다른 글

[Unity] 유니티 가장 가까운 몬스터 찾기  (0) 2023.11.10

+ Recent posts