Added server-sided movement!

This commit is contained in:
BOTAlex 2024-03-01 19:44:22 +01:00
parent 5b2759e65c
commit eae9ae9370
17 changed files with 481 additions and 238 deletions

View File

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

View File

@ -10,12 +10,13 @@ using UnityEngine;
[DisallowMultipleComponent] [DisallowMultipleComponent]
public class ClientNetworkTransform : NetworkTransform public class ClientNetworkTransform : NetworkTransform
{ {
/// <summary> public AuthorityMode authorityMode = AuthorityMode.Client;
/// Used to determine who can write to this transform. Owner client only.
/// This imposes state to the server. This is putting trust on your clients. Make sure no security-sensitive features use this transform. protected override bool OnIsServerAuthoritative() => authorityMode == AuthorityMode.Server;
/// </summary> }
protected override bool OnIsServerAuthoritative()
{ public enum AuthorityMode
return false; {
} Server,
Client
} }

View File

@ -0,0 +1,17 @@
{
"name": "Project.Scripts.Multiplayer.Transforms",
"rootNamespace": "",
"references": [
"GUID:1491147abca9d7d4bb7105af628b223e",
"GUID:3b8ed52f1b5c64994af4c4e0aa4b6c4b"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 41f069d934ffb98448515c5816eaffdf
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -5,17 +5,17 @@ using System;
using UnityEngine; using UnityEngine;
using UnityEngine.InputSystem; using UnityEngine.InputSystem;
public class PlayerInput : MonoBehaviour public class PlayerInput : MonoBehaviour, IMoveData
{ {
[SerializeField] private int playerNumber; [SerializeField] private int playerNumber;
public Vector2 movement; private MoveData moveData = new();
public Vector2 look;
public Gamepad controller { get; private set; } public Gamepad controller { get; private set; }
public bool whipAttack; public bool whipAttack;
public event Action<int> ropeLengthShrinken; public event Action<int> ropeLengthShrinken;
public event Action<int> ropeLengthExtend; public event Action<int> ropeLengthExtend;
public event Action<MoveData> OnNewMoveData;
public bool useArrowKeys = false; public bool useArrowKeys = false;
@ -32,12 +32,14 @@ public class PlayerInput : MonoBehaviour
private void Update() private void Update()
{ {
movement.x = Input.GetAxisRaw("bruh"); moveData.Movement.x = Input.GetAxisRaw("bruh");
movement.y = Input.GetAxisRaw("bruh_v"); moveData.Movement.y = Input.GetAxisRaw("bruh_v");
whipAttack = Input.GetKey(KeyCode.R); whipAttack = Input.GetKey(KeyCode.R);
if (Input.GetKey(KeyCode.E)) ropeLengthShrinken?.Invoke(playerNumber); if (Input.GetKey(KeyCode.E)) ropeLengthShrinken?.Invoke(playerNumber);
if (Input.GetKey(KeyCode.Q)) ropeLengthExtend?.Invoke(playerNumber); if (Input.GetKey(KeyCode.Q)) ropeLengthExtend?.Invoke(playerNumber);
OnNewMoveData?.Invoke(moveData);
} }
} }

View File

@ -2,7 +2,11 @@
"name": "Project.Scripts.Player.Input", "name": "Project.Scripts.Player.Input",
"rootNamespace": "", "rootNamespace": "",
"references": [ "references": [
"GUID:75469ad4d38634e559750d17036d5f7c" "GUID:75469ad4d38634e559750d17036d5f7c",
"GUID:ab47f305e1cd6654ca0ff5d6c7942d09",
"GUID:1491147abca9d7d4bb7105af628b223e",
"GUID:41f069d934ffb98448515c5816eaffdf",
"GUID:3b8ed52f1b5c64994af4c4e0aa4b6c4b"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],

View File

@ -0,0 +1,203 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Unity.Netcode;
using UnityEditor.Events;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
using UnityEngine.Windows;
/// This script is for networking the player with reconciliation
[RequireComponent(typeof(ClientNetworkTransform))]
public class ReconciliationPlayerControllerMiddleman : NetworkBehaviour, IMoveData
{
// Current
private InputPayload currentInputState;
private int currentTick => NetworkManager.Singleton.NetworkTickSystem.LocalTime.Tick;
private int bufferIndex => currentTick % BUFFER_SIZE;
private PlayerInput inputSource;
// Shared
private const int BUFFER_SIZE = 1024;
// Local
private StatePayload[] stateBuffer;
private InputPayload[] inputBuffer;
private StatePayload latestServerState;
private StatePayload lastProcessedState;
private Queue<InputPayload> inputQueue = new Queue<InputPayload>();
private ClientNetworkTransform clientNetworkTransform;
[Header("Debug")]
[SerializeField] private bool ForceEnableComponent = false;
public event Action<MoveData> OnNewMoveData;
void OnEnable()
{
if (NetworkManager.Singleton == null)
{
Debug.Log("[Movement] No network manager found. Ignoring reconciliation.");
if (!ForceEnableComponent)
{
this.enabled = false;
return;
}
}
if (!TryGetComponent(out inputSource))
{
Debug.LogError("[Movement] No player input found. Ignoring reconciliation.");
this.enabled = false;
return;
}
stateBuffer = new StatePayload[BUFFER_SIZE];
inputBuffer = new InputPayload[BUFFER_SIZE];
currentInputState = new InputPayload();
inputSource.OnNewMoveData += (moveData) => currentInputState.moveData = moveData;
clientNetworkTransform = GetComponent<ClientNetworkTransform>();
SwitchAuthorityMode(AuthorityMode.Client);
}
private void Update()
{
if (IsServer)
ServerTick();
if (IsOwner)
ClientTick();
}
private void ServerTick()
{
foreach (InputPayload payload in inputQueue)
{
stateBuffer[bufferIndex] = ProcessMovement(payload);
}
OnServerStateRecieved_ServerRpc(stateBuffer[bufferIndex]);
}
private void ClientTick()
{
if (!latestServerState.Equals(default(StatePayload)) &&
(lastProcessedState.Equals(default(StatePayload)) ||
!latestServerState.Equals(lastProcessedState)))
{
Reconciliation();
}
// Add payload to inputBuffer
InputPayload payload = new InputPayload();
payload.tick = currentTick;
payload.moveData = currentInputState.moveData;
inputBuffer[bufferIndex] = payload;
stateBuffer[bufferIndex] = ProcessMovement(payload);
if (!(IsHost || IsServer))
OnClientInput_ClientRpc(payload);
}
[ClientRpc]
private void OnClientInput_ClientRpc(InputPayload payload)
{
inputQueue.Enqueue(payload);
}
[ServerRpc]
private void OnServerStateRecieved_ServerRpc(StatePayload serverState)
{
if (!IsOwner) return;
latestServerState = serverState;
}
private void Reconciliation()
{
lastProcessedState = latestServerState;
int serverStateBufferIndex = latestServerState.tick % BUFFER_SIZE;
float positionError = Vector3.Distance(latestServerState.position, stateBuffer[serverStateBufferIndex].position);
if (positionError > 0.001f)
{
transform.position = latestServerState.position;
stateBuffer[serverStateBufferIndex] = latestServerState;
int tickToProcess = latestServerState.tick + 1;
for (; tickToProcess < currentTick; tickToProcess++)
{
// Reprocess movement
StatePayload reprocessedState = ProcessMovement(inputBuffer[tickToProcess]);
// Update buffer with reprocessed state
int bufferIndex = tickToProcess % BUFFER_SIZE;
stateBuffer[bufferIndex] = reprocessedState;
}
Debug.Log($"[{latestServerState.tick}] Reconciliated");
}
}
private void SwitchAuthorityMode(AuthorityMode mode)
{
clientNetworkTransform.authorityMode = mode;
bool shouldSync = mode == AuthorityMode.Client;
clientNetworkTransform.SyncPositionX = shouldSync;
clientNetworkTransform.SyncPositionY = shouldSync;
clientNetworkTransform.SyncPositionZ = shouldSync;
}
private StatePayload ProcessMovement(InputPayload payload)
{
OnNewMoveData?.Invoke(payload.moveData);
return new StatePayload()
{
tick = payload.tick,
position = transform.position
};
}
}
public struct InputPayload : INetworkSerializable
{
public int tick;
public MoveData moveData;
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref tick);
serializer.SerializeValue(ref moveData);
}
}
public struct StatePayload : INetworkSerializable
{
public int tick;
public Vector3 position;
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref tick);
serializer.SerializeValue(ref position);
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0b44a9f6fa4174c4da1032d1e3e4ddcd

View File

@ -25,7 +25,7 @@ public class PlayerMovement : MonoBehaviour
[SerializeField] [SerializeField]
private float maxWhipMoveSpeed = 30f; private float maxWhipMoveSpeed = 30f;
private PlayerInput playerInput; private IMoveData playerInput;
private HealthComponent hp; private HealthComponent hp;
private PlayerCollideAttack attack; private PlayerCollideAttack attack;
@ -33,62 +33,34 @@ public class PlayerMovement : MonoBehaviour
private void Start() private void Start()
{ {
rb = GetComponent<Rigidbody2D>(); rb = GetComponent<Rigidbody2D>();
playerInput = GetComponent<PlayerInput>();
hp = GetComponent<HealthComponent>(); hp = GetComponent<HealthComponent>();
attack = GetComponent<PlayerCollideAttack>(); attack = GetComponent<PlayerCollideAttack>();
if (gameObject.name == "Player2") // Try to get middleman first
if (TryGetComponent(out ReconciliationPlayerControllerMiddleman middleman))
{ {
playerInput.useArrowKeys = true; playerInput = middleman;
}
else
{
playerInput = GetComponent<PlayerInput>();
} }
if (playerInput.controller != null) playerInput.OnNewMoveData += PlayerInput_OnNewMoveData;
{
var pad = (DualShockGamepad)Gamepad.all.ElementAtOrDefault(playerInput.PlayerNum);
if (pad == null) return;
if (playerInput.PlayerNum == 1)
pad.SetLightBarColor(Color.red);
}
} }
private void Update() private void PlayerInput_OnNewMoveData(MoveData moveData)
{ {
//if (playerInput.movement != Vector2.zero) rb.AddForce(moveData.Movement * moveSpeed);
// animationHandler.Run(true);
//else
// animationHandler.Run(false);
} }
private void FixedUpdate()
{
//if (whipAttack.IsBeingWhipped)
//{
// //float sign = Vector2.Dot((whipAttack.joint.position - whipAttack.otherPlayerAttack.joint.position).normalized, movement.normalized);
// Vector2 ropeDir = whipAttack.otherPlayerAttack.joint.position - whipAttack.joint.position;
// Vector2 tangent = new Vector2(-ropeDir.y, ropeDir.x).normalized;
// rb.AddForce(Vector2.Dot(playerInput.movement, tangent) * tangent * whipMoveSpeed);
// rb.velocity = Vector2.ClampMagnitude(rb.velocity, maxWhipMoveSpeed);
//}
//else if (whipAttack.IsWhippingOtherPlayer)
//{
// playerInput.movement = Vector2.zero;
//}
//else
{
rb.AddForce(playerInput.movement * moveSpeed);
}
}
void OnCollisionStay2D(Collision2D collision) void OnCollisionStay2D(Collision2D collision)
{ {
if (collision.collider.gameObject.CompareTag("Enemy")) if (collision.collider.gameObject.CompareTag("Enemy"))
{ // Other object is an enemy { // Other object is an enemy
hp.TakeDamage(1f); hp.TakeDamage(1f);
} }
} }

View File

@ -8,7 +8,8 @@
"GUID:ddd4dba7c768b564a879069c52854fc5", "GUID:ddd4dba7c768b564a879069c52854fc5",
"GUID:2ea4a18a75f268848b43865100892489", "GUID:2ea4a18a75f268848b43865100892489",
"GUID:ab47f305e1cd6654ca0ff5d6c7942d09", "GUID:ab47f305e1cd6654ca0ff5d6c7942d09",
"GUID:f4c364e1215051e4dbc6c0bc8fb49793" "GUID:f4c364e1215051e4dbc6c0bc8fb49793",
"GUID:1491147abca9d7d4bb7105af628b223e"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],

View File

@ -0,0 +1,23 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Netcode;
using Unity.VisualScripting.YamlDotNet.Core.Tokens;
using UnityEngine;
public struct MoveData : INetworkSerializable
{
public Vector2 Movement;
public Vector2 Look;
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref Movement);
//serializer.SerializeValue(ref Look); // Not used yet
}
}
public interface IMoveData
{
public event Action<MoveData> OnNewMoveData;
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: fe68eaee6977ed948b5a2a0e53a44ef6

View File

@ -15,15 +15,17 @@ public class PlayerCollideAttack : MonoBehaviour
{ {
if (collision.collider.tag != "Enemy") return; if (collision.collider.tag != "Enemy") return;
HealthComponent health = collision.collider.gameObject.GetComponent<HealthComponent>(); // Below was messing with assembly definitions
if (health == null)
health = collision.collider.transform.parent.GetComponent<HealthComponent>();
if (health == null) return;
health = collision.collider.gameObject.GetComponentInChildren<HealthComponent>();
if (health == null) return;
float speed = body.velocity.magnitude; //HealthComponent health = collision.collider.gameObject.GetComponent<HealthComponent>();
float damage = speedToDamage.Evaluate(speed); //if (health == null)
health.TakeDamage(damage); // health = collision.collider.transform.parent.GetComponent<HealthComponent>();
//if (health == null) return;
// health = collision.collider.gameObject.GetComponentInChildren<HealthComponent>();
//if (health == null) return;
//float speed = body.velocity.magnitude;
//float damage = speedToDamage.Evaluate(speed);
//health.TakeDamage(damage);
} }
} }

View File

@ -3,10 +3,9 @@
"rootNamespace": "", "rootNamespace": "",
"references": [ "references": [
"GUID:6055be8ebefd69e48b49212b09b47b2f", "GUID:6055be8ebefd69e48b49212b09b47b2f",
"GUID:1eb4e3e6c04cdc848bab71651b1e2ecd",
"GUID:f0aa6e1ec272fc041a727a9dfb7c1e67", "GUID:f0aa6e1ec272fc041a727a9dfb7c1e67",
"GUID:75469ad4d38634e559750d17036d5f7c", "GUID:75469ad4d38634e559750d17036d5f7c",
"GUID:2ea4a18a75f268848b43865100892489" "GUID:1491147abca9d7d4bb7105af628b223e"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],

View File

@ -355,26 +355,26 @@ public class RopeSimulator : NetworkBehaviour
{ {
Assert.IsTrue(ShouldSimulate); Assert.IsTrue(ShouldSimulate);
if (overshoot > pullAnimationOvershootThreshold) //if (overshoot > pullAnimationOvershootThreshold)
{ //{
float startDot = Vector2.Dot((start.position - rope.points[1].position).normalized, start.playerInput.movement); // float startDot = Vector2.Dot((start.position - rope.points[1].position).normalized, start.playerInput.movement);
if (startDot > 0.35f) // if (startDot > 0.35f)
{ // {
start.playerAnimationHandler?.animator.SetBool("IsPulling", true); // start.playerAnimationHandler?.animator.SetBool("IsPulling", true);
} // }
float endDot = Vector2.Dot((end.position - rope.points[rope.points.Count - 2].position).normalized, end.playerInput.movement); // float endDot = Vector2.Dot((end.position - rope.points[rope.points.Count - 2].position).normalized, end.playerInput.movement);
if (endDot > 0.35f) // if (endDot > 0.35f)
{ // {
end.playerAnimationHandler?.animator.SetBool("IsPulling", true); // end.playerAnimationHandler?.animator.SetBool("IsPulling", true);
} // }
} //}
else //else
{ //{
start.playerAnimationHandler?.animator.SetBool("IsPulling", false); // start.playerAnimationHandler?.animator.SetBool("IsPulling", false);
end.playerAnimationHandler?.animator.SetBool("IsPulling", false); // end.playerAnimationHandler?.animator.SetBool("IsPulling", false);
} //}
} }
private void PullPlayers(float overshoot) private void PullPlayers(float overshoot)

View File

@ -125,176 +125,176 @@ public class Upgrader : MonoBehaviour
// Update is called once per frame // Update is called once per frame
void Update() void Update()
{ {
bool upgrade = canUpgrade(); //bool upgrade = canUpgrade();
if (canUpgrade()) //if (canUpgrade())
{ //{
if (!prevCouldUpgrade) // if (!prevCouldUpgrade)
{ // {
background.color = Color.white; // background.color = Color.white;
foreach (Image i in upgradeImages) // foreach (Image i in upgradeImages)
{ // {
i.color = Color.white; // i.color = Color.white;
} // }
Player1Cursor.gameObject.SetActive(true); // Player1Cursor.gameObject.SetActive(true);
Player2Cursor.gameObject.SetActive(true); // Player2Cursor.gameObject.SetActive(true);
} // }
int p1a = getRegion(Player1Input.look.x, Player1Input.look.y, 8); // int p1a = getRegion(Player1Input.look.x, Player1Input.look.y, 8);
int p2a = getRegion(Player2Input.look.x, Player2Input.look.y, 8); // int p2a = getRegion(Player2Input.look.x, Player2Input.look.y, 8);
//keyboard upgrade // //keyboard upgrade
if (Input.GetKey(KeyCode.Alpha1)) // if (Input.GetKey(KeyCode.Alpha1))
{ // {
p1a = p2a = 0; // p1a = p2a = 0;
} // }
else if (Input.GetKey(KeyCode.Alpha2)) // else if (Input.GetKey(KeyCode.Alpha2))
{ // {
p1a = p2a = 1; // p1a = p2a = 1;
} // }
else if (Input.GetKey(KeyCode.Alpha3)) // else if (Input.GetKey(KeyCode.Alpha3))
{ // {
p1a = p2a = 2; // p1a = p2a = 2;
} // }
else if (Input.GetKey(KeyCode.Alpha4)) // else if (Input.GetKey(KeyCode.Alpha4))
{ // {
p1a = p2a = 3; // p1a = p2a = 3;
} // }
else if (Input.GetKey(KeyCode.Alpha5)) // else if (Input.GetKey(KeyCode.Alpha5))
{ // {
p1a = p2a = 4; // p1a = p2a = 4;
} // }
else if (Input.GetKey(KeyCode.Alpha6)) // else if (Input.GetKey(KeyCode.Alpha6))
{ // {
p1a = p2a = 5; // p1a = p2a = 5;
} // }
else if (Input.GetKey(KeyCode.Alpha7)) // else if (Input.GetKey(KeyCode.Alpha7))
{ // {
p1a = p2a = 6; // p1a = p2a = 6;
} // }
else if (Input.GetKey(KeyCode.Alpha8)) // else if (Input.GetKey(KeyCode.Alpha8))
{ // {
p1a = p2a = 7; // p1a = p2a = 7;
} // }
if (p1a != -1 && p2a == p1a) // if (p1a != -1 && p2a == p1a)
{ // {
if (acceptTime > 2f) // if (acceptTime > 2f)
{ // {
switch (p1a) // switch (p1a)
{ // {
case 0: // case 0:
UpgradeMopSize(); // UpgradeMopSize();
break; // break;
case 1: // case 1:
UpgradeSpeed(); // UpgradeSpeed();
break; // break;
case 2: // case 2:
RopeUpgrade(); // RopeUpgrade();
break; // break;
case 3: // case 3:
HealthUpgrade(); // HealthUpgrade();
break; // break;
case 4: // case 4:
DamageUpgrade(); // DamageUpgrade();
break; // break;
case 5: // case 5:
BloodUpgrade(); // BloodUpgrade();
break; // break;
case 6: // case 6:
ReelUpgrade(); // ReelUpgrade();
break; // break;
case 7: // case 7:
ReviveUpgrade(); // ReviveUpgrade();
break; // break;
} // }
// Subtract blood // // Subtract blood
bloodManager.score -= upgradeCost; // bloodManager.score -= upgradeCost;
upgradeCost = (int)(upgradeCost * 1.2f); // upgradeCost = (int)(upgradeCost * 1.2f);
acceptTime = 0f; // acceptTime = 0f;
} // }
else // else
{ // {
acceptTime += Time.deltaTime; // acceptTime += Time.deltaTime;
foreach (Image i in upgradeImages) // foreach (Image i in upgradeImages)
{ // {
i.fillAmount = 1f; // i.fillAmount = 1f;
i.gameObject.transform.localScale = Vector3.one; // i.gameObject.transform.localScale = Vector3.one;
} // }
switch (p1a) // switch (p1a)
{ // {
case 0: // case 0:
description.text = upgrades.mopUpgrade.name; // description.text = upgrades.mopUpgrade.name;
break; // break;
case 1: // case 1:
description.text = upgrades.speedUpgrade.name; // description.text = upgrades.speedUpgrade.name;
break; // break;
case 2: // case 2:
description.text = upgrades.ropeUpgrade.name; // description.text = upgrades.ropeUpgrade.name;
break; // break;
case 3: // case 3:
description.text = upgrades.healthUpgrade.name; // description.text = upgrades.healthUpgrade.name;
break; // break;
case 4: // case 4:
description.text = upgrades.damageUpgrade.name; // description.text = upgrades.damageUpgrade.name;
break; // break;
case 5: // case 5:
description.text = upgrades.bloodUpgrade.name; // description.text = upgrades.bloodUpgrade.name;
break; // break;
case 6: // case 6:
description.text = upgrades.reelUpgrade.name; // description.text = upgrades.reelUpgrade.name;
break; // break;
case 7: // case 7:
description.text = upgrades.reviveUpgrade.name; // description.text = upgrades.reviveUpgrade.name;
break; // break;
} // }
upgradeImages[p1a].fillAmount = acceptTime / 2f; // upgradeImages[p1a].fillAmount = acceptTime / 2f;
upgradeImages[p1a].transform.localScale = Vector3.one * 2f; // upgradeImages[p1a].transform.localScale = Vector3.one * 2f;
} // }
} // }
else // else
{ // {
description.text = ""; // description.text = "";
if (acceptTime > 0f) // if (acceptTime > 0f)
{ // {
foreach (Image i in upgradeImages) // foreach (Image i in upgradeImages)
{ // {
i.fillAmount = 1f; // i.fillAmount = 1f;
i.gameObject.transform.localScale = Vector3.one; // i.gameObject.transform.localScale = Vector3.one;
} // }
} // }
acceptTime = 0f; // acceptTime = 0f;
// background.fillAmount = 0f; // // background.fillAmount = 0f;
} // }
} //}
else if (prevCouldUpgrade) //else if (prevCouldUpgrade)
{ //{
AudioManager.PlaySound("Blood_Splatter_Large_SFX", Vector3.zero, false, false); // AudioManager.PlaySound("Blood_Splatter_Large_SFX", Vector3.zero, false, false);
description.text = ""; // description.text = "";
background.color = Color.gray; // background.color = Color.gray;
foreach (Image i in upgradeImages) // foreach (Image i in upgradeImages)
{ // {
i.color = Color.gray; // i.color = Color.gray;
i.gameObject.transform.localScale = Vector3.one; // i.gameObject.transform.localScale = Vector3.one;
} // }
Player1Cursor.gameObject.SetActive(false); // Player1Cursor.gameObject.SetActive(false);
Player2Cursor.gameObject.SetActive(false); // Player2Cursor.gameObject.SetActive(false);
} //}
Player1Cursor.localPosition = Player1Input.look.normalized * (125 - 12); //Player1Cursor.localPosition = Player1Input.look.normalized * (125 - 12);
Player2Cursor.localPosition = Player2Input.look.normalized * (125 - 12); //Player2Cursor.localPosition = Player2Input.look.normalized * (125 - 12);
prevCouldUpgrade = upgrade; //prevCouldUpgrade = upgrade;
} }
/// Increases mop radius by 10% /// Increases mop radius by 10%