카테고리 없음

0716 포톤(좀비 서바이벌)

버스창문 2025. 7. 16. 18:00

Animator를 photon view에 할당

 

Photon ~~~ View 

-> 로컬에선, 그 움직임을 관측하고 다른 클라이언트에 전달

    리모트에선, 전달받은 움직임을 받아 자신의 ~~~ 에 값을 덮어씀

각 레이어 마다 설정하는 내용

 

Continuous : 애니메이션 연동을 안끊기게 쭉

Discrete : 살짝 끊기게

Disabled : 안함

 

애니메이션에 들어있는 Parameter마다 설정하는 내용

위와 같음

 

public class CameraSetUp : MonoBehaviourPun
{
    private void Start()
    {
        if (photonView.IsMine)
        {
            CinemachineVirtualCamera vc = FindObjectOfType<CinemachineVirtualCamera>();
            if (vc != null)
            {
                vc.Follow = this.transform; // 카메라가 플레이어를 따라가도록 설정
                vc.LookAt = this.transform; // 카메라가 플레이어를 바라보도록 설정
            }
        }
    }
}

태어났을때 카메라를 붙이는 로직

게임매니저쪽에 넣기엔 캐릭터가 태어났는지를 체크하기 애매해서 캐릭터쪽에 넣는게 낫다

 

WomanShooter : MonoBehaviourPun


    void Update()
    {
        if (!photonView.IsMine) return; // 로컬 플레이어가 아닐 경우 사격 X
        
        
 캐릭터 움직이는 내용들(input받거나, 총쏘거나, 움직이거나) 들에 전부 저렇게 추가
    private void CreatePlayer()
    {
        PhotonNetwork.Instantiate(
            "Woman",  //Resources 폴더 안에 있는, 생성할 프리팹 이름
            new Vector3(0, 3f, 0), //생성할 좌표
            Quaternion.identity,  // 회전값
            0, 
            null);
    }

 

 

LivingEntity코드


[PunRPC]
    public virtual void OnDamage(int damage, Vector3 hitPoint, Vector3 hitNormal)
    {
        //체력 있어야함
        //체력이 0이 됐을때 Action 실행
        if (PhotonNetwork.IsMasterClient)
        {
            this.hp -= damage; // 데미지 적용
            photonView.RPC("ApplyUpdatedHealth", RpcTarget.Others, this.hp, this.isDead); // 다른 클라이언트에게 체력 업데이트 전송
            photonView.RPC("OnDamage", RpcTarget.Others, damage, hitPoint, hitNormal); // Die 실행 시키려고 넣은거같은데 Die만 따로 되어있는거보면
                                                                                       // 체력 업데이트는 마스터쪽에서 다 같이 적용될거고 OnDamage를
                                                                                       // 다른 클라이언트에서 실행 시키면, Master if문은 안들어가고 아래
                                                                                       // Die쪽만 들어갈거니까
        }

        
        if(this.hp <= 0&&!this.isDead)//아직 죽지 않은 상태에서 체력이 0 이하가 되었을때
        {
            Die();
        }
    }
LivingEntity를 상속받은 PlayerHealth 코드


[PunRPC]
    public override void OnDamage(int damage, Vector3 hitPoint, Vector3 hitNormal)
    {
        if (this.isDead) return; // 이미 죽은 상태라면 데미지 처리하지 않음
        this.audioSource.PlayOneShot(this.damageClip); // 데미지 받는 소리 재생
        base.OnDamage(damage, hitPoint, hitNormal);
        // 추가적인 데미지 처리 로직이 필요하다면 여기에 작성
        this.healthSlider.value = this.hp; // 체력 슬라이더 업데이트

    }

위에 상속하는 쪽에서 이미 [PunRPC]가 되어있지만,

상속받는쪽에서도 [PunRPC]를 해야한다.

 

 

 

    private void CreateZombie()
    {
        
        ZombieData data = zombieDatas[UnityEngine.Random.Range(0, zombieDatas.Length)]; // 랜덤으로 좀비 데이터 선택
        Transform spawnPoint = spawnPoints[UnityEngine.Random.Range(0, spawnPoints.Length)]; // 랜덤으로 생성 위치 선택

        for(int i = 0; i<this.zombiePool.Count; i++)
        {
            if (!zombiePool[i].gameObject.activeSelf)
            {
                zombiePool[i].transform.position = spawnPoint.position; // 생성 위치로 이동
                //zombiePool[i].Setup(data); // 좀비 데이터 설정 , 싱글 게임 기준
                //멀티 게임 기준
                zombiePool[i].photonView.RPC("Setup", RpcTarget.All, data.hp,data.damage,data.moveSpeed,data.skinColor); // RPC를 통해 좀비 데이터 설정
                this.zombies.Add(zombiePool[i]); // 생성된 좀비 목록에 추가
                zombiePool[i].gameObject.SetActive(true); // 비활성화된 좀비가 있다면 활성화
                
                return;
            }
        }
        //여기로 왔으면 모든게 활성화 되어있거나, 생성된게 없거나
        #region 싱글 게임 기준, 좀비 오브젝트 풀링
        /*Zombie zombie = Instantiate(zombiePrefab, spawnPoint.position, Quaternion.identity).GetComponent<Zombie>(); // 좀비 생성
        zombie.Setup(data); // 좀비 데이터 설정*/
        #endregion
        #region 멀티 게임 기준, 좀비 오브젝트 풀링
        Zombie zombie = PhotonNetwork.Instantiate(
            zombiePrefab.name, // 좀비 프리팹 이름
            spawnPoint.position, // 생성 위치
            Quaternion.identity // 회전값
        ).GetComponent<Zombie>(); // Zombie 컴포넌트 가져오기
        zombie.photonView.RPC("Setup", RpcTarget.All, data.hp, data.damage, data.moveSpeed, data.skinColor); // RPC를 통해 좀비 데이터 설정

        #endregion
        zombie.DieAction += () =>
        {
            this.zombies.Remove(zombie); // 좀비가 죽으면 목록에서 제거
                                         //목록에서만 제거


            UpdateUI(); // UI 업데이트
            GameManager.Instance.AddScore(100); // 점수 업데이트
        };
        this.zombiePool.Add(zombie); // 생성된 좀비 풀링에 추가
        this.zombies.Add(zombie); // 생성된 좀비 목록에 추가

    }

단, 마스터에서 생성을 전담하고있기때문에, 

마스터가 아닌애들은 DieAction이 할당이 안되서 에러가 나는 문제가 있다

 

 

아이템 스폰

    private void Spawn()
    {
        Vector3 spawnPos = GetRandomPointOnNavMesh(this.playerTr.position, this.maxDistance);
        spawnPos += Vector3.up * 0.5f; // 아이템이 땅에 닿도록 약간 위로 이동

        var itemSelected = items[Random.Range(0, items.Length)]; // 아이템 목록에서 랜덤으로 선택

        #region 싱글 게임일때 아이템 생성
        /*GameObject item = Instantiate(itemSelected, spawnPos, Quaternion.identity); // 아이템 생성

        Destroy(item, 5f); // 5초 후 아이템 제거*/
        #endregion
        #region 멀티 게임일때 아이템 생성
        var item = PhotonNetwork.Instantiate(
            itemSelected.name, // 아이템 이름
            spawnPos, // 생성 위치
            Quaternion.identity// 회전값
        );

        StartCoroutine(DestroyAfter(item, 5f)); // 5초 후 아이템 제거 코루틴 시작
        #endregion

    }
    IEnumerator DestroyAfter(GameObject target, float time)
    {
        yield return new WaitForSeconds(time); // 지정된 시간 대기
        if (target != null)
            PhotonNetwork.Destroy(target); // PhotonNetwork를 통해 아이템 제거
    }

시간 지난뒤 생성했던 아이템을 없애는건데,

아이템을 이미 먹어서 없어져있는 상태에서 없애려고 하면 에러가 나는 문제가 있어서, 유효성 검사를 추가했다

 

 

 

_______________________________________________________________________

 

 

URP

Universal Render Pipeline : 범용으로 사용 가능한 랜더러 파이프 라인으로 고품질의 랜더링을 제공한다.

거의 모든 플랫폼에 적용 가능, 포스트 프로세싱 기능과 통합되어 다양한 후처리 그래픽 효과 처리 가능

 

 

 

이렇게 2개 생김

URP가 적용이 안되어있어서

material이 missing상태가 아닌데도 깨져있음

Graphics에 비어있는거에 아까 생성한 AngryBot Render 할당

 

 

카메라 생긴것도 달라져있음

 

 

Volume 생성

Volume에 profile이 원래 비어있으니, new로 새로 생성

 

Add Override를 이용해서 

Bloom

Vignette 추가

 

 

뭐 이리저리 하고싶은대로 셋팅

이걸 게임 화면에 적용하려면, Camera에서 Rendering쪽에 있는 Post Processing을 체크해야함

 

 

체크 안한거

 

Generate Lightmap UV 체크해야 라이트매핑이 된다

 

라이트 매핑

Volume에 Tonemapping 추가

Neutral : 중립적인 톤 유지

ACES : 톤 매핑을 조명 밝기를 HDR(high dynamic Range) 에서, 사람이 인식할 수 있는 범위로 조정하는 효과를 말하며

Bloom효과와 같이 사용할 경우 더욱 더 좋은 이미지 품질을 낼 수 있다.