Skip to content

2 ‐ PlayerManager

문현우 edited this page Sep 13, 2023 · 15 revisions

📌 PlayerManager

🎇 Managed by 김광수

  • PlayerManager는 플레이어를 생성하고 관리하는 기능을 담당합니다.

📜 Code Summary

  • PlayerType Enum

    • 플레이어의 유형을 정의하는 열거형입니다.
    • 각 플레이어를 대표하는 상수 값을 가지고 있습니다.
  • Awake()

    • PlayerManger의 인스턴스를 생성합니다.
    • 플레이어 매니저의 인스턴스를 설정하여, 다른 스크립트에서 PlayerManager에 접근할 수 있게됩니다.
  • CreatePlayer()

    • 지정된 유형의 플레이어를 생성합니다.
    • 미리 지정된 플레이어 Prefab을 가져와 인스턴화합니다.
    • 인스턴스화된 GameObject에 Player 컴포넌트를 추가합니다.
    • 이후 해당 컴포넌트를 반환합니다.

💻 Code

PlayerManager.cs
using UnityEngine;

public enum PlayerType
{
    ZombiePlayer1,
    ZombiePlayer2,
    SkelletionPlayer1,
    SkelletionPlayer2,
    MonsterPlayer,

}
public class PlayerManager : MonoBehaviour
{
    public static PlayerManager Instance { get; private set; }

    [SerializeField] private GameObject[] playerPrefabs = new GameObject[5];

    public Player player{  get; private set; }

    private void Awake()
    {
        if (Instance == null) Instance = this;
    }

    public Player CreatePlayer(PlayerType type)
    {
        GameObject go = Instantiate(playerPrefabs[(int)type]);
        player = go.GetComponent<Player>();
        return player;
    }
}

✔️ Player

🎇 Managed by 김광수

  • 플레이어 캐릭터를 정의하며, 캐릭터의 체력, 이동 속도, 공격 및 피해 관련 동작을 다룹니다.

📜 Code Summary

  • Start()

    • IsAttack 변수를 false로 초기화하고, maxHp를 hp 값으로 설정합니다.
  • Update()

    • 매 프레임마다 호출되며, attack_cool_time 변수를 업데이트합니다.
  • AttackCharacter()

    • 플레이어의 공격 동작을 처리합니다.
    • attack_cool_time이 0보다 크면 공격을 실행하지 않습니다.
    • IsAttack를 true로 설정하고 1초 후에 CompleteAttack 메서드를 호출하여 공격을 완료합니다.
    • attack_cool_time을 3초로 설정하여 쿨다운을 시작합니다.
  • TakeDamage()

    • 플레이어가 피해를 받았을 때 호출됩니다.
    • 애니메이션 트리거 "Hit"을 활성화하고 체력(hp)을 감소시킵니다.
    • 체력이 0 이하로 내려가면 0으로 설정하고, GameManager의 HitPlayer() 메서드를 호출하여 게임 매니저에게 플레이어가 피해를 받았음을 알립니다.
  • TakePotion()

    • 플레이어가 포션을 먹었을 때 호출됩니다.
    • 현재 체력(hp)이 최대 체력(maxHp)보다 작으면 체력을 1 증가시킵니다.
    • GameManager의 TakePotion() 메서드를 호출하여 게임 매니저에게 포션을 먹었다는 정보를 전달합니다.
  • CompleteAttack()

    • 공격 동작이 완료되었을 때 호출됩니다.
    • IsAttack을 false로 설정하여 플레이어가 더 이상 공격 중이 아님을 나타냅니다.

💻 Code

Player.cs
using UnityEngine;

public class Player : MonoBehaviour, ICharacter
{
    [SerializeField] private int hp;
    [SerializeField] private float speed;
    [SerializeField] Animator anim;
    [SerializeField] Animator atkAnim;

    public int maxHp;
    public int Hp { get { return hp; } }
    public float Speed { get { return speed; } }

    public bool IsAttack { get; private set; }

    float attack_cool_time = 0f;

    private void Start()
    {
        IsAttack = false;
        maxHp = hp;
    }
    private void Update()
    {
        attack_cool_time-= Time.deltaTime;
    }
    public void AttackCharacter()
    {
        if (attack_cool_time > 0f) return;
        IsAttack = true;
        Invoke("CompleteAttack", 1f);
        attack_cool_time = 3f;
    }

    public void TakeDamage()
    {
        anim.SetTrigger("Hit");
        hp -= 1;

        if (hp < 0) { hp = 0; }
        GameManager.Instance.HitPlayer();
    }

   public void TakePotion()
    {
        if(hp < maxHp)
        {
            hp += 1;
        }
        GameManager.Instance.TakePotion();
    }

    public void CompleteAttack()
    {
        IsAttack=false;
    }

}

✔️ Enemy

🎇 Managed by 김광수

  • 플레이어를 향해 이동하고, 공격하는 적을 구현합니다.

📜 Code Summary

  • AttackCharacter()

    • 적을 공격합니다. 대기시간이 끝났는지 확인합니다.
    • 만약 대기시간이 끝났다면, 플레이어에게 탄환을 발사합니다. 이후 다시 대기시간을 설정합니다.
  • RotateEnemyToPalyer()

    • 적이 플레이를 바라보도록 회전하는 메서드입니다.
    • 플레이어와 적의 방향 벡터를 계산하여 적을 회전시킵니다.
  • FlipXEnemy()

    • 적이 왼쪽을 바라보고 있다면, 수평으로 뒤집습니다.
    • 적의 몸체, 팔 스프라이트를 뒤집습니다.
  • TakeDamage()

    • 적이 플레이어 공격의 피해를 받습니다.
    • 적을 게임에서 제거하고 게임 오브젝트를 파괴합니다.

💻 Code

Player.cs
using UnityEngine;

public class Enemy : MonoBehaviour, ICharacter
{
    float remainCoolTime = 0f;
    float COOL_TIME = 4.5f;
    Vector3 moveDirection = Vector3.right;
    [SerializeField] private SpriteRenderer body;
    [SerializeField] private SpriteRenderer left;
    [SerializeField] private SpriteRenderer right;
    [SerializeField] private Transform spawnBullet;

    Vector3 leftPos = Vector3.zero;
    Vector3 rightPos = Vector3.zero;
    bool isFlip = false;

    private void Start()
    {
        leftPos = left.transform.position;
        rightPos = right.transform.position;
    }

    private void Update()
    {
        remainCoolTime -= Time.deltaTime;
        if (remainCoolTime <= 0f) AttackCharacter();
    }

    private void FixedUpdate()
    {
        RotateEnemyToPlayer();
    }

    public void AttackCharacter()
    {
        int rate = Random.Range(0, 100);
        BulletType type;
        float speed;
        if (rate >= 98)
        {
            type = BulletType.Bomb;
            speed = Random.Range(3.5f, 4.5f);
        }
        else if(rate >= 95)
        {
            type = BulletType.Potion;
            speed = Random.Range(3.5f, 4.5f);
        }
        else
        {
            type = BulletType.Enemy;
            speed = Random.Range(0.5f, 2f);
        }

        BulletManager.Instance.ShotBullet(type, spawnBullet.position, speed);
        remainCoolTime = COOL_TIME;
    }

    private void RotateEnemyToPlayer()
    {
        moveDirection = (PlayerManager.Instance.player.transform.position - transform.position).normalized;
        float rotZ = Mathf.Atan2(moveDirection.y, moveDirection.x) * Mathf.Rad2Deg;
        FlipXEnemy(Mathf.Abs(rotZ) > 90);
    }    

    private void FlipXEnemy(bool result)
    {
        if (isFlip != result)
        {
            body.flipX = result;
            left.flipX = result;
            right.flipX = result;

            if (result == true)
            {    
                left.transform.position = rightPos;
                right.transform.position = leftPos;
                right.transform.rotation = Quaternion.Euler(0, 0, 45f);
                isFlip = true;
            }
            else
            {
                left.transform.position = leftPos;
                right.transform.position = rightPos;
                right.transform.rotation = Quaternion.Euler(0, 0, -45f);
                isFlip = false;
            }
            
        }
        
    }

    public void TakeDamage() 
    {
        EnemyManager.Instance.Enemies.Remove(this);
        Destroy(gameObject);
    }
}

✔️ Interface ICharacter

🎇 Managed by 김광수

  • ICharacter 인터페이스는 게임 캐릭터의 기본적인 동작을 정의하는 인터페이스입니다.
  • ICharacter 인터페이스는 게임 캐릭터를 구현하는 데 사용할 수 있습니다.
  • 이 인터페이스를 구현하는 클래스는 AttackCharacter() 메서드를 사용하여 캐릭터를 공격하고, TakeDamage() 메서드를 사용하여 캐릭터가 피해를 받았을 때 처리할 수 있습니다.

📜 Code Summary

  • AttackCharacter()

    • 캐릭터를 공격합니다.
  • TakeDamage()

    • 캐릭터가 피해를 받습니다.

💻 Code

ICharacter
interface ICharacter
{
    void AttackCharacter();
    void TakeDamage();
}

✔️TopDownAimRotation

🎇 Managed by 이성권

  • 캐릭터의 조준을 구현을 담당합니다.

📜 Code Summary

  • Awake()

    • OnAim()에 대한 리스너를 등록합니다.
  • Start(0

    • OnAIm() 메서드를 호출하여 캐릭터를 조준합니다.
  • _controller

    • 캐릭터의 이동과 조준을 처리하는 컴포넌트입니다.
  • OnAim()

    • 캐릭터가 조준할 때 호출되는 메서드입니다. 캐릭터를 새로운 조준 방향으로 회전합니다.
  • RotatePlayer()

    • 캐릭터를 새로운 조준 방향으로 회전하는 메서드입니다. 캐릭터의 SpriteRenderer 컴포넌트의 FlipX 속성을 사용하여 캐릭터를 수평으로 뒤집습니다.

💻 Code

TopDownAimRotation.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TopDownAimRotation : MonoBehaviour
{
    private TopDownCharacterController _controller;

    private void Awake()
    {
        _controller = GetComponent<TopDownCharacterController>();

    }

    void Start()
    {
        _controller.OnLookEvent += OnAim;   
    }

    public void OnAim(Vector2 newAimDirection)
    {
        RotatePlayer(newAimDirection);
    }
    private void RotatePlayer(Vector2 direction)
    {
        float rotZ = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
        gameObject.GetComponentInChildren<SpriteRenderer>().flipX = Mathf.Abs(rotZ) > 90f;
    }

  
}

✔️TopDownMovement

🎇 Managed by 이성권

  • 캐릭터의 이동을 담당합니다.

📜 Code Summary

  • Awake()

    • Rigidbody2D 컴포넌트를 검색합니다.
  • Start(

    • _controller.OnMoveEvent 리스너를 등록합니다.
  • Move()

    • 캐릭터의 이동 방향을 설정하는 메서드입니다.
    • _movementDirection 변수에 캐릭터의 이동 방향을 설정합니다.
  • ApplyMovment()

    • 캐릭터를 이동시키는 메서드입니다.
    • _movementDirection 변수에 따라 캐릭터의 Rigidbody2D 컴포넌트의 velocity 속성을 설정합니다.

💻 Code

TopDownMovement.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TopDownMovement : MonoBehaviour
{
    private TopDownCharacterController _controller;

    private Vector2 _movementDirection = Vector2.zero;
    private Rigidbody2D _rigidbody;

    private void Awake()
    {
        _controller = GetComponent<TopDownCharacterController>();
        _rigidbody = GetComponent<Rigidbody2D>();
    }    

    private void Start()
    {
     
        _controller.OnMoveEvent += Move;
    }

    private void FixedUpdate()
    {
        ApplyMovment(_movementDirection);
    }

    private void Move(Vector2 direction)
    {
        _movementDirection = direction;
    }

    private void ApplyMovment(Vector2 direction)
    {
        direction = direction * 5;

        _rigidbody.velocity = direction;
    }
}

Clone this wiki locally