티스토리 뷰

오늘 한 것

  • Vector3 기준으로 작동하던 이동 방식을 Degree 각도 기준으로 변경.
  • 공격용 오브젝트 작성
    • 투사체 오브젝트의 각도 문제 수정
    • 파동 오브젝트 추가
    • 구체 오브젝트 추가
  • 플레이어가 공격의 주체가 될 수 있도록 구성
    • 마우스 휠을 이용한 스킬 전환 구현
    • 마우스 버튼을 이용한 스킬 및 평타 사용 기능 구현

 

결과물

 

코드

이동

더보기
public void Move_Chara(float _velocity)
{
    Vector2 Mouse_Pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    // 탄젠트 값을 이용하여 Radian 각도를 구한 뒤 이를 Degree 각도로 치환하는 공식.
    Angle_Mouse = Mathf.Atan2(Mouse_Pos.y - transform.position.y, Mouse_Pos.x - transform.position.x) * Mathf.Rad2Deg;
    // 두 점 간의 거리를 구하는 함수.
    float distance = Vector3.Distance(transform.position, Mouse_Pos);
    
    if (distance > 3.5)
    {
        transform.position += Quaternion.Euler(0.0f, 0.0f, Angle_Mouse) * Vector3.right * 5.0f * _velocity;
        Stamina.Dec_Gauge(1);
    }

    else if (distance > 1)
    {
        transform.position += Quaternion.Euler(0.0f, 0.0f, Angle_Mouse) * Vector3.right * _velocity;
    }

    else
    {
        Stamina.Inc_Gauge(1);
    }
}

투사체

더보기

투사체 오브젝트

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

public class Projectile : MonoBehaviour
{
    public bool is_friendly;

    public int[] Damage = new int[5];
    public int Pierce_Max;
    int Pierce_Cur;
    public List<int> Fork;
    public float Time_Max = 1.0f;
    float Time_Cur;

    public float velocity;
    public Vector3 Size;
    public float rotate;
    Vector3 Direction;
    public Sprite Shape;
    SpriteRenderer Rend;

    List<GameObject> Hitted_Units = new List<GameObject>();

    private void Start()
    {
        Pierce_Cur = Pierce_Max;
        Rend = GetComponent<SpriteRenderer>();
        Rend.sprite = Shape;
        transform.localScale = Size;
        transform.rotation = Quaternion.Euler(0.0f, 0.0f, rotate);
        Time_Cur = 0.0f;
    }

    private void Update()
    {
        Direction = transform.rotation * Vector3.right;

        transform.position += Direction * velocity;

        Time_Cur += Time.deltaTime;

        if (Time_Cur >= Time_Max)
            Destroy(gameObject);
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        bool Affective = false;

        if (is_friendly)
        {
            if (collision.gameObject.CompareTag("Enemy"))
                Affective = true;
        }

        else
        {
            if (collision.gameObject.CompareTag("Player"))
                Affective = true;
        }

        if (Affective && !Hitted_Units.Contains(collision.gameObject))
        {
            collision.gameObject.GetComponent<Chara_Base>().Get_Damage(Damage);
            Hitted_Units.Add(collision.gameObject);

            if (Pierce_Cur > 0)
                Pierce_Cur--;

            else if (Fork.Count > 0)
            {
                Pierce_Cur = Pierce_Max;

                int Fork_Temp = Fork[0];
                Fork.RemoveAt(0);

                for (int j = 0; j < Fork_Temp; j++)
                {
                    float Fork_rotate = rotate + (((((float)Fork_Temp - 1.0f) / 2.0f) - j) * 30.0f);

                    GameObject Sub_Projectile = Instantiate(this.gameObject, position: transform.position, rotation: Quaternion.Euler(0.0f, 0.0f, Fork_rotate));

                    Projectile Sub_Proj_Script = Sub_Projectile.gameObject.GetComponent<Projectile>();
                    Sub_Proj_Script.rotate = Fork_rotate;
                    Sub_Proj_Script.Hitted_Units = Hitted_Units;
                    Sub_Proj_Script.Time_Cur = Time_Cur;
                }

                Destroy(this.gameObject);
            }

            else
                Destroy(this.gameObject);
        }
    }
}

 

투사체 발사 함수

public void Shoot_Proj(Vector3 _Position, float _rotation, float _velocity, float _Size, int[] _Damage)
{
    GameObject temp = Instantiate(Projectile_Pref, _Position, Quaternion.identity);
    temp.SetActive(false);

    Projectile temp_Proj = temp.GetComponent<Projectile>();
    temp_Proj.is_friendly = true;
    temp_Proj.velocity = _velocity;
    temp_Proj.rotate = transform.rotation.z + _rotation;
    temp_Proj.Fork.Add(3);
    temp_Proj.Damage = _Damage;
    temp_Proj.Size = new Vector3(_Size, _Size, 1.0f);

    temp.SetActive(true);
}

파동

더보기

파동 오브젝트

public class Pulse : MonoBehaviour
{
    public bool is_friendly;

    public int[] Damage = new int[5];

    public Animator Anim;
    public float speed = 1.0f;
    float E_Time;
    float C_Time;

    public Vector3 Size;

    private void Start()
    {
        transform.localScale = Size;

        Anim = GetComponent<Animator>();
        Anim.SetFloat("E_Speed", speed);

        E_Time = 1.25f / speed;
        C_Time = 0.0f;
    }

    private void Update()
    {
        C_Time += Time.deltaTime;

        if (C_Time >= E_Time)
        {
            Destroy(gameObject);
        }
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        bool Affective = false;

        if (is_friendly)
        {
            if (collision.gameObject.CompareTag("Enemy"))
                Affective = true;
        }

        else
        {
            if (collision.gameObject.CompareTag("Player"))
                Affective = true;
        }

        if (Affective)
        {
            collision.gameObject.GetComponent<Chara_Base>().Get_Damage(Damage);
        }
    }
}

 

파동 발산 함수

public void Emit_Pulse(Vector3 _Position, float E_Speed, float _Size, int[] _Damage)
{
    GameObject temp = Instantiate(Pulse_Pref, _Position, Quaternion.identity);
    temp.SetActive(false);

    Pulse temp_Pul = temp.GetComponent<Pulse>();
    temp_Pul.is_friendly = true;
    temp_Pul.speed = E_Speed;
    temp_Pul.Damage = _Damage;
    temp_Pul.Size = new Vector3(_Size, _Size, 1.0f);

    temp.SetActive(true);
}

구체

더보기

구체 오브젝트

public class Orb : MonoBehaviour
{
    public bool is_friendly;

    public int[] Damage = new int[5];
    public float Time_Max = 5.0f;
    float Time_Cur;
    public float TIme_Term = 0.5f;
    bool is_On;
    float Timer;
    List<GameObject> Hitted_Units = new List<GameObject>();

    Animator Anim;
    public Vector3 Size;
    public float Direction;
    public float velocity;

    private void Start()
    {
        transform.localScale = Size;
        Time_Cur = 0.0f;
        Timer = 0.0f;
        is_On = false;

        Anim = GetComponent<Animator>();
    }

    private void Update()
    {
        Time_Cur += Time.deltaTime;

        transform.position += Quaternion.Euler(new Vector3(0.0f, 0.0f, Direction)) * Vector3.right * velocity;

        if(is_On)
            Timer += Time.deltaTime;

        if(Timer >= TIme_Term)
        {
            Timer -= TIme_Term;
            Hitted_Units.Clear();
        }

        if (Time_Cur >= 0.5f && !is_On)
        {
            Time_Cur = 0.0f;
            is_On = true;
        }

        if (Time_Cur >= Time_Max)
        {
            is_On = false;
            Anim.SetBool("is_End", true);
            Invoke("Destroy_this", 0.5f);
        }
    }

    private void OnTriggerStay2D(Collider2D collision)
    {
        bool Affective = false;

        if (is_friendly)
        {
            if (collision.gameObject.CompareTag("Enemy"))
                Affective = true;
        }

        else
        {
            if (collision.gameObject.CompareTag("Player"))
                Affective = true;
        }

        if (Affective && !Hitted_Units.Contains(collision.gameObject) && is_On)
        {
            Hitted_Units.Add(collision.gameObject);
            collision.gameObject.GetComponent<Chara_Base>().Get_Damage(Damage);
        }
    }

    void Destroy_this()
    {
        Destroy(gameObject);
    }
}

 

구체 생성 함수

public void Create_Orb(Vector3 _Position, float _Time_Max, float _Time_Term, float _Size, float _velocity, float _Direction, int[] _Damage)
{
    GameObject temp = Instantiate(Orb_Pref, _Position, Quaternion.identity);
    temp.SetActive(false);

    Orb temp_Orb = temp.GetComponent<Orb>();
    temp_Orb.is_friendly = true;
    temp_Orb.Time_Max = _Time_Max;
    temp_Orb.TIme_Term = _Time_Term;
    temp_Orb.velocity = _velocity;
    temp_Orb.Direction = _Direction;
    temp_Orb.Damage = _Damage;
    temp_Orb.Size = new Vector3(_Size, _Size, 1.0f);

    temp.SetActive(true);
}

스킬 사용 관련 코드 (일부)

더보기

스킬 버튼 UI

public class Skill_Button : MonoBehaviour
{
    public Chara_Base Chara;

    public GameObject Cursor;
    public GameObject OFF_Display;

    public int Skill_Num;
    public int Gauge_Need;

    private void Update()
    {
        if (Chara.Cur_Skill == Skill_Num)
            Cursor.SetActive(true);
        else
            Cursor.SetActive(false);

        if (Chara.Point_Cur >= Gauge_Need)
            OFF_Display.SetActive(false);
        else
            OFF_Display.SetActive(true);
    }
}

 

스킬 사용 코드

if (Input.GetMouseButtonDown(0) && Point_Cur >= 2)
{
    int[] Damage_Bark = { 15, 0, 0, 0, 0 };
    Emit_Pulse(transform.position, 1.0f, 7.5f, Damage_Bark);
}

if (Input.GetMouseButtonDown(1))
{
    if (Cur_Skill == 1 && Point_Cur >= 1)
    {
        Point_Use(8.0f, 1);
        int[] Damage_Skill = { 25, 0, 0, 0, 0 };
        Shoot_Proj(transform.position, Angle_Mouse, 0.1f, 8.0f, Damage_Skill);
    }

    else if (Cur_Skill == 2 && Point_Cur >= 3)
    {
        Point_Use(3.0f, 3);
        int[] Damage_Skill = { 10, 0, 0, 0, 0 };
        Emit_Pulse(transform.position + (Quaternion.Euler(0.0f, 0.0f, Angle_Mouse) * Vector3.right * 2.0f), 1.0f, 2.5f, Damage_Skill);
        Emit_Pulse(transform.position + (Quaternion.Euler(0.0f, 0.0f, Angle_Mouse) * Vector3.right * 3.0f), 1.0f, 2.5f, Damage_Skill);
        Emit_Pulse(transform.position + (Quaternion.Euler(0.0f, 0.0f, Angle_Mouse) * Vector3.right * 4.0f), 1.0f, 2.5f, Damage_Skill);
    }

    else if (Cur_Skill == 3 && Point_Cur >= 2)
    {
        Point_Use(5.0f, 2);
        int[] Damage_Skill = { 4, 0, 0, 0, 0 };
        Create_Orb(transform.position + (Quaternion.Euler(0.0f, 0.0f, Angle_Mouse) * Vector3.right * 2.0f), 2.5f, 0.25f, 1.5f, 0.01f, Angle_Mouse, Damage_Skill);
    }
}

float Input_Wheel = Input.GetAxis("Mouse ScrollWheel");
if (Input_Wheel > 0)
{
    Cur_Skill++;
    if (Cur_Skill >= 4)
        Cur_Skill = 1;
}

else if (Input_Wheel < 0)
{
    Cur_Skill--;
    if (Cur_Skill <= 0)
        Cur_Skill = 3;
}

 

정리하며

이틀 전에 언급했듯이, 오늘은 기존에 제작했던 것 들을 다듬고, 공격용 객체와 플레이어 컨트롤 시스템을 작성하였습니다.

이제 여기에 적 캐릭터 관련 요소 및 필드 관련 요소들 만 작성하면 1차적으로 테스트를 해볼 수 있는 버전이 됩니다.

물론, 그 뒤에도 스킬 시스템과 장비 시스템, 타이틀(+ 설정), 세이브 시스템 등등 작성해야 할 것들은 아직 많긴 하지만, 그래도 단판 테스트는 가능하게 됩니다.

그래도 이제 플레이어 조작 관련 최소 요구 기능은 거의 작업 완료된 거 같네요.

 

여담으로, 기믹 대처용으로 점프를 넣으려고 했는데 2D로 기반을 만들어놔서 3D로 바꾸면 세로로 정렬이 되어 버립니다. 그래서 살짝 골치 아픈데, 아마 실제 좌표가 변하는 게 아닌, 점프 지속 시간 동안 특수한 상태가 적용되는 방식을 사용하거나 좌표랑 각도, 벡터 다 뜯어고쳐서 3D로 엎게 되지 않을까 싶습니다.

일단 어찌되었건 아직 점프를 작성할 단계는 아니라서 좀 더 고민해보지 싶네요.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함