Fixed an issue with calculating the normal on a box HitShape.

This commit is contained in:
Karrar
2024-10-08 15:36:58 +03:00
parent d6e0bc5597
commit 01d6efd4b4
23 changed files with 233 additions and 249 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

8
Samples.meta Normal file
View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7cb3eab0a0c224643b75b94f77430909
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -284,6 +284,11 @@ MonoBehaviour:
AutoConnect: 0 AutoConnect: 0
Port: 36728 Port: 36728
ServerIPAddress: 127.0.0.1 ServerIPAddress: 127.0.0.1
Cap: 1
FPS: 450
ShowDisconnectButton: 1
ShowConnectButton: 1
Offset: {x: 36, y: 0}
--- !u!1 &2037625649 --- !u!1 &2037625649
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -7195,7 +7200,7 @@ MeshFilter:
SceneRoots: SceneRoots:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_Roots: m_Roots:
- {fileID: 1809360484}
- {fileID: 2037625652} - {fileID: 2037625652}
- {fileID: 1070948398} - {fileID: 1070948398}
- {fileID: 1809360484}
- {fileID: 3762179930698311635} - {fileID: 3762179930698311635}

View File

@@ -6,7 +6,7 @@ namespace Netick.Samples.Bomberman
{ {
public class Block : NetworkBehaviour public class Block : NetworkBehaviour
{ {
// Networked properties // Networked Properties
[Networked] [Networked]
public NetworkBool Visible { get; set; } = true; public NetworkBool Visible { get; set; } = true;

View File

@@ -7,32 +7,29 @@ namespace Netick.Samples.Bomberman
public class Bomb : NetworkBehaviour public class Bomb : NetworkBehaviour
{ {
public GameObject ExplosionPrefab; public GameObject ExplosionPrefab;
public BombermanController Bomber; public BombermanController Bomber;
public float ExplosionDelay = 3.0f; public float ExplosionDelay = 3.0f;
private readonly Vector3[] _directionsAroundBomb = new Vector3[4] { Vector3.right, Vector3.left, Vector3.up, Vector3.down }; private readonly Vector3[] _directionsAroundBomb = new Vector3[4] { Vector3.right, Vector3.left, Vector3.up, Vector3.down };
private static RaycastHit[] _hits = new RaycastHit[20];
public override void NetworkStart() public override void NetworkStart()
{ {
Bomber?.SpawnedBombs.Add(this); Bomber?.SpawnedBombs.Add(this);
} GetComponent<Renderer>().enabled = true;
}
public override void NetworkDestroy() public override void NetworkDestroy()
{ {
Bomber?.SpawnedBombs.Remove(this); Bomber?.SpawnedBombs.Remove(this);
// spawn explosion // spawn explosion.
if (ExplosionPrefab != null) if (ExplosionPrefab != null)
Instantiate(ExplosionPrefab, transform.position, Quaternion.identity); Instantiate(ExplosionPrefab, transform.position, Quaternion.identity);
} }
public override void NetworkReset()
{
GetComponent<Renderer>().enabled = true;
}
public override void NetworkFixedUpdate() public override void NetworkFixedUpdate()
{ {
if (Sandbox.TickToTime(Sandbox.Tick - Object.SpawnTick) >= ExplosionDelay) if (Sandbox.TickToTime(Sandbox.Tick - Object.SpawnTick) >= ExplosionDelay)
@@ -41,47 +38,35 @@ namespace Netick.Samples.Bomberman
private void Explode() private void Explode()
{ {
// hide bomb after delay // hide bomb after delay.
GetComponent<Renderer>().enabled = false; GetComponent<Renderer>().enabled = false;
// dealing damage is done on the server only // dealing damage is done on the server only.
if (IsServer) if (IsServer)
{
DamageTargetsAroundBomb(transform.position); DamageTargetsAroundBomb(transform.position);
// only the server can destroy the bomb or the client but only when the Id of the bomb is -1, meaning it was a spawn-predicted but never was confirmed by the server
if (IsServer || Id == -1)
Sandbox.Destroy(Object); Sandbox.Destroy(Object);
}
private void DamageTargetsAroundBomb(Vector3 pos)
{
// Find all objects around the bomb position
// Note: Causes GC
foreach (var dir in _directionsAroundBomb)
{
var hits = Physics.RaycastAll(pos, dir, 1f);
foreach (var hit in hits)
Damage(hit.collider.gameObject);
} }
} }
private void Damage(GameObject target) private void DamageTargetsAroundBomb(Vector3 pos)
{ {
var obj = target.GetComponent<NetworkObject>(); // find all objects around the bomb position.
var block = target.GetComponent<Block>(); foreach (var dir in _directionsAroundBomb)
var bomber = target.GetComponent<BombermanController>(); {
var hitsCount = Sandbox.Physics.Raycast(pos, dir, _hits, 1f);
// make sure the object is not null and in the same sandbox as the bomb for (int i = 0; i < hitsCount; i++)
if (obj == null || obj.Sandbox != Sandbox) {
return; var target =_hits[i].collider.gameObject;
var block = target.GetComponent<Block>();
var bomber = target.GetComponent<BombermanController>();
if (block != null) if (block != null)
block.Visible = false; block.Visible = false;
bomber?.Die();
if (bomber != null) }
bomber.Die(); }
} }
} }
} }

View File

@@ -9,7 +9,7 @@ namespace Netick.Samples.Bomberman
{ {
public class BombermanController : NetworkBehaviour public class BombermanController : NetworkBehaviour
{ {
public List<Bomb> SpawnedBombs = new List<Bomb>(); public List<Bomb> SpawnedBombs = new(4);
[HideInInspector] [HideInInspector]
public Vector3 SpawnPos; public Vector3 SpawnPos;
[SerializeField] [SerializeField]
@@ -17,11 +17,10 @@ namespace Netick.Samples.Bomberman
[SerializeField] [SerializeField]
private float _speedBoostMultiplayer = 2f; private float _speedBoostMultiplayer = 2f;
private GameObject _bombPrefab; private GameObject _bombPrefab;
private CharacterController _CC; private CharacterController _CC;
// Networked properties // Networked Properties
[Networked] [Networked]
public int Score { get; set; } = 0; public int Score { get; set; } = 0;
[Networked] [Networked]
@@ -34,22 +33,18 @@ namespace Netick.Samples.Bomberman
[Networked(relevancy: Relevancy.InputSource)] [Networked(relevancy: Relevancy.InputSource)]
public float BombPowerUpTimer { get; set; } = 0; public float BombPowerUpTimer { get; set; } = 0;
void Awake()
{
// We store the spawn pos so that we use it later during respawn
SpawnPos = transform.position;
_CC = GetComponent<CharacterController>();
}
public override void NetworkStart() public override void NetworkStart()
{ {
_bombPrefab = Sandbox.GetPrefab("Bomb"); _bombPrefab = Sandbox.GetPrefab("Bomb");
// we store the spawn pos so that we use it later during respawn.
SpawnPos = transform.position;
_CC = GetComponent<CharacterController>();
} }
public override void OnInputSourceLeft() public override void OnInputSourceLeft()
{ {
Sandbox.GetComponent<BombermanEventsHandler>().KillPlayer(this); Sandbox.GetComponent<BombermanEventsHandler>().KillPlayer(this);
// destroy the player object when its input source (controller player) leaves the game // destroy the player object when its input source (controller player) leaves the game.
Sandbox.Destroy(Object); Sandbox.Destroy(Object);
} }
@@ -60,27 +55,30 @@ namespace Netick.Samples.Bomberman
if (FetchInput(out BombermanInput input)) if (FetchInput(out BombermanInput input))
{ {
// clamp movement inputs.
input.Movement = new Vector3(Mathf.Clamp(input.Movement.x, -1f, 1f), Mathf.Clamp(input.Movement.y, -1f, 1f));
if (BombPowerUpTimer > 0) if (BombPowerUpTimer > 0)
BombPowerUpTimer -= Sandbox.FixedDeltaTime; BombPowerUpTimer -= Sandbox.FixedDeltaTime;
else else
MaxBombs = 1; MaxBombs = 1;
if (SpeedPowerUpTimer > 0) if (SpeedPowerUpTimer > 0)
SpeedPowerUpTimer -= Sandbox.FixedDeltaTime; SpeedPowerUpTimer -= Sandbox.FixedDeltaTime;
var hasSpeedBoost = SpeedPowerUpTimer > 0; var hasSpeedBoost = SpeedPowerUpTimer > 0;
var speed = hasSpeedBoost ? _speed * _speedBoostMultiplayer : _speed; var speed = hasSpeedBoost ? _speed * _speedBoostMultiplayer : _speed;
_CC.Move(input.Movement * speed * Sandbox.FixedDeltaTime); _CC.Move(input.Movement * speed * Sandbox.FixedDeltaTime);
// we make sure the z coord of the pos of the player is always zero // we make sure the z coord of the pos of the player is always zero.
transform.position = new Vector3(transform.position.x, transform.position.y, 0f); transform.position = new Vector3(transform.position.x, transform.position.y, 0f);
if (IsServer && input.PlantBomb && SpawnedBombs.Count < MaxBombs) if (IsServer && input.PlantBomb && SpawnedBombs.Count < MaxBombs)
{ {
// * round the bomb pos so that it snaps to the nearest square. // round the bomb pos so that it snaps to the nearest square.
var bomb = Sandbox.NetworkInstantiate(_bombPrefab, Round(transform.position), Quaternion.identity).GetComponent<Bomb>(); var bomb = Sandbox.NetworkInstantiate(_bombPrefab, Round(transform.position), Quaternion.identity).GetComponent<Bomb>();
bomb.Bomber = this; bomb.Bomber = this;
} }
} }
} }
@@ -100,31 +98,31 @@ namespace Netick.Samples.Bomberman
public void Die() public void Die()
{ {
Alive = false; Alive = false;
Sandbox.GetComponent<BombermanEventsHandler>().KillPlayer(this); Sandbox.GetComponent<BombermanEventsHandler>().KillPlayer(this);
} }
public void Respawn() public void Respawn()
{ {
Alive = true;
Sandbox.GetComponent<BombermanEventsHandler>().RespawnPlayer(this); Sandbox.GetComponent<BombermanEventsHandler>().RespawnPlayer(this);
transform.position = SpawnPos; Alive = true;
SpeedPowerUpTimer = 0; SpeedPowerUpTimer = 0;
BombPowerUpTimer = 0; BombPowerUpTimer = 0;
MaxBombs = 1; MaxBombs = 1;
transform.position = SpawnPos;
} }
[OnChanged(nameof(Alive))] [OnChanged(nameof(Alive))]
private void OnAliveChanged(OnChangedData onChangedData) private void OnAliveChanged(OnChangedData onChangedData)
{ {
// Based on state of Alive: // based on state of Alive:
// * Hide/show player object // * hide/show player object.
GetComponentInChildren<Renderer>().SetEnabled(Sandbox,Alive); GetComponentInChildren<Renderer>().SetEnabled(Sandbox,Alive);
// * Enable/disable the CharacterController // * enable/disable the CharacterController.
_CC.enabled = Alive; _CC.enabled = Alive;
} }

View File

@@ -5,99 +5,73 @@ using Netick.Unity;
namespace Netick.Samples.Bomberman namespace Netick.Samples.Bomberman
{ {
public class BombermanEventsHandler : NetworkEventsListener public class BombermanEventsHandler : NetworkBehaviour
{ {
public List<BombermanController> Players = new(4);
public List<BombermanController> AlivePlayers = new(4);
public List<BombermanController> AlivePlayers = new List<BombermanController>(); private GameObject _playerPrefab;
public Vector3[] SpawnPositions = new Vector3[4] private Vector3[] _spawnPositions = new Vector3[4] { new Vector3(11, 9, 0), new Vector3(11, 1, 0), new Vector3(1, 9, 0), new Vector3(1, 1, 0) };
private Queue<Vector3> _freePositions = new(4);
public override void NetworkStart()
{ {
new Vector3(11, 9, 0), Sandbox.Events.OnInputRead += OnInput;
new Vector3(11, 1, 0), Sandbox.Events.OnConnectRequest += OnConnectRequest;
new Vector3(1, 9, 0), Sandbox.Events.OnPlayerConnected += OnPlayerConnected;
new Vector3(1, 1, 0) Sandbox.Events.OnPlayerDisconnected += OnPlayerDisconnected;
};
private GameObject _playerPrefab; _playerPrefab = Sandbox.GetPrefab("Bomberman Player");
private Queue<Vector3> _freePositions = new Queue<Vector3>(4); Sandbox.InitializePool(Sandbox.GetPrefab("Bomb"), 5);
Sandbox.InitializePool(_playerPrefab,4);
// ******************* Netick Callbacks ******************* for (int i = 0; i < 4; i++)
_freePositions.Enqueue(_spawnPositions[i]);
// This is called on the server and the clients when Netick has started. if (IsServer)
public override void OnStartup(NetworkSandbox sandbox) RestartGame();
}
public void OnConnectRequest(NetworkSandbox sandbox, NetworkConnectionRequest request)
{ {
_playerPrefab = sandbox.GetPrefab("Bomberman Player"); if (Sandbox.ConnectedPlayers.Count >= 4)
sandbox.InitializePool(sandbox.GetPrefab("Bomb"), 5); request.Refuse();
}
// This is called on the server when a playerObj has connected.
public void OnPlayerConnected(NetworkSandbox sandbox, NetworkPlayer player)
{
var playerObj = sandbox.NetworkInstantiate(_playerPrefab, _spawnPositions[Sandbox.ConnectedPlayers.Count], Quaternion.identity, player).GetComponent<BombermanController>();
player.PlayerObject = playerObj.gameObject;
AlivePlayers. Add(playerObj);
Players. Add(playerObj);
}
// This is called on the server when a client has disconnected.
public void OnPlayerDisconnected(NetworkSandbox sandbox, Netick.NetworkPlayer player, TransportDisconnectReason reason)
{
_freePositions.Enqueue(((GameObject)player.PlayerObject).GetComponent<BombermanController>().SpawnPos);
Players. Remove (((GameObject)player.PlayerObject).GetComponent<BombermanController>());
} }
// This is called to read inputs. // This is called to read inputs.
public override void OnInput(NetworkSandbox sandbox) public void OnInput(NetworkSandbox sandbox)
{ {
var input = sandbox.GetInput<BombermanInput>(); var input = sandbox.GetInput<BombermanInput>();
input.Movement = GetMovementDir(); input.Movement = GetMovementDir();
input.PlantBomb |= Input.GetKeyDown(KeyCode.Space); input.PlantBomb |= Input.GetKeyDown(KeyCode.Space);
sandbox.SetInput(input); sandbox.SetInput(input);
} }
// This is called on the server when a player has connected.
public override void OnPlayerConnected(NetworkSandbox sandbox, NetworkPlayer networkPlayer)
{
var player = sandbox.NetworkInstantiate(_playerPrefab, SpawnPositions[Sandbox.ConnectedPlayers.Count], Quaternion.identity, networkPlayer).GetComponent<BombermanController>();
networkPlayer.PlayerObject = player.gameObject;
AlivePlayers.Add(player);
}
// This is called on the server when a client has disconnected.
public override void OnClientDisconnected(NetworkSandbox sandbox, NetworkConnection client, TransportDisconnectReason reason)
{
_freePositions.Enqueue(((GameObject)client.PlayerObject).GetComponent<BombermanController>().SpawnPos);
}
public override void OnConnectRequest(NetworkSandbox sandbox, NetworkConnectionRequest request)
{
if (_freePositions.Count < 1)
request.Refuse();
}
// This is called on the server and the clients when the scene has been loaded.
public override void OnSceneLoaded(NetworkSandbox sandbox)
{
if (sandbox.IsClient)
return;
_freePositions.Clear();
for (int i = 0; i < 4; i++)
_freePositions.Enqueue(SpawnPositions[i]);
RestartGame();
}
// ******************* ********************
public void RestartGame() public void RestartGame()
{ {
DestroyLevel(); // destroy level.
CreateNewLevel(); foreach (var block in Sandbox.FindObjectsOfType<Block>())
foreach (var player in Sandbox.ConnectedPlayers)
((GameObject)player.PlayerObject).GetComponent<BombermanController>().Respawn();
}
private void DestroyLevel()
{
var blocks = Sandbox.FindObjectsOfType<Block>();
var bombs = Sandbox.FindObjectsOfType<Bomb>();
foreach (var block in blocks)
Sandbox.Destroy(block.Object); Sandbox.Destroy(block.Object);
foreach (var bomb in bombs) foreach (var bomb in Sandbox.FindObjectsOfType<Bomb>())
Sandbox.Destroy(bomb.Object); Sandbox.Destroy(bomb.Object);
}
// create new level.
private void CreateNewLevel()
{
var blockPrefab = Sandbox.GetPrefab("DestroyableBlock"); var blockPrefab = Sandbox.GetPrefab("DestroyableBlock");
var powerUpPrefab = Sandbox.GetPrefab("Power Up"); var powerUpPrefab = Sandbox.GetPrefab("Power Up");
var numberOfBoosters = Random.Range(2, 4+1); var numberOfBoosters = Random.Range(2, 4+1);
@@ -109,8 +83,8 @@ namespace Netick.Samples.Bomberman
{ {
for (int y = 1; y <= maxY; y++) for (int y = 1; y <= maxY; y++)
{ {
var spawn = Random.value > 0.5f; var spawn = Random.value > 0.5f;
var pos = new Vector3(x, y); var pos = new Vector3(x, y);
if (spawn && IsValidPos(pos)) if (spawn && IsValidPos(pos))
{ {
@@ -122,8 +96,8 @@ namespace Netick.Samples.Bomberman
while (numberOfBoosters > 0) while (numberOfBoosters > 0)
{ {
var randomPos = new Vector3(Random.Range(1, 11+1), Random.Range(1, 9+1), 0); var randomPos = new Vector3(Random.Range(1, 11+1), Random.Range(1, 9+1), 0);
var type = (Random.value > 0.5f) ? PowerUpType.Speed : PowerUpType.IncreaseBombs; var type = (Random.value > 0.5f) ? PowerUpType.Speed : PowerUpType.IncreaseBombs;
if (!takenPositions.Contains(randomPos) && IsValidPos(randomPos)) if (!takenPositions.Contains(randomPos) && IsValidPos(randomPos))
{ {
@@ -132,24 +106,25 @@ namespace Netick.Samples.Bomberman
numberOfBoosters--; numberOfBoosters--;
} }
} }
// reset players.
foreach (var player in Players)
player.Respawn();
} }
private bool IsValidPos(Vector3 pos) private bool IsValidPos(Vector3 pos)
{ {
// if the pos is the position of a static block, we ignore it // if the pos is the position of a static block, we ignore it.
if ((pos.x >= 2 && pos.x <= 10) && (pos.y >= 2 && pos.y <= 8)) if ((pos.x >= 2 && pos.x <= 10) && (pos.y >= 2 && pos.y <= 8))
if (pos.x % 2 == 0 && pos.y % 2 == 0) if (pos.x % 2 == 0 && pos.y % 2 == 0)
return false; return false;
// if the pos is near the position of the spawn locations of the players, we ignore it // if the pos is near the position of the spawn locations of the players, we ignore it.
foreach (var loc in SpawnPositions) foreach (var loc in _spawnPositions)
{ {
if (pos == loc) if (pos == loc) return false;
return false; if (pos == loc + Vector3.up || pos == loc + Vector3.down) return false;
if (pos == loc + Vector3.up || pos == loc + Vector3.down) if (pos == loc + Vector3.left || pos == loc + Vector3.right) return false;
return false;
if (pos == loc + Vector3.left || pos == loc + Vector3.right)
return false;
} }
return true; return true;
@@ -168,24 +143,19 @@ namespace Netick.Samples.Bomberman
else if (AlivePlayers.Count < 1) else if (AlivePlayers.Count < 1)
RestartGame(); RestartGame();
} }
public void RespawnPlayer(BombermanController bomber) public void RespawnPlayer(BombermanController bomber)
{ {
if (!AlivePlayers.Contains(bomber)) if (!AlivePlayers.Contains(bomber))
AlivePlayers.Add(bomber); AlivePlayers.Add(bomber);
} }
private Vector2 GetMovementDir() private Vector2 GetMovementDir()
{ {
if (Input.GetKey(KeyCode.W)) if (Input.GetKey(KeyCode.W)) return Vector2.up;
return Vector2.up; else if (Input.GetKey(KeyCode.D)) return Vector2.right;
else if (Input.GetKey(KeyCode.D)) else if (Input.GetKey(KeyCode.S)) return Vector2.down;
return Vector2.right; else if (Input.GetKey(KeyCode.A)) return Vector2.left;
else if (Input.GetKey(KeyCode.S)) else return Vector2.zero;
return Vector2.down;
else if (Input.GetKey(KeyCode.A))
return Vector2.left;
else
return Vector2.zero;
} }
} }
} }

View File

@@ -4,9 +4,11 @@ using Netick.Unity;
namespace Netick.Samples.Bomberman namespace Netick.Samples.Bomberman
{ {
[Networked]
public struct BombermanInput : INetworkInput public struct BombermanInput : INetworkInput
{ {
public Vector2 Movement; [Networked]
public Vector2 Movement { get; set; }
public NetworkBool PlantBomb; public NetworkBool PlantBomb;
} }
} }

View File

@@ -15,26 +15,19 @@ namespace Netick.Samples.Bomberman
public float PowerUpTime = 35; public float PowerUpTime = 35;
private Material _mat; private Material _mat;
// Networked properties // Networked Properties
[Networked] [Networked]
public PowerUpType Type { get; set; } public PowerUpType Type { get; set; }
private void Awake() private void Awake()
{ {
_mat = GetComponentInChildren<Renderer>().material; _mat = GetComponentInChildren<Renderer>().material;
} }
private void Update() public override void NetworkRender()
{ {
if (Type == PowerUpType.IncreaseBombs) var color = Type == PowerUpType.IncreaseBombs ? Color.green : Color.blue;
_mat.color = GetColor(Color.green); _mat.color = Color.Lerp(color, color * 0.5f, Mathf.InverseLerp(-1f, 1f, Mathf.Sin(15f * Time.time)));
else
_mat.color = GetColor(Color.blue);
}
private Color GetColor(Color color)
{
return Color.Lerp(color, color * 0.5f, Mathf.InverseLerp(-1f, 1f, Mathf.Sin(15f * Time.time)));
} }
public void OnTriggerEnter(Collider other) public void OnTriggerEnter(Collider other)
@@ -44,7 +37,7 @@ namespace Netick.Samples.Bomberman
var player = other.gameObject.GetComponent<BombermanController>(); var player = other.gameObject.GetComponent<BombermanController>();
if (Sandbox.IsServer) if (Sandbox.IsServer && player != null)
{ {
player.ReceivePowerUp(Type, PowerUpTime); player.ReceivePowerUp(Type, PowerUpTime);
Sandbox.Destroy(Object); Sandbox.Destroy(Object);

View File

@@ -158,8 +158,8 @@ GameObject:
- component: {fileID: 7011933354638177220} - component: {fileID: 7011933354638177220}
- component: {fileID: 5100633453439203130} - component: {fileID: 5100633453439203130}
- component: {fileID: 3197551385548652812} - component: {fileID: 3197551385548652812}
- component: {fileID: 6851739389618402669}
- component: {fileID: 1417749684482701243} - component: {fileID: 1417749684482701243}
- component: {fileID: 6918953610149222310}
m_Layer: 0 m_Layer: 0
m_Name: FPS Player m_Name: FPS Player
m_TagString: Untagged m_TagString: Untagged
@@ -223,25 +223,13 @@ MonoBehaviour:
TeleportDistance: 50 TeleportDistance: 50
PositionPrecision: 3 PositionPrecision: 3
Settings: 5 Settings: 5
TransformSpace: 0 TransformSpace: 1
EnablePredictionErrorCorrectionSmoothing: 0
InterpolationMultiplier: 20
CorrectionMultiplier: 3
CorrectionMaxBlendAlpha: 0.7
TeleportErrorThreshold: 50
_interpolationSource: 0 _interpolationSource: 0
--- !u!114 &6851739389618402669
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7011933354638177272}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 754e582306c60a24eb1619b9878f55fd, type: 3}
m_Name:
m_EditorClassIdentifier:
_movementSpeed: 10
_sensitivityX: 1.6
_sensitivityY: -1
_cameraParent: {fileID: 3369032719007731524}
<YawPitch>k__BackingField: {x: 0, y: 0}
--- !u!143 &1417749684482701243 --- !u!143 &1417749684482701243
CharacterController: CharacterController:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -268,3 +256,21 @@ CharacterController:
m_SkinWidth: 0.08 m_SkinWidth: 0.08
m_MinMoveDistance: 0.001 m_MinMoveDistance: 0.001
m_Center: {x: 0, y: 0, z: 0} m_Center: {x: 0, y: 0, z: 0}
--- !u!114 &6918953610149222310
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7011933354638177272}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 754e582306c60a24eb1619b9878f55fd, type: 3}
m_Name:
m_EditorClassIdentifier:
_renderTransform: {fileID: 4519677825914407182}
_movementSpeed: 10
_sensitivityX: 1.6
_sensitivityY: -1
_cameraParent: {fileID: 3369032719007731524}
<YawPitch>k__BackingField: {x: 0, y: 0}

View File

@@ -453,6 +453,11 @@ MonoBehaviour:
AutoConnect: 0 AutoConnect: 0
Port: 36339 Port: 36339
ServerIPAddress: 127.0.0.1 ServerIPAddress: 127.0.0.1
Cap: 1
FPS: 450
ShowDisconnectButton: 1
ShowConnectButton: 1
Offset: {x: 36, y: 0}
--- !u!4 &1293352709 --- !u!4 &1293352709
Transform: Transform:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -480,6 +485,15 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: d6475ef2cc420914e87d5433265300cf, type: 3} m_Script: {fileID: 11500000, guid: d6475ef2cc420914e87d5433265300cf, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
Offset: {x: 27, y: 20}
MediumLatencyThreshold: 150
HighLatencyThreshold: 250
MediumPacketLossThreshold: 1
HighPacketLossThreshold: 10
PacketLossIconOffset: {x: -80, y: 30}
LatencyIconOffset: {x: -80, y: 70}
ServerLagIconOffset: {x: -80, y: 110}
IconSize: 30
--- !u!114 &1293352711 --- !u!114 &1293352711
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -790,9 +804,9 @@ Transform:
SceneRoots: SceneRoots:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_Roots: m_Roots:
- {fileID: 1293352709}
- {fileID: 1318413501}
- {fileID: 2022675087} - {fileID: 2022675087}
- {fileID: 1318413501}
- {fileID: 1293352709}
- {fileID: 476934809} - {fileID: 476934809}
- {fileID: 10129275} - {fileID: 10129275}
- {fileID: 1929588644} - {fileID: 1929588644}

View File

@@ -6,6 +6,9 @@ namespace Netick.Samples.FPS
{ {
public class FPSController : NetworkBehaviour public class FPSController : NetworkBehaviour
{ {
[SerializeField]
private Transform _renderTransform;
[SerializeField] [SerializeField]
private float _movementSpeed = 10; private float _movementSpeed = 10;
[SerializeField] [SerializeField]
@@ -17,7 +20,7 @@ namespace Netick.Samples.FPS
private CharacterController _CC; private CharacterController _CC;
private Vector2 _camAngles; private Vector2 _camAngles;
// Networked properties // Networked Properties
[Networked][Smooth] [Networked][Smooth]
public Vector2 YawPitch { get; set; } public Vector2 YawPitch { get; set; }
@@ -36,7 +39,7 @@ namespace Netick.Samples.FPS
public override void OnInputSourceLeft() public override void OnInputSourceLeft()
{ {
// destroy the player object when its input source (controller player) leaves the game // destroy the player object when its input source (controller player) leaves the game.
Sandbox.Destroy(Object); Sandbox.Destroy(Object);
} }
@@ -45,15 +48,17 @@ namespace Netick.Samples.FPS
if (!IsInputSource || !Sandbox.InputEnabled) if (!IsInputSource || !Sandbox.InputEnabled)
return; return;
Vector2 input = new Vector2(Input.GetAxisRaw("Mouse X") * _sensitivityX, Input.GetAxisRaw("Mouse Y") * _sensitivityY); Vector2 mouseInputs = new Vector2(Input.GetAxisRaw("Mouse X") * _sensitivityX, Input.GetAxisRaw("Mouse Y") * _sensitivityY);
var networkInput = Sandbox.GetInput<FPSInput>(); var networkInput = Sandbox.GetInput<FPSInput>();
networkInput.YawPitch += input; networkInput.Movement = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
Sandbox.SetInput<FPSInput>(networkInput); networkInput.ShootInput |= Input.GetMouseButton(0);
networkInput.YawPitch += mouseInputs;
Sandbox.SetInput(networkInput);
// we apply the rotation in update too to have smooth camera control // we apply the rotation in update too to have smooth camera control.
_camAngles = ClampAngles(_camAngles.x + input.x, _camAngles.y + input.y); _camAngles = ClampAngles(_camAngles.x + mouseInputs.x, _camAngles.y + mouseInputs.y);
ApplyRotations(_camAngles); ApplyRotations(_camAngles, false);
} }
public override void NetworkFixedUpdate() public override void NetworkFixedUpdate()
@@ -64,17 +69,20 @@ namespace Netick.Samples.FPS
private void MoveAndRotate(FPSInput input) private void MoveAndRotate(FPSInput input)
{ {
// rotation // clamp movement inputs.
YawPitch = ClampAngles(YawPitch.x + input.YawPitch.x, YawPitch.y + input.YawPitch.y); input.Movement = new Vector3(Mathf.Clamp(input.Movement.x, -1f, 1f), Mathf.Clamp(input.Movement.y, -1f, 1f));
ApplyRotations(YawPitch);
// movement direction // rotation.
var movement = transform.TransformVector(new Vector3(input.Movement.x, 0, input.Movement.y)) * _movementSpeed; YawPitch = ClampAngles(YawPitch.x + input.YawPitch.x, YawPitch.y + input.YawPitch.y);
movement.y = 0; ApplyRotations(YawPitch,false);
var gravity = 15f * Vector3.down; // movement direction.
var movement = transform.TransformVector(new Vector3(input.Movement.x, 0, input.Movement.y)) * _movementSpeed;
movement.y = 0;
// move var gravity = 15f * Vector3.down;
// move.
_CC.Move((movement + gravity) * Sandbox.FixedDeltaTime); _CC.Move((movement + gravity) * Sandbox.FixedDeltaTime);
} }
@@ -82,26 +90,28 @@ namespace Netick.Samples.FPS
[OnChanged(nameof(YawPitch), invokeDuringResimulation: true)] [OnChanged(nameof(YawPitch), invokeDuringResimulation: true)]
private void OnYawPitchChanged(OnChangedData onChanged) private void OnYawPitchChanged(OnChangedData onChanged)
{ {
ApplyRotations(YawPitch); ApplyRotations(YawPitch, false);
} }
public override void NetworkRender() public override void NetworkRender()
{ {
if (IsProxy) if (IsProxy)
ApplyRotations(YawPitch); ApplyRotations(YawPitch, true);
} }
private void ApplyRotations(Vector2 camAngles) private void ApplyRotations(Vector2 camAngles, bool isProxy)
{ {
// on the player transform, we apply yaw // on the player transform, we apply yaw.
transform.rotation = Quaternion.Euler(new Vector3(0, camAngles.x, 0)); if (isProxy)
_renderTransform.rotation = Quaternion.Euler(new Vector3(0, camAngles.x, 0));
else
transform.rotation = Quaternion.Euler(new Vector3(0, camAngles.x, 0));
// on the weapon/camera holder, we apply the pitch angle // on the weapon/camera holder, we apply the pitch angle.
_cameraParent.localEulerAngles = new Vector3(camAngles.y, 0, 0); _cameraParent.localEulerAngles = new Vector3(camAngles.y, 0, 0);
_camAngles = camAngles; _camAngles = camAngles;
} }
private Vector2 ClampAngles(float yaw, float pitch) private Vector2 ClampAngles(float yaw, float pitch)
{ {
return new Vector2(ClampAngle(yaw, -360, 360), ClampAngle(pitch, -80, 80)); return new Vector2(ClampAngle(yaw, -360, 360), ClampAngle(pitch, -80, 80));

View File

@@ -9,16 +9,6 @@ namespace Netick.Samples.FPS
public Transform SpawnPos; public Transform SpawnPos;
public GameObject PlayerPrefab; public GameObject PlayerPrefab;
// This is called to read inputs.
public override void OnInput(NetworkSandbox sandbox)
{
var input = sandbox.GetInput<FPSInput>();
input.Movement = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
input.ShootInput |= Input.GetMouseButton(0);
sandbox.SetInput<FPSInput>(input);
}
// This is called on the server when a player has connected. // This is called on the server when a player has connected.
public override void OnPlayerConnected(NetworkSandbox sandbox, NetworkPlayer networkPlayer) public override void OnPlayerConnected(NetworkSandbox sandbox, NetworkPlayer networkPlayer)
{ {

View File

@@ -3,10 +3,13 @@ using Netick;
namespace Netick.Samples.FPS namespace Netick.Samples.FPS
{ {
[Networked]
public struct FPSInput : INetworkInput public struct FPSInput : INetworkInput
{ {
public Vector2 YawPitch; [Networked]
public Vector2 Movement; public Vector2 YawPitch { get; set; }
[Networked]
public Vector2 Movement { get; set; }
public NetworkBool ShootInput; public NetworkBool ShootInput;
} }
} }

View File

@@ -70,11 +70,11 @@ namespace Netick.Transport
private readonly byte[] _connectionBytes = new byte[200]; private readonly byte[] _connectionBytes = new byte[200];
private int _port; private int _port;
private Dictionary<NetPeer, LNLConnection> _clients = new Dictionary<NetPeer, LNLConnection>(); private Dictionary<NetPeer, LNLConnection> _clients = new();
private Queue<LNLConnection> _freeClients = new Queue<LNLConnection>(); private Queue<LNLConnection> _freeClients = new();
// LAN Discovery // LAN Discovery
private List<Session> _sessions = new List<Session>(); private List<Session> _sessions = new();
private NetDataWriter _writer = new NetDataWriter(); private NetDataWriter _writer = new NetDataWriter();
private string _machineName; private string _machineName;
@@ -88,7 +88,7 @@ namespace Netick.Transport
_buffer = new BitBuffer(createChunks: false); _buffer = new BitBuffer(createChunks: false);
_netManager = new NetManager((INetEventListener)this) { AutoRecycle = true }; _netManager = new NetManager((INetEventListener)this) { AutoRecycle = true };
_machineName = Environment.MachineName; _machineName = Environment.MachineName;
_netManager.DisconnectTimeout = (int)( _provider.DisconnectTimeout * 1000); _netManager.DisconnectTimeout = (int)(_provider.DisconnectTimeout * 1000);
_netManager.ReconnectDelay = (int)(_provider.ReconnectInterval * 1000); _netManager.ReconnectDelay = (int)(_provider.ReconnectInterval * 1000);
_netManager.MaxConnectAttempts = _provider.MaxConnectAttempts; _netManager.MaxConnectAttempts = _provider.MaxConnectAttempts;
_netManager.UpdateTime = (int)(_provider.UpdateInterval * 1000); _netManager.UpdateTime = (int)(_provider.UpdateInterval * 1000);

View File

@@ -1,6 +1,6 @@
{ {
"name": "com.karrar.netick", "name": "com.karrar.netick",
"version": "0.12.41", "version": "0.12.42",
"displayName": "Netick", "displayName": "Netick",
"description": "A networking solution for Unity", "description": "A networking solution for Unity",
"unity": "2021.3", "unity": "2021.3",