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.