[Unity] 1인칭 FPS 게임 - 2. Living Entity-1

홍예주·2021년 7월 7일
0
  • 실습용으로 작성한 코드이기 때문에 정리가 안되어 있습니다. 따라서 필요 없는 부분이나 미흡한 부분이 있을 수 있습니다.

1. Living Entity

  • 체력, 생존, 사망 상태를 가진 객체를 만들기 위한 상위 객체
using System.Collections;
using UnityEngine;

public class LivingEntity : MonoBehaviour, IDamageble
{

    public float startingHealth;

    protected float health;
    public bool dead;


    public event System.Action OnDeath;

    protected virtual void Start()
    {
        health = startingHealth;
        dead = false;
    }

    //HP에 데미지
    public void TakeHit(float damage)
    {
        health = health - damage;
        Debug.Log("Take hit");
        Debug.Log(health);
        if (health <= 0 && !dead)
        {
            Die();
        }
    }

//사망시 이벤트 구독하도록 -> 실제 구현에서 못썼음
    protected virtual void Die()
    {
        dead = true;
        health = startingHealth;
        if (OnDeath != null)
        {
            OnDeath();
        }

        //Destroy(this.gameObject);
    }

//체력 확인 위해
    public float getHealth()
    {
        return health;
    }

//체력 세팅
    public void setHealth(float _health)
    {
        health = _health;
    }
}

2. IDamageble

  • 해당 인터페이스를 상속받아 데미지 받는 기능을 구현
using UnityEngine;

public interface IDamageble {

    //damage : 받는 데미지량, hit : 충돌 지점
    void TakeHit(float damage);
}

3. Player

  • 플레이어의 조작을 담당
  • 플레이어 이동, 회전, 총 발사, 달리기 처리
  • 스테이지 통과 판정도 여기서 처리
  • Living Entity를 상속받음

1) Unity Object

매 레벨마다 Instantiate로 생성하기 위해 prefab으로 생성

  • 1인칭 시점이기 때문에 플레이어 모델링은 하지 않음
  • 플레이어의 시야와 맞추기 위해 Camera와 Light를 플레이어 자식으로
  • 플레이어 주변 시야만 밝히기 위해 Point Light 사용(사진 속 Directional Light - 이름 바꾸는걸 까먹음)

2) C# Code

using UnityEngine.UI;
using UnityEngine;


[RequireComponent (typeof(GunController))]
public class Player : LivingEntity
{
	//플레이어 세팅값
    public float speed;
    public float mouseSensitivity;
    
    float tmpSpeed;

    //총구 fire 파티클
    public ParticleSystem muzzleFlash;


    Rigidbody rid;
    
    //총기 컨트롤
    GunController gunController;

    public GameManager gameManager;

    protected override void Start()
    {
        //Living Entity의 start를 상속받음
        base.Start();
        dead = false;

        Debug.Log(health);
        rid = GetComponent<Rigidbody>();
        //gameManager = GameObject.Find("GameManager");

        //MainCamera = GameObject.Find("Main Camera").GetComponent<Camera>();
        gunController = GetComponent<GunController>();

        tmpSpeed = speed;
    }

    void Update()
    {
        PlayerMove();
        PlayerRotation();

        //Weapon Input

        //왼쪽 클릭시 총알 발사
        if (Input.GetMouseButton(0))
        {
            muzzleFlash.Play();
            gunController.Shoot();
        }

        //달리기
        if (Input.GetKeyDown(KeyCode.LeftShift))
        {
            speed = speed + 1f;
        }

        if (Input.GetKeyUp(KeyCode.LeftShift))
        {
            speed = tmpSpeed;
        }

        
    }


    private void PlayerMove()
    {
        float moveX = Input.GetAxis("Horizontal");
        float moveZ = Input.GetAxis("Vertical");

        Vector3 moveHorizontal = transform.right * moveX;
        Vector3 moveVertical = transform.forward * moveZ;

        Vector3 velocity = (moveHorizontal + moveVertical).normalized * speed;

        rid.MovePosition(transform.position + velocity * Time.deltaTime);
    }

    private void SpeedUp()
    {
        if (Input.GetKey(KeyCode.LeftShift))
        {
            speed = speed + 1;
        }
    }

    private void PlayerRotation()
    {
        float rotationV = Input.GetAxis("Mouse X");
        Vector3 playerRotationV = new Vector3(0f, rotationV, 0f) * mouseSensitivity;
        rid.MoveRotation(rid.rotation * Quaternion.Euler(playerRotationV));

    }

    //레벨 클리어 판정
    public void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Clear"))
        {
            Debug.Log("Clear stage");
            gameManager.NextLevel();
        }
    }
    


    protected override void Die()
    {
        dead = true;
        Debug.Log("Player Dead");
        //gameManager.GetComponent<GameManager>().EndGame();
        gameManager.EndGame();
    }




}

4. 발생했던 문제점

1) Player, Enemy를 모두 Prefab으로 생성 -> 객체끼리 인식 못하는 문제 발생

특히 Player의 체력을 Enemy 쪽에서 알아야 하는데 이걸 자꾸 인식을 못해서 애먹었다.

처음에는

IDamageble damagebleObject = player.GetComponent();

로 선언해서 player의 takehit을 호출했는데, 현재 씬에 불려온 플레이어 프리팹의 체력이 깎이지 않아서 플레이어 객체에서 바로 함수를 호출했다.

2) 카메라 회전과 플레이어 회전 일치

원래는 플레이어에 카메라 컨트롤 하는 부분을 붙여뒀는데 코드의 관리를 위해 분리 했다.

  using UnityEngine;

public class CameraController : MonoBehaviour
{

    public float mouseSensitivity;
    public float currRotationX = 0;
    public float rotationLimit;

    Camera MainCamera;

    private void Start()
    {
        MainCamera = GameObject.Find("Main Camera").GetComponent<Camera>();
    }

    private void Update()
    {
        CameraRotation();
    }

    private void CameraRotation()
    {
        if(Time.deltaTime == 0)
        {
            return;
        }
        float rotationX = Input.GetAxis("Mouse Y");

        float cameraRotationX = rotationX * mouseSensitivity;

        currRotationX -= cameraRotationX;
        currRotationX = Mathf.Clamp(currRotationX, -rotationLimit, rotationLimit);

        MainCamera.transform.localEulerAngles = new Vector3(currRotationX, 0f, 0f);
    }
}
profile
기록용.

0개의 댓글