未発表パーティゲーム PlayerController.cs
msandfrey3
Aug 12, 2024
4 min read
using PartyGame.GameManagement;using LeftTurnStudios.Observables;using UnityEngine;using UnityEngine.InputSystem;using PartyGame.Config;using System.Collections;using PartyGame.Character.Abilities;using PartyGame.PhysicsManagement;using PartyGame.Multiplayer;using PartyGame.Scoring;using Fusion;using PartyGame.Multiplayer.Inputs;using System;using System.Linq;using System.Collections.Generic;using PartyGame.Character.Abilities.Grapple;using PartyGame.Cosmetics;using PartyGame.Props;using DG.Tweening;using PartyGame.CameraManagement;using PartyGame.PhysicsManagement.Collisions;
namespace PartyGame.Character.Player{ [RequireComponent(typeof(PlayerInput))] public class PlayerController : NetworkBehaviour, IGameLoop, IPlayerController { public delegate void PlayerDied(PlayerController playerController);
public PlayerDied OnPlayerDied { get; set; }
[SerializeField] private Rigidbody _rigidbody; [SerializeField] private NetworkRigidbody _networkRigidbody; [SerializeField] private PlayerNumber _playerNumber = PlayerNumber.Unset; [SerializeField] private GrappleTurret _grappleTurret; [SerializeField] private BumperCar _bumperCar; [SerializeField] private SpeedTracker _speedTracker; [SerializeField] private WinnerEffect _winnerEffect;
[SerializeField] private GameObject _stunVisual; [SerializeField] private float _stunDuration = 3.0f; [SerializeField] private float _stunCooldown = 3.0f;
[Header("Abilities")] [SerializeField] private GrappleAbility _grappleAbility;
[Header("Status Effects")] [SerializeField, Tooltip("Set to false to disable stun mechanic")] private bool _enableStunMechanic = true;
[Networked(OnChanged = nameof(OnReadyUpdated))] private NetworkBool _isReady { get; set; }//only used in lobby now
private int _localID; private bool _isStunned; private bool _canStun; private bool _enableCarRotation = false; private bool _areControlsEnabled = true;
private IPhysicsManager _physicsManager; private ScoreManager _scoreManager; private TournamentLobbyManager _lobbyManager; private CollisionManager _collisionManager;
private PlayerInput _playerInput; private PlayerInputHandler _playerInputHandler; private Observable<bool> _isRespawning = new Observable<bool>(false); private Observable<bool> _isActiveInGame = new Observable<bool>(false); private Observable<Color> _playerColor = new Observable<Color>(Color.white);
public event Action<PlayerNumber, bool> OnReady;
public PlayerInput PlayerInput => _playerInput; public Observable<bool> IsRespawning => _isRespawning; public Observable<bool> IsActiveInGame { get => _isActiveInGame; set => _isActiveInGame = value; } public GrappleTurret GrappleTurret => _grappleTurret; public IPhysicsManager PhysicsManager => _physicsManager; public Rigidbody Rigidbody => _rigidbody; public NetworkRigidbody NetworkRigidbody => _networkRigidbody; public GameObject GameObject => gameObject; public Transform Transform => _rigidbody.transform; public bool IsGrappling => _grappleAbility.IsGrappling; public PlayerNumber PlayerNumber => _playerNumber; public ScoreManager ScoreManager => _scoreManager; public Observable<Color> PlayerColor => _playerColor; public Ray AimRay => _grappleAbility.AimRay; public int LocalID { get => _localID; set => _localID = value; } public NetworkBool IsReady => _isReady; public IGrappleTarget GrappleTarget => _grappleAbility.GrappleTarget; public SpeedTracker SpeedTracker => _speedTracker;
private void Awake() { PlayerConfig playerConfig = FindAnyObjectByType<PlayerConfig>(); _physicsManager = GetComponent<PhysicsManager>(); _physicsManager.MaxSpeed = playerConfig.GameSettingsConfig.MaxSpeed;
_playerInput = GetComponent<PlayerInput>(); _scoreManager = GetComponent<ScoreManager>(); _playerInputHandler = GetComponent<PlayerInputHandler>(); _collisionManager = GetComponent<CollisionManager>();
_collisionManager.OnCollisionEnter += HandleCollisionEnter; _collisionManager.OnCollisionStay += HandleCollisionStay; _collisionManager.OnCollisionExit += HandleCollisionExit; }
public override void Spawned() { _isReady = false; _lobbyManager = FindObjectOfType<TournamentLobbyManager>(); // We start with grappling enabled. For the lobby Unstun();
_canStun = _enableStunMechanic; _enableCarRotation = false;
// Set the cosmetics data for the grapple ability PlayerCosmeticsManager playerCosmeticsManager = PlayerCosmeticsManager.Instance; PlayerCosmeticsData playerCosmeticsData = playerCosmeticsManager.GetPlayerCosmeticsData(_playerNumber); _grappleAbility.SetPlayerCosmeticsData(playerCosmeticsData); }
public override void FixedUpdateNetwork() { HandlePlayerInput(); RotateTowardsMovement();
if (Runner.IsResimulation) { return; }
_collisionManager.CheckCollisions(); _grappleAbility.UpdateNetworkData();
_physicsManager.ApplyForces(); }
private void HandlePlayerInput() {
if (GetInput<NetworkPlayerInputs>(out NetworkPlayerInputs networkPlayerInputs)) { NetworkPlayerInput networkPlayerInput = networkPlayerInputs.GetPlayerInput(_playerNumber);
Ray aimRay = networkPlayerInput.GetAimRay(); SetAimRay(aimRay);
// Hack: This is messy but we need to set the aim ray even if controls are disabled so that we rotate the turret correctly if (!_areControlsEnabled) { return; }
// If the grapple button is pressed if (networkPlayerInput.NetworkButtons.IsSet(PlayerButton.GrappleButton)) { if (!_grappleAbility.IsGrappling) { // We use the aim ray from the Grapple Ability instead of the one from the player input // This is because the player input aim ray doesn't take into account // the player position and rotation // The GrappleAbility handles all of this for us StartGrapple(_grappleAbility.AimRay); } } else { if (_grappleAbility.IsGrappling) { StopGrapple(); } } } }
private void RotateTowardsMovement() { if (!_enableCarRotation) { return; }
// Rotate the car towards the direction of travel. if (_rigidbody.velocity.x != 0 || _rigidbody.velocity.z != 0) { // Calculate the target rotation based on the direction of the velocity. Vector3 flattenedVelocity = new Vector3(_rigidbody.velocity.x, 0f, _rigidbody.velocity.z);
Vector3 normalizedVelocity = flattenedVelocity.normalized;
// If we not moving, then don't rotate // Note: if we try to call Quaternion.LookRotation with a zero vector, it will spam the console with useless log messages if (normalizedVelocity == Vector3.zero) { return; }
Quaternion targetRotation = Quaternion.LookRotation(flattenedVelocity.normalized, Vector3.up);
// Smoothly rotate towards the target rotation. float rotationSpeed = 10.0f; _bumperCar.transform.rotation = Quaternion.Slerp(_bumperCar.transform.rotation, targetRotation, rotationSpeed * Time.deltaTime); } }
public void ToggleReady() { RPCSetReady(!_isReady); }
public void ResetReady() { RPCSetReady(false); }
[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.StateAuthority)] private void RPCSetReady(NetworkBool state) { _isReady = state; }
protected static void OnReadyUpdated(Changed<PlayerController> changed) { changed.Behaviour._lobbyManager.ReadyChange(changed.Behaviour.PlayerNumber, changed.Behaviour._isReady); }
public void SpawnAtLocation(Vector3 location, Quaternion rotation) { _rigidbody.transform.position = location; _rigidbody.transform.rotation = rotation; _rigidbody.velocity = Vector3.zero; _rigidbody.angularVelocity = Vector3.zero; }
public void SetAimRay(Ray ray) { _grappleAbility.SetAimRay(ray); }
public void ClearAimRay() { _grappleAbility.ClearAimRay(); }
public void StartGrapple(Ray ray) { if (_isRespawning) { return; }
_grappleAbility.StartGrapple(ray); }
public void StopGrapple() { _grappleAbility.StopGrapple(); }
/// <summary> /// This function takes in a force vector and applies it to the player as a boost /// </summary> /// <param name="boostForce"></param> public void Boost(Vector3 boostForce, ForceMode forceMode = ForceMode.Impulse) { if (!_areControlsEnabled) { return; }
// If the boost is coming from the local player, then we want to send an RPC to the server // to handle the boost if (Object.HasInputAuthority) { _physicsManager.RPCEnqueueForce(boostForce, forceMode); } else if (Object.HasStateAuthority) // we are the host, apply the boost { _physicsManager.EnqueueForce(boostForce, forceMode); } }
public void ScaleMomentum(float amount) { _physicsManager.ScaleMomentum(amount); }
public void StartNewRound() { Unstun(); _scoreManager.StartNewRound(); }
public void GameOver() { FreezeMovement(); _scoreManager.GameOver(); }
public void SetRespawning(bool isRespawning) { _isRespawning.Value = isRespawning;
if (isRespawning) { DisableControls(); } else { EnableControls(); } }
public void Die() { OnPlayerDied?.Invoke(this); }
public void FreezeMovement() { _physicsManager.StopMomentum(); }
public void DisableControls() { _areControlsEnabled = false; _enableCarRotation = false; _scoreManager.DisableScoreKeeping(); _grappleAbility.DisableGrappleAbility(); _grappleAbility.DisableGrappleAbility(); }
public void EnableControls() { _areControlsEnabled = true; _enableCarRotation = true; _isActiveInGame.Value = true; _scoreManager.EnableScoreKeeping(); _grappleAbility.EnableGrappleAbility(); }
[Rpc(sources: RpcSources.All, targets: RpcTargets.All)] public void RPCEnableControls() { EnableControls(); }
public void StoreMinGameScore() { _scoreManager.StoreScore(); }
public void SetAsWinner() { _winnerEffect.PlayEffect();
float duration = 5.0f; float rotationSpeed = 100.0f; float targetRotation = duration * rotationSpeed;
_bumperCar.transform.DORotate(new Vector3(0.0f, targetRotation, 0.0f), duration, RotateMode.FastBeyond360) .SetEase(Ease.Linear); }
public void Stun() { if (_isStunned || !_canStun) { return; } _isStunned = true;
StopGrapple(); _grappleAbility.DisableGrappleAbility(); _stunVisual.SetActive(true); StartCoroutine(UnstunDelay()); }
private IEnumerator UnstunDelay() { yield return new WaitForSeconds(_stunDuration); Unstun(); }
private void Unstun() { _isStunned = false; _grappleAbility.EnableGrappleAbility(); _stunVisual.SetActive(false);
_canStun = false; StartCoroutine(ResetStun()); }
private IEnumerator ResetStun() { yield return new WaitForSeconds(_stunCooldown); _canStun = _enableStunMechanic; }
public void SetPlayerCamera(PlayerCamera playerCamera) { _playerInputHandler.PlayerInputListener.SetPlayerCamera(playerCamera); }
private void HandleCollisionExit(Collider collider, Vector3 collisionPoint) { List<ICollidable> collidables = collider.GetComponents<ICollidable>().ToList(); foreach (ICollidable collidable in collidables) { if (collidable != null) { collidable.CollisionExit(this.gameObject, collisionPoint); } } }
private void HandleCollisionStay(Collider collider, Vector3 collisionPoint) { List<ICollidable> collidables = collider.GetComponents<ICollidable>().ToList(); foreach (ICollidable collidable in collidables) { if (collidable != null) { collidable.CollisionStay(this.gameObject, collisionPoint); } } }
private void HandleCollisionEnter(Collider collider, Vector3 collisionPoint) { List<ICollidable> collidables = collider.GetComponents<ICollidable>().ToList(); foreach (ICollidable collidable in collidables) { if (collidable != null) { collidable.CollisionEnter(this.gameObject, collisionPoint); } } }
public void MiniGameCompleted() { _collisionManager.ClearCollisionTracking(); } }}
Comments