Unity

[유니티] 포톤게임 만들기 3

Skull Crusher 2021. 6. 8. 10:50
728x90

1. 이펙트 추가

PhotonPlayer -> BloodSplatter 추가

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

using UnityEngine.UI;

public class SoldierHealth : Photon.MonoBehaviour
{
    // 피격 파티클 시스템
    [SerializeField] private ParticleSystem hitParticleSys;

    [SerializeField] private Animator animator;

    [SerializeField] private SoldierStat stat;

    [SerializeField] private Image hpProgress;
    [SerializeField] private int hp;

    public int Hp
    {
        get { return hp; }
        set
        {
            isDie = (value <= 0) ? true : false; //사망 여부 판단
            hp = value; //체력값 설정
            hpProgress.fillAmount = hp * 0.01f;
        }
    }

    //캐릭터 사망 여부
    private bool isDie = false;

    //총알 피격 처리
    private void OnTriggerEnter(Collider collision)
    {
        if (collision.tag == "Bullet")
        {

            //PhotonNetwork.isMasterClient : 현재 클라이언트 방장인지 여부

            //피격 이펙트 재생
            hitParticleSys.Play();

            //현재 클라이언트가 방장이라면
            if (PhotonNetwork.isMasterClient)
            {
                //이미 사망한 상태면 피격 처리 안함
                if (isDie) return;                            

                //체력 감소
                HpDown(30);
                
            }
            
        }
    }

    public void HpDown(int damage)
    {
        Hp = Hp - damage;

    }

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

    // Update is called once per frame
    void Update()
    {
        
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SoldierShot : Photon.MonoBehaviour
{
    [SerializeField] private float shotDelayTime; // 발포 지연 시간

    [SerializeField] private GameObject bulletPrefab; // 총알 프리팹

    [SerializeField] private Transform shotPos; // 발포 위치

    [SerializeField] private float shotPower; // 발포 힘

    private float time;

    // Update is called once per frame
    void Update()
    {
        // 현재 캐릭터가 현재 클라이언트(유저)의 소유일 경우 총알을 발포함
        if (photonView.isMine)
        {
            time += Time.deltaTime;

            // 왼쪽 마우스 버큰 클릭 시 && 발포 제한 시간간격이 넘으면
            if (Input.GetButtonDown("Fire1") && time >= shotDelayTime)
            {
                photonView.RPC("Fire", PhotonTargets.AllViaServer, shotPos.position, shotPos.forward, transform.rotation);

                // 발포 메소드 실행
                // Fire(shotPos.position, shotPos.forward, transform.rotation);

                time = 0;
            }
        }
    }


    // 발포 메소드

    // 아래 메소드는 포톤 RPC 메소드임을 설정
    // (전제 : 같은 PhtonView 컴포넌트에 대해서만 호출이 가능함)
    [PunRPC] 
    public void Fire(Vector3 pos, Vector3 direction, Quaternion qt)
    {
        GameObject bullet = Instantiate(bulletPrefab, pos, qt);
        bullet.GetComponent<Rigidbody>().velocity = direction * shotPower;

        Destroy(bullet, 1f);
    }
}

 

2. 팀별 피격

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

using UnityEngine.UI;

public class SoldierHealth : Photon.MonoBehaviour
{
    // 피격 파티클 시스템
    [SerializeField] private ParticleSystem hitParticleSys;

    [SerializeField] private Animator animator;

    [SerializeField] private SoldierStat stat;

    [SerializeField] private Image hpProgress;
    [SerializeField] private int hp;

    public int Hp
    {
        get { return hp; }
        set
        {
            isDie = (value <= 0) ? true : false; //사망 여부 판단
            hp = value; //체력값 설정
            hpProgress.fillAmount = hp * 0.01f;
        }
    }

    //캐릭터 사망 여부
    private bool isDie = false;

    //총알 피격 처리
    private void OnTriggerEnter(Collider collision)
    {
        if (collision.tag == "Bullet")
        {

            //PhotonNetwork.isMasterClient : 현재 클라이언트 방장인지 여부
                        
            //현재 클라이언트가 방장이라면
            if (PhotonNetwork.isMasterClient)
            {
                //이미 사망한 상태면 피격 처리 안함
                if (isDie) return;

                BulletInfo binfo = collision.GetComponent<BulletInfo>();                             

                //총알을 쏜 유저의 팀과 현재 피격된 캐릭터 소유자의 팀이 일치하면
                if (photonView.owner.GetTeam() == binfo.team)
                {
                    //총알 파괴
                    Destroy(collision.gameObject);

                    photonView.RPC("TeamHit", PhotonTargets.AllViaServer);

                    return;
                }

                //RPC를 이용한 피격 동기화 (총알쏜유저포톤뷰아이디, 총알쏜유저의 팀)
                photonView.RPC("Hit",
                    PhotonTargets.AllViaServer, 30, binfo.shotPlayerPvId, binfo.team);
                
            }

            //총알 파괴
            Destroy(collision.gameObject);
        }
    }

    [PunRPC]
    public void TeamHit()
    {
        hitParticleSys.Play();
    }

    [PunRPC]
    public void Hit(int damage, int shotPlayerPvId)
    {
        hitParticleSys.Play();

        Hp = Hp - damage;

        if (hp <= 0)
        {
            animator.SetInteger("Stage", (int)SoldierStat.STATE.DIE);
        }
    }

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

    // Update is called once per frame
    void Update()
    {
        
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BulletInfo : MonoBehaviour
{
    public int shotPlayerPvId; //총알을 발포한 유저의 포톤뷰 아이디

    public PunTeams.Team team; //포톤 팀 정보

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

public class SoldierMovement : Photon.MonoBehaviour
{
    [SerializeField] private CharacterController cController; // 캐릭터 컨트롤러

    [SerializeField] private float speed; // 이동 속도

    [SerializeField] private Animator animator; // 애니메이터

    [SerializeField] private SoldierHealth health; //체력 관리

    // Update is called once per frame
    void Update()
    {
        // PhotonView 컴포넌트의 Controllered locally가 true면 photonView.isMine도 true임
        // * isMine true라는건 현재 이 캐릭터가 이 클라이언트 소유라는 것
        if (photonView.isMine && !health.isDie) // 현재 캐릭터가 현재 유저의 것이라면
        {
            // 입력에 의한 이동과 회전을 수행함
            Move();
            Turn();
        }
    }

    void Move()
    {
        float h = Input.GetAxisRaw("Horizontal");
        float v = Input.GetAxisRaw("Vertical");

        Vector3 direction = new Vector3(h, 0f, v).normalized;

        // 이동 입력값에 따라 애니메이션의 상태를 설정함
        animator.SetInteger("State", 
            (direction == Vector3.zero) ? (int)SoldierStat.STATE.IDLE : (int)SoldierStat.STATE.RUN);

        if (direction != Vector3.zero)
        {
            direction *= speed;

            cController.SimpleMove(direction);
        }
    }

    void Turn()
    {
        // 마우스 포인트 기준의 카메라 레이 생성
        Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);

        RaycastHit floorHit;

        // Floor 레이어와의 Raycast 충돌을 판정함
        if (Physics.Raycast(camRay, out floorHit, 100f, 1 << LayerMask.NameToLayer("Floor")))
        {
            Vector3 playerToMouse = floorHit.point - transform.position; // 캐릭터의 시선방향을 구함
            playerToMouse.y = 0f;

            Quaternion rot = Quaternion.LookRotation(playerToMouse); // 시선방향 벡터를 향한 회전
            transform.rotation = rot;
        }
    }
}

3.

 

4.

 

5.