Unity

[유니티] RPG 게임 만들기2

Skull Crusher 2021. 5. 28. 10:37
728x90

1. Trail Renderer

Width -> Color -> Element 설정

 

2.

Player -> Window -> Animation -> Attack1 -> Add event 추가

 

3.

 

4. 추적 카메라 추가

 

5. 슬라임 프리펩 추가

쉐이더 변경

애니메이터 추가

 

6. 애니스테이트 활용

 

7. 공격 피격 콜라이더 추가

 

8.  foreach in 사용

 

Add Layer -> Monster = Attack Layer Name

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

public class CharacterAttackController : MonoBehaviour
{
    [SerializeField] private Animator animator;

    public bool isAttack; // 공격 여부

    [SerializeField] private CharacterAttack characterAttack;

    [SerializeField] private string attackLayerName;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (isAttack) return;

        if (Input.GetKeyDown(KeyCode.Z))
        {
            animator.SetTrigger("Attack1");
        }
        else if (Input.GetKeyDown(KeyCode.X))
        {
            animator.SetTrigger("Attack2");
        }
    }

    public void OnNormalAttackAnimationEvent()
    {
        characterAttack.Attack(attackLayerName);
    }

    public void OnSkillAttackAnimationEvent()
    {

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

public class CharacterAttack : MonoBehaviour
{
    public Transform attackHitPoint; //피격 위치 포인트 참조

    public float attackRange; // 공격 범위

    public int damage; // 데미지

    //이펙트 표현이 필요한 공격에 수행할 이펙트 참조
    public GameObject attackShowEffectPrefab;

    //현재 공격이 피결될때 표현될 이펙트 참조
    public GameObject attackHitEffectPrefab;

    private void AttackShowEffect()
    {
        if (attackShowEffectPrefab = null) return;

        Instantiate(attackShowEffectPrefab, attackHitPoint.position, Quaternion.identity);
    }

    // 디폴트 매개변수 : 호출시 생략이 가능한 매개변수 (생략시 디폴트값으로 적용)
    // * 디폴트 매개변수는 오른쪽부터 적용 가능 

    // isKnockBack 매개변수는 디폴트 값으로 false를 설정함
    // 호출방식1 -> Attack(레이어이름, true/false)
    // 호출방식2 -> Attack(레이어이름) <==== 매개변수값 생략 가능 (생략시 디폴트 값으로 적용)
    // 호출방식3 -> Attack();
    public void Attack(string layerName, bool isKnockBack = false)
    {
        AttackShowEffect(); // 공격시 이펙트 재생

        // Physics.OverlapSphere(충돌체크위치, 검출위치, 1 << LayerMask.NameToLayer(충돌레이어);
        Collider[] hitMonsters = Physics.OverlapSphere(attackHitPoint.position, 
            attackRange, 1 << LayerMask.NameToLayer(layerName));

        // foreach : 순차적으로 목록화된 배열에서 순차적으로 하나의 요소를 접근할 때 사용하는 for 개량형 문법

        // foreach (요소변수 in 배열(컬렉션)변수)
        //{...}
        
        // for (int i=0; i<hitMonsters.Length; i++)
        foreach (Collider hitMonster in hitMonsters)
        {
            Debug.Log(hitMonster.name + ", " + hitMonster.transform.position);
        }
    }
}

9. 이펙트 prefabs 파일에 옮기기

 

Effects (1).zip
0.12MB

 

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

// 몬스터 체력/피격
public class MonsterHealth : MonoBehaviour
{
    // 피격 이펙트 생성 위치
    [SerializeField] private Transform hitEffectTrans;

    [SerializeField] private float knockBackSize; // 뒤로 밀리는 크기

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void Damage(GameObject hitEffectPrefab, int damage, bool isKnockBack = false)
    {
        //넉백이 데미지일 경우
        if (isKnockBack)
        {
            // 몬스터를 뒤로 밈
            transform.Translate(-Vector3.forward * knockBackSize);
        }

        // 체력 감소

        Instantiate(hitEffectPrefab, hitEffectTrans.position, Quaternion.identity);

    }
}

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

public class CharacterAttack : MonoBehaviour
{
    public Transform attackHitPoint; //피격 위치 포인트 참조

    public float attackRange; // 공격 범위

    public int damage; // 데미지

    //이펙트 표현이 필요한 공격에 수행할 이펙트 참조
    public GameObject attackShowEffectPrefab;

    //현재 공격이 피결될때 표현될 이펙트 참조
    public GameObject attackHitEffectPrefab;

    private void AttackShowEffect()
    {
        if (attackShowEffectPrefab = null) return;

        Instantiate(attackShowEffectPrefab, attackHitPoint.position, Quaternion.identity);
    }

    // 디폴트 매개변수 : 호출시 생략이 가능한 매개변수 (생략시 디폴트값으로 적용)
    // * 디폴트 매개변수는 오른쪽부터 적용 가능 

    // isKnockBack 매개변수는 디폴트 값으로 false를 설정함
    // 호출방식1 -> Attack(레이어이름, true/false)
    // 호출방식2 -> Attack(레이어이름) <==== 매개변수값 생략 가능 (생략시 디폴트 값으로 적용)
    // 호출방식3 -> Attack();
    public void Attack(string layerName, bool isKnockBack = false)
    {
        AttackShowEffect(); // 공격시 이펙트 재생

        // Physics.OverlapSphere(충돌체크위치, 검출위치, 1 << LayerMask.NameToLayer(충돌레이어);
        Collider[] hitMonsters = Physics.OverlapSphere(attackHitPoint.position, 
            attackRange, 1 << LayerMask.NameToLayer(layerName));

        // foreach : 순차적으로 목록화된 배열에서 순차적으로 하나의 요소를 접근할 때 사용하는 for 개량형 문법

        // foreach (요소변수 in 배열(컬렉션)변수)
        //{...}
        
        // for (int i=0; i<hitMonsters.Length; i++)
        foreach (Collider hitMonster in hitMonsters)
        {
            hitMonster.GetComponent<MonsterHealth>().Damage(attackHitEffectPrefab, damage, true);

            Debug.Log(hitMonster.name + ", " + hitMonster.transform.position);
        }
    }
}

 

10. 몬스터에 체력바 만들기

UI -> Canvas

그림판 -> box.png

 

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

using UnityEngine.UI;

// 몬스터 체력/피격
public class MonsterHealth : MonoBehaviour
{
    // 피격 이펙트 생성 위치
    [SerializeField] private Transform hitEffectTrans;

    [SerializeField] private float knockBackSize; // 뒤로 밀리는 크기

    [SerializeField] private int hp; // 총 체력
    private int currentHp;  // 현재 체력

    [SerializeField] private Image hpPregressImage;

    // Start is called before the first frame update
    void Start()
    {
        currentHp = hp; // 체력 설정
    }

    public void HpDown(int downValue)
    {
        if (currentHp < 0) return;

        currentHp = -downValue; // 체력 감소

        float resultHp = currentHp / hp; // 현재 체력의 비율을 계산

        hpPregressImage.fillAmount = resultHp; // 비율값을 체력 게이지에 적용
    }

    public void Damage(GameObject hitEffectPrefab, int damage, bool isKnockBack = false)
    {
        //넉백이 데미지일 경우
        if (isKnockBack)
        {
            // 몬스터를 뒤로 밈
            transform.Translate(-Vector3.forward * knockBackSize);
        }

        // 체력 감소
        HpDown(damage);
        
        // 피격 처리에 사용될 이펙트를 생성함
        Instantiate(hitEffectPrefab, hitEffectTrans.position, Quaternion.identity);

    }
}

 

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

public class UIBillboard : MonoBehaviour
{
    // Update is called once per frame
    void LateUpdate()
    {
        //메인 카메라의 시선과 일치하게 UI 게임오브젝트의 시선을 회전함
        transform.rotation = Quaternion.LookRotation(Camera.main.transform.forward);
    }
}