일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 유니티 해상도 변경
- 오브젝트 깜빡임
- unity git
- 유니티 머지
- m585
- NavMesh
- networkbehaviourid
- unity 병합
- 몬스터
- 유니티 해상도
- 유니티 브랜치 merge
- Unity
- unity merge
- stateauthority
- m590 수리
- nav거리
- nav오브젝트사이거리
- 깃허브 데스크탑 합치기
- m585 수리
- networkobject.networkid
- M590
- 유니티 해상도 설정
- networkobject
- Github DeskTop Merge
- 깃허브 데스크탑 병합
- navigation
- 유니티 합치기
- 유니티
- githubdesktopmerge
- Today
- Total
집게사장의 꿈
[뜯어보기] Asteroids.SharedSimple 본문
[Version 2.0.0]
https://doc.photonengine.com/fusion/current/game-samples/fusion-asteroids
! Player
PlayerDataNetworked.cs
플레이어의 모든 정보를 가지고 있으며, 모든 클라이언트에 정보가 복제되는 것을 보장한다.
스폰과 디스폰 시 정보 초기화도 진행한다.
- Score
- Lives
- NickName
각 정보를 가지고 있으며, 변경 사항을 받는다.
모든 플레이어가 OverView에 참조되며, 각 정보에 대해 변경될 업데이트 된다.
LocalInputPoller.cs
INetworkRunnerCallbacks을 상속받아 OnInput을 통해 입력에 대한 값을 지정한다.
LocalPlayerData.cs
플레이어 데이터 중 닉네임에 대한 설정
Struct SpaceshipInput
플레이어 입력에 대한 정보
SpaceshipController.cs
- 우주선에 대한 생명주기 동안 조작하며
- NetworkBehaviour에서 기본적으로 제공되는 기능을 사용하는 FusionPlayer에서 파생된 컨트롤러
- 플레이어의 관리와 틱정렬 시스템
주요기능
1. 행성과의 충돌 판정
2. 네트워크 인터페이스를 통한 이동 판정
3. Fixed, Simulation, Render를 통한 우주선 업데이트
4. 이동, 죽음 효과
5. 스폰, 총알 발사 등 TickTimer의 사용
//스폰될 경우
public override void Spawned()
{
_playerDataNetworked = GetComponent<PlayerDataNetworked>();
// 모델의 컬러를 현재 클라이언트의 번호에 따라 부여한다.
var playerRef = Object.InputAuthority;
_spaceshipModel.material.color = GetColor(playerRef.PlayerId);
// Grab a change detector for this NB so we can detect when a life is lost and play an appropriate effect
// 플레이어가 생명을 잃거나 충분한 효과가 생겼을 경우 감지가능하다.
//Simulation으로부터 가져오는 것
_changeDetector = GetChangeDetector(ChangeDetector.Source.SimulationState);
// We're controlling the ship using forces, so grab the rigidbody
_rigidbody = GetComponent<Rigidbody>();
//현재 객체에 대한 권한이 있는 경우 실행
if (HasStateAuthority)
{
IsAlive = true;
}
}
//네트워크 상 모든 시뮬레이션이 끝나고, Fusion이 물리는 사용하고 있는 경우 유니티 Update에서 사용
public override void Render()
{
// Adjust the engine effect based on acceleration
ParticleSystem.EmissionModule e = _engineTrailVFX.emission;
e.rateOverTimeMultiplier = Mathf.Abs(Acceleration);
var main = _engineTrailVFX.main;
main.startSpeedMultiplier = -0.2f * Acceleration;
// Check if there were any changes to our network state and handle changes in our alive state
foreach (var change in _changeDetector.DetectChanges(this, out var prev, out var current))
{
switch (change)
{
//변경된 값이 IsAlive라면?
case nameof(IsAlive):
{
// Get a property reader and read the previous and current values of the changed property
//네트워크 Reader로부터 변경된 값을 가져와 이전값과 다음값을 읽는다.
(var wasAlive, var isAlive) = GetPropertyReader<NetworkBool>(change).Read(prev, current);
ToggleVisuals(wasAlive, isAlive);
break;
}
}
}
}
//파괴와 생성을 확인한다.
private void ToggleVisuals(bool wasAlive, bool isAlive)
{
// Check if the spaceship was just brought to life
//막 살아난 경우
if (isAlive && !wasAlive)
{
_spaceshipModel.enabled = true;
_engineTrailVFX.Play();
_destructionVFX.Stop();
}
// 막 죽은 경우
else if (wasAlive && !isAlive)
{
_spaceshipModel.enabled = false;
_engineTrailVFX.Stop();
_destructionVFX.Play();
}
}
//플레이어 숫자에 따른 색 변경
public static Color GetColor(int player)
{
switch (player % 8)
{
case 0: return Color.red;
case 1: return Color.green;
case 2: return Color.blue;
case 3: return Color.yellow;
case 4: return Color.cyan;
case 5: return Color.grey;
case 6: return Color.magenta;
case 7: return Color.white;
}
return Color.black;
}
//네트워크 상에서의 업데이트
public override void FixedUpdateNetwork()
{
var gamestate = GameController.Singleton;
//게임 동작 중인 경우
if (!gamestate.GameIsRunning)
return;
// Checks if the spaceship is ready to be respawned.
//우주선이 스폰 준비가 된 경우
if (RespawnTimer.Expired(Runner))
{
IsAlive = true;
RespawnTimer = default;
}
// Checks if the spaceship got hit by an asteroid
//우주선이 행성에 강타 당한 경우
if (IsAlive && HasHitAsteroid())
{
ShipWasHit();
}
// Handle input if we have StateAuthority over the object (GetInput returns false otherwise)
//GetInput은 현재 객체가 StateAuthority인 경우 반환된다.
//아닌 경우 false가 반환된다.
if (AcceptInput && GetInput<SpaceshipInput>(out var input)) //SpaceshipInput입력 -> NetworkInput 변환 등록 -> SpaceshipInput 변환 반환
{
Move(input);
Fire(input);
}
// Keep spaceship on screen
//우주선이 현재 바탕 화면에 존재하는지 판단
CheckExitScreen(gamestate);
}
//행성에 타격 당한 경우
private bool HasHitAsteroid()
{
//네트워크 상 충돌 객체
var count = Runner.GetPhysicsScene().OverlapSphere(_rigidbody.position, _spaceshipDamageRadius, _hits,
_asteroidCollisionLayer.value, QueryTriggerInteraction.UseGlobal);
if (count <= 0)
return false;
var asteroidBehaviour = _hits[0].GetComponent<AsteroidBehaviour>();
return asteroidBehaviour.OnAsteroidHit();
}
// Toggle the IsAlive boolean if the spaceship was hit and check whether the player has any lives left.
// If they do, then the RespawnTimer is activated.
//남은 생명이 있는경우 충돌 판정과 충돌 된 경우 리스폰을 판단
private void ShipWasHit()
{
if (!HasStateAuthority) return;
_rigidbody.velocity = Vector3.zero;
_rigidbody.angularVelocity = Vector3.zero;
IsAlive = false;
//타이머 발동
if (_playerDataNetworked.Lives > 1)
RespawnTimer = TickTimer.CreateFromSeconds(Runner, _respawnDelay);
else
RespawnTimer = default;
//보여지는 라이프를 감소
_playerDataNetworked.SubtractLife();
}
// Moves the spaceship RB using the input for the client with InputAuthority over the object
//InputAuthority가 포함된 클라이언트 입력을 사용
private void Move(SpaceshipInput input)
{
Transform xform = transform;
//up 방향에 회전가속도 더하기
_rigidbody.AddRelativeTorque(
Mathf.Clamp(input.HorizontalInput, -1, 1) * _rotationSpeed * Runner.DeltaTime * xform.up,
ForceMode.VelocityChange);
//선형 가속도
Acceleration = Mathf.Clamp(input.VerticalInput, -1, 1) * _acceleration * Runner.DeltaTime;
//가속
Vector3 force = xform.forward * Acceleration;
_rigidbody.AddForce(force);
//최고속도를 초과한 경우 최고값으로 지정
if (_rigidbody.velocity.magnitude > _maxSpeed)
_rigidbody.velocity = _rigidbody.velocity.normalized * _maxSpeed;
}
// Moves the ship to the opposite side of the screen if it exits the screen boundaries.
// 가장자리에 우주선이 위치한 경우 반대 편으로 이동
private void CheckExitScreen(GameController ctrl)
{
var position = _rigidbody.position;
if (Mathf.Abs(position.x) < ctrl.ScreenBoundaryX && Mathf.Abs(position.z) < ctrl.ScreenBoundaryY) return;
if (Mathf.Abs(position.x) > ctrl.ScreenBoundaryX)
position = new Vector3(-Mathf.Sign(position.x) * ctrl.ScreenBoundaryX, 0, position.z);
if (Mathf.Abs(position.z) > ctrl.ScreenBoundaryY)
position = new Vector3(position.x, 0, -Mathf.Sign(position.z) * ctrl.ScreenBoundaryY);
//가장자리에서 이동하는 것을 방지
position -= position.normalized *
0.1f; // offset a little bit to avoid looping back & forth between the 2 edges
//네트워크 객체를 텔레포트
//런시뮬레이션 이전에 FixedNetwork에서 호출할 수 있다.
GetComponent<NetworkRigidbody3D>().Teleport(position);
}
// Checks the Buttons in the input struct against their previous state to check
// if the fire button was just pressed.
// 구조체를 통해 버튼의 입력을 비교하여 눌렀는지 판단
private void Fire(SpaceshipInput input)
{
//버튼을 누른 경우 발사
if (input.Buttons.WasPressed(ButtonsPrevious, SpaceshipButtons.Fire))
SpawnBullet();
ButtonsPrevious = input.Buttons;
}
// Spawns a bullet which will be travelling in the direction the spaceship is facing
//우주선이 바라보는 방향으로 이동하는 총알을 생성
private void SpawnBullet()
{
if (_shootCooldown.ExpiredOrNotRunning(Runner) == false) return;
Runner.Spawn(_bullet, _rigidbody.position, _rigidbody.rotation, Object.InputAuthority);
_shootCooldown = TickTimer.CreateFromSeconds(Runner, _delayBetweenShots);
}
! Server
OnServerDisconnected.cs
INetworkRunnerCallbacks를 통해 서버가 닫힐 경우 씬을 불러온다,
! UI
StartMenu.cs
1. 타이틀에서 네트워크 시작을 위한 Runner 생성과 방 번호를 통해 네트워크에 연결된다.
- 닉네임
- 방이름
- 네트워크 러너 프리팹을 통한 생성
PlayerOverviewPanel.cs
1. 현재 씬에 생성된 모든 플레이어 에 대한 모든 객체에 대한 정보를 업데이트 한다.
2. PlayerDataNetworked.cs 를 Dictionary 형태로 참조하여 값을 업데이트 한다.
새로 생성되는 Text 정보는 Grid Layout Group를 통해 정렬한다.
행성
AsteroidSpawner.cs
- 큰 행성에 대한 생성
- 네트워크 소유 주체가 바뀌면 다시 생성
AsteroidBehaviour.cs
- 행성에 대한 움직임과 생성 파괴에 대한 값이 들어가 있음
- 행성의 파괴는 Host가 아니어도 RPC를 통한 통신을 통해 다른 클라이언트들과의 소통이 이루어짐
GameController.cs
- 게임 진행 시 3가지 상태에 따라 업데이트 한다.
- 플레이어가 Master일 경우에만 행성의 생성과 게임의 종료를 판단한다.
- 플레이어들이 생성될 경우 고유 ID가 등록된다.
어떻게 마스터 클라이언트를 판단하는 것일까?
'유니티 > Fusion' 카테고리의 다른 글
flag |= NetworkObjectFlags.MasterClientObject; (0) | 2024.06.18 |
---|---|
Fusion 기본 정보 (1) | 2024.06.06 |
photon fusion tutorial #3 (1) | 2024.06.04 |
Photon Fusion Tutorial #2 (0) | 2024.06.04 |
Fusion Shared Tutorial #1 (0) | 2024.06.04 |