728x90
반응형
몬스터 HP바
Canvas위에 Image 2개를 생성하여 HP바를 구현하였다.
HP바가 항상 몬스터의 머리 위에 떠있게 유지시키기 위해서 몬스터의 좌표를 Canvas좌표로 변환하여
두 개의 Image에 전달해주었다.
public class EnemyMove : MonoBehaviour
{
public float hp;
public RectTransform HpBar;
public RectTransform HpBarBackGround;
// Start is called before the first frame update
void Start()
{
hp = 10;
}
// Update is called once per frame
void Update()
{
HpBar.position = Camera.main.WorldToScreenPoint(new Vector2(transform.position.x, transform.position.y + 1));
HpBarBackGround.position = Camera.main.WorldToScreenPoint(new Vector2(transform.position.x, transform.position.y + 1));
}
}
몬스터 피격
몬스터 피격 시 hp를 damage만큼 감소시키는 함수를 선언하고 PlayerMove 스크립트에서 피격 시 호출하였다.
public void EnemyTakeDamage(int damage)
{
hp -= damage;
HpBar.GetComponent<Image>().fillAmount = (float)hp / 10f;
Debug.Log(hp);
}
PlayerMove 스크립트
damage 함수를 호출함과 동시에 Vector2.Lerp 함수를 사용하여 넉백까지 구현하였다.
Collider2D[] collider2Ds = Physics2D.OverlapBoxAll(AttackPos.position, AttackBoxSize, 0);
foreach (Collider2D collider in collider2Ds)
{
if (collider.name == "Enemyprf(Clone)")
{
Enemy.GetComponent<EnemyMove>().EnemyTakeDamage(damage);
if (RightState == true)
EnemyKnockBackPos = new Vector2(Enemy.transform.position.x + 0.1f, Enemy.transform.position.y);
else
EnemyKnockBackPos = new Vector2(Enemy.transform.position.x - 0.1f, Enemy.transform.position.y);
}
}
Enemy.transform.position = Vector2.Lerp(Enemy.transform.position, EnemyKnockBackPos, 10 * Time.deltaTime);
몬스터 스폰
빈 오브젝트에 스크립트를 적용시키고 프리팹을 만들어서 몬스터의 스폰을 구현하였다.
적용된 코드는 다음과 같다.
public class EnemyGenerate : MonoBehaviour
{
public GameObject Enemyprf;
// Start is called before the first frame update
void Start()
{
GameObject Enemy = Instantiate(Enemyprf) as GameObject;
Enemy.transform.position = new Vector2(Random.Range(-55, 73) / 10f, -3.55f);
}
// Update is called once per frame
void Update()
{
}
}
몬스터 처치
몬스터의 HP가 0이하가 되면 Destory함수를 사용하여 프리팹을 삭제하고 Player의 경험치를 1 증가시켜준다.
if (hp <= 0)
{
player.GetComponent<PlayerMove>().exp++;
Destroy(gameObject);
}
최종코드
EnemyGenerate script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyGenerate : MonoBehaviour
{
public GameObject Enemyprf;
// Start is called before the first frame update
void Start()
{
GameObject Enemy = Instantiate(Enemyprf) as GameObject;
Enemy.transform.position = new Vector2(Random.Range(-55, 73) / 10f, -3.55f);
}
// Update is called once per frame
void Update()
{
}
}
EnemyMove script
using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EnemyMove : MonoBehaviour
{
Rigidbody2D MyRigidbody2D;
public float hp;
public RectTransform HpBar;
public RectTransform HpBarBackGround;
GameObject player;
public void EnemyTakeDamage(int damage)
{
hp -= damage;
HpBar.GetComponent<Image>().fillAmount = (float)hp / 10f;
Debug.Log(hp);
}
// Start is called before the first frame update
void Start()
{
hp = 10;
MyRigidbody2D = GetComponent<Rigidbody2D>();
player = GameObject.Find("Player");
}
// Update is called once per frame
void Update()
{
HpBar.position = Camera.main.WorldToScreenPoint(new Vector2(transform.position.x, transform.position.y + 1));
HpBarBackGround.position = Camera.main.WorldToScreenPoint(new Vector2(transform.position.x, transform.position.y + 1));
if (hp <= 0)
{
player.GetComponent<PlayerMove>().exp++;
Destroy(gameObject);
}
}
}
PlayerMove script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UIElements;
public class PlayerMove : MonoBehaviour
{
Rigidbody2D MyRigidbody2D;
Animator MyAnimator;
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.name == "Ground")
GroundTag = true;
}
public int exp = 0;
public int level = 1;
public int speed = 15;
public int jumpforce = 8;
public int damage = 1;
private float AttackTime = 0.56f;
public float CurAttackTime = 0;
public GameObject Enemy;
public Transform AttackPos;
private Vector2 AttackBoxSize = new Vector2(0.94f, 1.19f);
private Vector2 EnemyKnockBackPos;
bool RightState;
bool GroundTag = false;
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireCube(AttackPos.position, AttackBoxSize);
}
// Start is called before the first frame update
void Start()
{
MyRigidbody2D = GetComponent<Rigidbody2D>();
MyAnimator = GetComponent<Animator>();
RightState = true;
Enemy = GameObject.Find("Enemyprf(Clone)");
}
// Update is called once per frame
void Update()
{
if (Enemy == null)
Enemy = GameObject.Find("Enemyprf(Clone)");
MyAnimator.SetBool("Walk", false);
MyAnimator.SetBool("Attack", false);
if (CurAttackTime <= 0 && Input.GetKey(KeyCode.RightArrow))
{
MyAnimator.SetBool("Walk", true);
transform.Translate(0.001f * speed, 0, 0);
transform.localScale = Vector2.one;
RightState = true;
}
if (CurAttackTime <= 0 && Input.GetKey(KeyCode.LeftArrow))
{
MyAnimator.SetBool("Walk", true);
transform.Translate(-0.001f * speed, 0, 0);
transform.localScale = new Vector2(-1, 1);
RightState = false;
}
if (Input.GetKeyDown(KeyCode.LeftAlt) && (GroundTag && CurAttackTime <= 0))
{
GroundTag = false;
MyRigidbody2D.AddForce(new Vector2(0, 100*jumpforce));
}
if (CurAttackTime <= 0 && Input.GetKeyDown(KeyCode.LeftControl)) // 공격시작
{
if (RightState == true)
AttackPos.position = new Vector2(transform.position.x + 1.255f, transform.position.y - 0.3f);
else
AttackPos.position = new Vector2(transform.position.x - 1.255f, transform.position.y - 0.3f);
CurAttackTime = AttackTime;
if (Enemy != null)
{
Collider2D[] collider2Ds = Physics2D.OverlapBoxAll(AttackPos.position, AttackBoxSize, 0);
foreach (Collider2D collider in collider2Ds)
{
if (collider.name == "Enemyprf(Clone)")
{
Enemy.GetComponent<EnemyMove>().EnemyTakeDamage(damage);
if (RightState == true)
EnemyKnockBackPos = new Vector2(Enemy.transform.position.x + 0.1f, Enemy.transform.position.y);
else
EnemyKnockBackPos = new Vector2(Enemy.transform.position.x - 0.1f, Enemy.transform.position.y);
}
}
}
}
else if (CurAttackTime >= 0.3f)
{
MyAnimator.SetBool("Attack", true);
if (Enemy != null)
Enemy.transform.position = Vector2.Lerp(Enemy.transform.position, EnemyKnockBackPos, 10 * Time.deltaTime);
}
if (CurAttackTime >= 0)
CurAttackTime -= Time.deltaTime;
}
}
수정할 점
프리팹을 생성하여 여러 마리의 몬스터를 생성해보았는데 생성된 객체의 이름이 전부 같다보니 몬스터를 공격할 때
다른 몬스터의 체력이 감소하는 오류가 있었다.
오버랩 박스로 충돌을 감지할 때 충돌된 오브젝트에 접근하던가 피격 구현 코드를 EnemyMove 스크립트에 작성하여서
프리팹에 복제될 수 있도록 변경해야할 것 같다.
728x90
반응형
'유니티 > 유니티 연습프로젝트' 카테고리의 다른 글
[유니티/연습 프로젝트] 걷기 모션, 공격 모션, 근접 공격 범위 설정 (1) | 2023.10.10 |
---|---|
[유니티/연습 프로젝트] 캐릭터 이동 (0) | 2023.10.06 |