alap
This commit is contained in:
67
Assets/Scripts/CharacterSkinElement.cs
Normal file
67
Assets/Scripts/CharacterSkinElement.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using Steamworks;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
public class CharacterSkinElement : MonoBehaviour
|
||||
{
|
||||
public Transform nametagPos;
|
||||
|
||||
public MyClient client { get; private set; }
|
||||
public CSteamID steamId { get; private set; }
|
||||
public NametagMarker nametagMarker { get; set; }
|
||||
|
||||
bool initialized = false;
|
||||
Sprite icon;
|
||||
protected Callback<AvatarImageLoaded_t> avatarImageLoaded;
|
||||
|
||||
private void OnAvatarImageLoaded(AvatarImageLoaded_t callback)
|
||||
{
|
||||
if (callback.m_steamID != steamId) return;
|
||||
|
||||
Texture2D tex = SteamHelper.GetAvatar(steamId);
|
||||
if(tex)
|
||||
icon = SteamHelper.ConvertTextureToSprite(tex);
|
||||
nametagMarker.UpdatePFP(icon);
|
||||
}
|
||||
|
||||
public void Initialize(MyClient client, bool _isReady)
|
||||
{
|
||||
string username = SteamFriends.GetPersonaName();
|
||||
bool isReady = _isReady;
|
||||
|
||||
steamId = client ? new CSteamID(client.playerInfo.steamId) : SteamUser.GetSteamID();
|
||||
|
||||
if (nametagMarker == null)
|
||||
nametagMarker = (NametagMarker)MarkerHandler.instance.SpawnMarker(0, nametagPos.position, null);
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
this.client = client;
|
||||
username = client.playerInfo.username;
|
||||
icon = client.icon;
|
||||
}
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = true;
|
||||
avatarImageLoaded = Callback<AvatarImageLoaded_t>.Create(OnAvatarImageLoaded);
|
||||
|
||||
Texture2D tex = SteamHelper.GetAvatar(steamId);
|
||||
if (tex)
|
||||
icon = SteamHelper.ConvertTextureToSprite(tex); nametagMarker.UpdatePFP(icon);
|
||||
}
|
||||
|
||||
nametagMarker.UpdateTag(username, isReady);
|
||||
nametagMarker.UpdatePFP(icon);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (nametagMarker)
|
||||
nametagMarker.DestroyMarker();
|
||||
}
|
||||
|
||||
}
|
11
Assets/Scripts/CharacterSkinElement.cs.meta
Normal file
11
Assets/Scripts/CharacterSkinElement.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b27e9af7236205e4cb5c6aceca60c9a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
88
Assets/Scripts/CharacterSkinHandler.cs
Normal file
88
Assets/Scripts/CharacterSkinHandler.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using Mirror;
|
||||
using Steamworks;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
public class CharacterSkinHandler : MonoBehaviour
|
||||
{
|
||||
public static CharacterSkinHandler instance;
|
||||
|
||||
[SerializeField] private GameObject characterSkinPrefab;
|
||||
[SerializeField] private Transform[] spawnPositions;
|
||||
public CharacterSkinElement[] clientsCharacters;
|
||||
private void Awake()
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
clientsCharacters = new CharacterSkinElement[NetworkManager.singleton.maxConnections];
|
||||
|
||||
StartCoroutine(WaitTillSteamInitialized());
|
||||
}
|
||||
|
||||
IEnumerator WaitTillSteamInitialized()
|
||||
{
|
||||
while (!SteamManager.Initialized)
|
||||
yield return new WaitForEndOfFrame();
|
||||
|
||||
SpawnCharacterMesh(null);
|
||||
}
|
||||
public void SpawnCharacterMesh(MyClient client)
|
||||
{
|
||||
int index = GetNextPlatformIndex(client);
|
||||
|
||||
if(client && client.isLocalPlayer)
|
||||
{
|
||||
client.characterInstance = clientsCharacters[0];
|
||||
client.characterInstance.Initialize(client, client.IsReady);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
clientsCharacters[index] = Instantiate(characterSkinPrefab, spawnPositions[index]).GetComponent<CharacterSkinElement>();
|
||||
clientsCharacters[index].Initialize(client, client ? client.IsReady : false);
|
||||
|
||||
|
||||
if (client)
|
||||
client.characterInstance = clientsCharacters[index];
|
||||
}
|
||||
|
||||
public int GetNextPlatformIndex(MyClient client)
|
||||
{
|
||||
if (client == null || client.isLocalPlayer)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < clientsCharacters.Length; i++)
|
||||
{
|
||||
if(clientsCharacters[i] == null)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void DestroyCharacterMesh(MyClient client)
|
||||
{
|
||||
foreach (var character in clientsCharacters)
|
||||
{
|
||||
if(character == null)
|
||||
continue;
|
||||
|
||||
if (character.client == client)
|
||||
{
|
||||
if (character == clientsCharacters[0])
|
||||
{
|
||||
clientsCharacters[0].Initialize(client, false);
|
||||
MainMenu.instance.UpdateReadyButton(false);
|
||||
}
|
||||
else
|
||||
Destroy(character.gameObject);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/CharacterSkinHandler.cs.meta
Normal file
11
Assets/Scripts/CharacterSkinHandler.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57d18d537abc50e4fa7a309050dfbbe5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/Scripts/Extensions.meta
Normal file
8
Assets/Scripts/Extensions.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c3aed70129c830468c2963252484828
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
15
Assets/Scripts/Extensions/ArrayExtension.cs
Normal file
15
Assets/Scripts/Extensions/ArrayExtension.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using UnityEngine;
|
||||
|
||||
public static class ArrayExtension
|
||||
{
|
||||
|
||||
public static T GetRandomFromArray<T>(T[] array)
|
||||
{
|
||||
if (array.Length > 0)
|
||||
{
|
||||
return array[Random.Range(0, array.Length)];
|
||||
}
|
||||
return default;
|
||||
}
|
||||
|
||||
}
|
11
Assets/Scripts/Extensions/ArrayExtension.cs.meta
Normal file
11
Assets/Scripts/Extensions/ArrayExtension.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c0653a9321e8014ea8aaade33c69f45
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
49
Assets/Scripts/Extensions/MonoBehaviourExtensions.cs
Normal file
49
Assets/Scripts/Extensions/MonoBehaviourExtensions.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public static class MonoBehaviourExtensions
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This will Call a method wtih a delay (including being able to use delegates unlike Invoke(nameof(method), delay);)
|
||||
/// </summary>
|
||||
/// <param name="mono"></param>
|
||||
/// <param name="method"></param>
|
||||
/// <param name="delay"></param>
|
||||
public static void CallWithDelay(this MonoBehaviour mono, Action method, float delay)
|
||||
=> mono.StartCoroutine(CallWithDelayRoutine(method, delay));
|
||||
|
||||
static IEnumerator CallWithDelayRoutine(Action method, float delay)
|
||||
{
|
||||
yield return new WaitForSeconds(delay);
|
||||
method();
|
||||
}
|
||||
|
||||
|
||||
public static GameObject[] ShuffleList(this MonoBehaviour mono, List<GameObject> list)
|
||||
{
|
||||
GameObject[] array = list.ToArray();
|
||||
|
||||
// Shuffle the array using Fisher-Yates algorithm
|
||||
for (int i = 0; i < array.Length - 1; i++)
|
||||
{
|
||||
int randomIndex = UnityEngine.Random.Range(i, array.Length);
|
||||
GameObject temp = array[i];
|
||||
array[i] = array[randomIndex];
|
||||
array[randomIndex] = temp;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public static float RoundValue(float value, int decimalAmount)
|
||||
{
|
||||
float multiplier = Mathf.Pow(10.0f, decimalAmount);
|
||||
return Mathf.Round(value * multiplier) / multiplier;
|
||||
}
|
||||
|
||||
}
|
||||
|
11
Assets/Scripts/Extensions/MonoBehaviourExtensions.cs.meta
Normal file
11
Assets/Scripts/Extensions/MonoBehaviourExtensions.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8546b79ebab6cc544b7e02354332a262
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
56
Assets/Scripts/Extensions/SteamHelper.cs
Normal file
56
Assets/Scripts/Extensions/SteamHelper.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using Steamworks;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public static class SteamHelper
|
||||
{
|
||||
|
||||
public static Texture2D GetAvatar(CSteamID steamID)
|
||||
{
|
||||
int imageID = SteamFriends.GetLargeFriendAvatar(steamID);
|
||||
if (imageID == -1) return null;
|
||||
|
||||
Texture2D texture = null;
|
||||
|
||||
bool isValid = SteamUtils.GetImageSize(imageID, out uint width, out uint height);
|
||||
|
||||
if (isValid)
|
||||
{
|
||||
byte[] image = new byte[width * height * 4];
|
||||
|
||||
isValid = SteamUtils.GetImageRGBA(imageID, image, (int)(width * height * 4));
|
||||
|
||||
if (isValid)
|
||||
{
|
||||
texture = new Texture2D((int)width, (int)height, TextureFormat.RGBA32, false, false);
|
||||
texture.LoadRawTextureData(image);
|
||||
texture.Apply();
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Sprite ConvertTextureToSprite(Texture2D texture)
|
||||
{
|
||||
return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
|
||||
}
|
||||
|
||||
|
||||
public static List<CSteamID> GetMembersInLobby()
|
||||
{
|
||||
List<CSteamID> members = new List<CSteamID>();
|
||||
int memberAmount = SteamMatchmaking.GetNumLobbyMembers(SteamLobby.LobbyID);
|
||||
|
||||
for (int i = 0; i < memberAmount; i++)
|
||||
{
|
||||
CSteamID cSteamID = SteamMatchmaking.GetLobbyMemberByIndex(SteamLobby.LobbyID, i);
|
||||
members.Add(cSteamID);
|
||||
}
|
||||
|
||||
return members;
|
||||
}
|
||||
}
|
||||
|
11
Assets/Scripts/Extensions/SteamHelper.cs.meta
Normal file
11
Assets/Scripts/Extensions/SteamHelper.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7faf9027c4eb4594798d708da42bd056
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
62
Assets/Scripts/FriendItem.cs
Normal file
62
Assets/Scripts/FriendItem.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using Steamworks;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class FriendItem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Image _iconImage;
|
||||
[SerializeField] private Image _statusImage;
|
||||
[SerializeField] private TMP_Text _usernameText;
|
||||
|
||||
/* [SerializeField] private Color onlineColor;
|
||||
[SerializeField] private Color offlineColor;*/
|
||||
private string username;
|
||||
private CSteamID steamID;
|
||||
private bool isOnline;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
avatarImageLoaded = Callback<AvatarImageLoaded_t>.Create(OnAvatarImageLoaded);
|
||||
}
|
||||
public void InitializeFriendItem(string name, ulong id, bool status)
|
||||
{
|
||||
username = name;
|
||||
steamID = new CSteamID(id);
|
||||
isOnline = status;
|
||||
|
||||
_usernameText.text = username;
|
||||
//_statusImage.color = isOnline ? onlineColor : offlineColor;
|
||||
|
||||
//_iconImage.sprite = SteamHelper.GetAvatar(steamID);
|
||||
GetIcon();
|
||||
|
||||
}
|
||||
|
||||
public void InviteFriend()
|
||||
{
|
||||
SteamMatchmaking.InviteUserToLobby(SteamLobby.LobbyID, steamID);
|
||||
}
|
||||
|
||||
|
||||
Sprite icon;
|
||||
protected Callback<AvatarImageLoaded_t> avatarImageLoaded;
|
||||
|
||||
private void OnAvatarImageLoaded(AvatarImageLoaded_t callback)
|
||||
{
|
||||
if (callback.m_steamID != steamID) return;
|
||||
GetIcon();
|
||||
}
|
||||
|
||||
void GetIcon()
|
||||
{
|
||||
Texture2D tex = SteamHelper.GetAvatar(steamID);
|
||||
if (tex)
|
||||
{
|
||||
icon = SteamHelper.ConvertTextureToSprite(tex);
|
||||
_iconImage.sprite = icon;
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/FriendItem.cs.meta
Normal file
11
Assets/Scripts/FriendItem.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39424224dc4222c4a803fa7e76838603
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
102
Assets/Scripts/FriendListManager.cs
Normal file
102
Assets/Scripts/FriendListManager.cs
Normal file
@ -0,0 +1,102 @@
|
||||
using Steamworks;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class FriendListManager : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject _steamFriendItem;
|
||||
[SerializeField] private Transform _friendListContainer;
|
||||
[SerializeField] private List<FriendItem> _friendList = new List<FriendItem>();
|
||||
|
||||
private Dictionary<CSteamID, FriendItem> friendDictionary = new Dictionary<CSteamID, FriendItem>();
|
||||
|
||||
|
||||
[SerializeField] private float timeToRefreshList = 30f;
|
||||
float timer;
|
||||
|
||||
bool initialized = false;
|
||||
private void Start()
|
||||
{
|
||||
|
||||
}
|
||||
private void Update()
|
||||
{
|
||||
if (SteamManager.Initialized)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
GetSteamFriends();
|
||||
initialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
timer += Time.deltaTime;
|
||||
if (timer > timeToRefreshList)
|
||||
{
|
||||
GetSteamFriends();
|
||||
timer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GetSteamFriends()
|
||||
{
|
||||
if (_friendList.Count > 0)
|
||||
{
|
||||
foreach (FriendItem friend in _friendList)
|
||||
{
|
||||
Destroy(friend.gameObject);
|
||||
}
|
||||
_friendList.Clear();
|
||||
}
|
||||
|
||||
int friendsCount = SteamFriends.GetFriendCount(EFriendFlags.k_EFriendFlagImmediate);
|
||||
int currentOnlineCount = 0;
|
||||
|
||||
if (friendsCount == -1)
|
||||
{
|
||||
Debug.LogError("Friend count returned at -1, the user is not logged in");
|
||||
friendsCount = 0;
|
||||
}
|
||||
|
||||
//ONLINE FIRST
|
||||
for (int i = 0; i < friendsCount; i++)
|
||||
{
|
||||
CSteamID friendSteamID = SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate);
|
||||
string friendName = SteamFriends.GetFriendPersonaName(friendSteamID);
|
||||
EPersonaState friendState = SteamFriends.GetFriendPersonaState(friendSteamID);
|
||||
|
||||
bool isOnline = false;
|
||||
|
||||
if (friendState == EPersonaState.k_EPersonaStateOffline)
|
||||
continue;
|
||||
else
|
||||
isOnline = true;
|
||||
|
||||
FriendItem friendItem = Instantiate(_steamFriendItem, _friendListContainer).GetComponent<FriendItem>();
|
||||
friendItem.InitializeFriendItem(friendName, friendSteamID.m_SteamID, isOnline);
|
||||
_friendList.Add(friendItem);
|
||||
currentOnlineCount++;
|
||||
}
|
||||
|
||||
//OFFLINE LAST
|
||||
for (int i = 0; i < friendsCount; i++)
|
||||
{
|
||||
CSteamID friendSteamID = SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate);
|
||||
string friendName = SteamFriends.GetFriendPersonaName(friendSteamID);
|
||||
EPersonaState friendState = SteamFriends.GetFriendPersonaState(friendSteamID);
|
||||
|
||||
bool isOnline = false;
|
||||
|
||||
if (friendState == EPersonaState.k_EPersonaStateOffline)
|
||||
isOnline = false;
|
||||
else
|
||||
continue;
|
||||
|
||||
FriendItem friendItem = Instantiate(_steamFriendItem, _friendListContainer).GetComponent<FriendItem>();
|
||||
friendItem.InitializeFriendItem(friendName, friendSteamID.m_SteamID, isOnline);
|
||||
_friendList.Add(friendItem);
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/FriendListManager.cs.meta
Normal file
11
Assets/Scripts/FriendListManager.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9083ffff4021744597068b92d1df3db
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
53
Assets/Scripts/LobbyController.cs
Normal file
53
Assets/Scripts/LobbyController.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using Mirror;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class LobbyController : MonoBehaviour
|
||||
{
|
||||
public static LobbyController instance;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
|
||||
|
||||
public void StartGameWithParty()
|
||||
{
|
||||
if (AllPlayersReady())
|
||||
{
|
||||
StartGame();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void StartGameSolo()
|
||||
{
|
||||
StartCoroutine(StartSinglePlayer());
|
||||
}
|
||||
IEnumerator StartSinglePlayer()
|
||||
{
|
||||
NetworkManager.singleton.StartHost();
|
||||
|
||||
while(NetworkClient.localPlayer == null)
|
||||
yield return new WaitForEndOfFrame();
|
||||
|
||||
((MyNetworkManager)NetworkManager.singleton).SetMultiplayer(false);
|
||||
StartGame();
|
||||
}
|
||||
|
||||
private void StartGame()
|
||||
{
|
||||
NetworkManager.singleton.ServerChangeScene("Stage_1");
|
||||
}
|
||||
|
||||
private bool AllPlayersReady()
|
||||
{
|
||||
foreach (MyClient client in ((MyNetworkManager)NetworkManager.singleton).allClients)
|
||||
if (!client.IsReady)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
11
Assets/Scripts/LobbyController.cs.meta
Normal file
11
Assets/Scripts/LobbyController.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ba7df8027f02f94c92f43d9d02d5b7c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
93
Assets/Scripts/MainMenu.cs
Normal file
93
Assets/Scripts/MainMenu.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using Mirror;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public enum MenuState { Home, InParty}
|
||||
public class MainMenu : MonoBehaviour
|
||||
{
|
||||
public static MainMenu instance;
|
||||
|
||||
public MenuState state = MenuState.Home;
|
||||
[SerializeField] private GameObject homeUI, partyUI;
|
||||
|
||||
[Header("Ready Button")]
|
||||
[SerializeField] private Image readyButton_Image;
|
||||
[SerializeField] private TMP_Text readyButton_Text;
|
||||
public Color readyColor, notReadyColor;
|
||||
private void Awake()
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public void SetMenuState(MenuState state)
|
||||
{
|
||||
this.state = state;
|
||||
|
||||
homeUI.SetActive(state == MenuState.Home);
|
||||
partyUI.SetActive(state == MenuState.InParty);
|
||||
}
|
||||
|
||||
public void CreateParty()
|
||||
{
|
||||
|
||||
PopupManager.instance.Popup_Show("Creating Party");
|
||||
|
||||
((MyNetworkManager)NetworkManager.singleton).SetMultiplayer(true);
|
||||
SteamLobby.instance.CreateLobby();
|
||||
}
|
||||
|
||||
public void StartSinglePlayer()
|
||||
{
|
||||
LobbyController.instance.StartGameSolo();
|
||||
}
|
||||
|
||||
public void LeaveParty()
|
||||
{
|
||||
if (!NetworkClient.active) return;
|
||||
|
||||
if(NetworkClient.localPlayer.isServer)
|
||||
NetworkManager.singleton.StopHost();
|
||||
else
|
||||
NetworkManager.singleton.StopClient();
|
||||
|
||||
SteamLobby.instance.Leave();
|
||||
}
|
||||
|
||||
public void FindMatch()
|
||||
{
|
||||
SteamLobby.instance.FindMatch();
|
||||
}
|
||||
|
||||
public void StartGame()
|
||||
{
|
||||
LobbyController.instance.StartGameWithParty();
|
||||
}
|
||||
|
||||
public void StartLocalClient()
|
||||
{
|
||||
((MyNetworkManager)NetworkManager.singleton).SetMultiplayer(true);
|
||||
NetworkManager.singleton.StartClient();
|
||||
}
|
||||
|
||||
public void StartLocalHost()
|
||||
{
|
||||
((MyNetworkManager)NetworkManager.singleton).SetMultiplayer(true);
|
||||
NetworkManager.singleton.StartHost();
|
||||
}
|
||||
|
||||
public void ToggleReady()
|
||||
{
|
||||
if (!NetworkClient.active) return;
|
||||
|
||||
NetworkClient.localPlayer.GetComponent<MyClient>().ToggleReady();
|
||||
}
|
||||
|
||||
public void UpdateReadyButton(bool value)
|
||||
{
|
||||
readyButton_Text.text = value ? "Ready" : "Not Ready";
|
||||
readyButton_Image.color = value ? readyColor : notReadyColor;
|
||||
}
|
||||
}
|
11
Assets/Scripts/MainMenu.cs.meta
Normal file
11
Assets/Scripts/MainMenu.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 284b6fd5c3191dc4fac424b5f10dfa81
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/Scripts/Markers.meta
Normal file
8
Assets/Scripts/Markers.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9df7d0ffa0b65b419c8bf6b476132f7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
54
Assets/Scripts/Markers/Marker.cs
Normal file
54
Assets/Scripts/Markers/Marker.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using Mirror;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
public class Marker : MonoBehaviour
|
||||
{
|
||||
public MarkerDefinition markerDefinition;
|
||||
/* public CanvasGroup fadeGroup;
|
||||
public CanvasGroup aimFadeGroup;
|
||||
public AnimationCurve fadeRemap;*/
|
||||
|
||||
public Vector3 targetPos { get; private set; }
|
||||
public GameObject worldObject { get; private set; }
|
||||
|
||||
MarkerHandler markerHandler;
|
||||
Transform objToFollow;
|
||||
|
||||
float timeAlive;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (objToFollow)
|
||||
{
|
||||
targetPos = objToFollow.transform.position;
|
||||
}
|
||||
|
||||
|
||||
if (markerDefinition.unlimitedLife) return;
|
||||
|
||||
timeAlive += Time.deltaTime;
|
||||
if (timeAlive > markerDefinition.lifeDuration)
|
||||
{
|
||||
DestroyMarker();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void InitializeMarker(MarkerHandler markerHandler, GameObject worldObject, Vector3 targetPos, Transform objToFollow)
|
||||
{
|
||||
this.markerHandler = markerHandler;
|
||||
this.worldObject = worldObject;
|
||||
this.targetPos = targetPos;
|
||||
this.objToFollow = objToFollow;
|
||||
/* aimFadeGroup.alpha = 0;
|
||||
fadeGroup.alpha = 0;*/
|
||||
}
|
||||
|
||||
public virtual void DestroyMarker()
|
||||
{
|
||||
markerHandler.RemoveMarker(this);
|
||||
}
|
||||
}
|
11
Assets/Scripts/Markers/Marker.cs.meta
Normal file
11
Assets/Scripts/Markers/Marker.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2cd7a42d3a95a6469836350e9008ffc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
18
Assets/Scripts/Markers/MarkerDefinition.cs
Normal file
18
Assets/Scripts/Markers/MarkerDefinition.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
[CreateAssetMenu(menuName = "Markers/Marker")]
|
||||
public class MarkerDefinition : ScriptableObject
|
||||
{
|
||||
public byte id;
|
||||
|
||||
[Space(10)]
|
||||
public GameObject markerLocalObj, markerWorldObj;
|
||||
public float lifeDuration;
|
||||
public bool unlimitedLife;
|
||||
public float minFadeAmount;
|
||||
public bool fadeByDotProduct;
|
||||
public bool fadeByAim;
|
||||
}
|
||||
|
11
Assets/Scripts/Markers/MarkerDefinition.cs.meta
Normal file
11
Assets/Scripts/Markers/MarkerDefinition.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35a98cf24352f1f4d99d7a33c0b4d1e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
89
Assets/Scripts/Markers/MarkerHandler.cs
Normal file
89
Assets/Scripts/Markers/MarkerHandler.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MarkerHandler : MonoBehaviour
|
||||
{
|
||||
public static MarkerHandler instance;
|
||||
|
||||
[SerializeField] private MarkerDefinition[] allMarkerDefinitions;
|
||||
[SerializeField] private Transform markerContainer;
|
||||
|
||||
List<Marker> markerInstances = new List<Marker>();
|
||||
Camera cam;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
cam = Camera.main;
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
UpdateMarkers();
|
||||
}
|
||||
void UpdateMarkers()
|
||||
{
|
||||
|
||||
for (int i = 0; i < markerInstances.Count; i++)
|
||||
{
|
||||
var currentMarker = markerInstances[i];
|
||||
currentMarker.transform.position = cam.WorldToScreenPoint(currentMarker.targetPos);
|
||||
// aimFadeAmount = 1 - player.weaponManager.aim.aimAmount;
|
||||
|
||||
bool isBehindCam = currentMarker.transform.position.z < 0;
|
||||
float dot = Vector3.Dot(cam.transform.forward, (cam.transform.position - currentMarker.targetPos).normalized);
|
||||
//Debug.Log(dot);
|
||||
|
||||
/*
|
||||
if (currentMarker.markerDefinition.fadeByAim)
|
||||
currentMarker.aimFadeGroup.alpha = isBehindCam ? 0 : Mathf.Max(aimFadeAmount, currentMarker.markerDefinition.minFadeAmount);
|
||||
|
||||
if (currentMarker.markerDefinition.fadeByDotProduct)
|
||||
currentMarker.fadeGroup.alpha = isBehindCam ? 0 : Mathf.Clamp01(Mathf.Clamp(currentMarker.fadeRemap.Evaluate(Mathf.Clamp01(-dot)), currentMarker.markerDefinition.minFadeAmount, 1));
|
||||
|
||||
currentMarker.gameObject.SetActive(!player.IsUIOpen());*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Marker SpawnMarker(byte markerID, Vector3 targetPos, Transform objToFollow)
|
||||
{
|
||||
MarkerDefinition markerDef = allMarkerDefinitions[markerID];
|
||||
|
||||
GameObject localObj = Instantiate(markerDef.markerLocalObj, markerContainer);
|
||||
GameObject worldObj = null;
|
||||
Marker marker = localObj.GetComponent<Marker>();
|
||||
|
||||
if (markerDef.markerWorldObj)
|
||||
{
|
||||
worldObj = Instantiate(markerDef.markerWorldObj, targetPos, Quaternion.identity);
|
||||
}
|
||||
|
||||
marker.InitializeMarker(this, worldObj, targetPos, objToFollow);
|
||||
|
||||
AddMarker(marker);
|
||||
|
||||
return marker;
|
||||
}
|
||||
|
||||
public void AddMarker(Marker marker)
|
||||
{
|
||||
markerInstances.Add(marker);
|
||||
}
|
||||
|
||||
public void RemoveMarker(Marker marker)
|
||||
{
|
||||
markerInstances.Remove(marker);
|
||||
|
||||
if (marker.worldObject)
|
||||
Destroy(marker.worldObject);
|
||||
|
||||
Destroy(marker.gameObject);
|
||||
}
|
||||
|
||||
}
|
11
Assets/Scripts/Markers/MarkerHandler.cs.meta
Normal file
11
Assets/Scripts/Markers/MarkerHandler.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c3fa5eb1f4aef54a91cc6c50111cc9e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
25
Assets/Scripts/Markers/NametagMarker.cs
Normal file
25
Assets/Scripts/Markers/NametagMarker.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class NametagMarker : Marker
|
||||
{
|
||||
public TMP_Text username_text, ready_text;
|
||||
public Image ready_image, pfp_Image;
|
||||
|
||||
public void UpdateTag(string username, bool isReady)
|
||||
{
|
||||
username_text.text = username;
|
||||
ready_image.color = isReady ? MainMenu.instance.readyColor : MainMenu.instance.notReadyColor;
|
||||
ready_text.text = isReady ? "Ready" : "Not Ready";
|
||||
ready_text.color = isReady ? MainMenu.instance.readyColor : MainMenu.instance.notReadyColor;
|
||||
}
|
||||
|
||||
public void UpdatePFP(Sprite icon)
|
||||
{
|
||||
pfp_Image.sprite = icon;
|
||||
}
|
||||
}
|
11
Assets/Scripts/Markers/NametagMarker.cs.meta
Normal file
11
Assets/Scripts/Markers/NametagMarker.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79b83d359693de5458001ffa4e86801e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
94
Assets/Scripts/Movement.cs
Normal file
94
Assets/Scripts/Movement.cs
Normal file
@ -0,0 +1,94 @@
|
||||
using Mirror;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Movement : NetworkBehaviour
|
||||
{
|
||||
[Header("Movement Settings")]
|
||||
[SerializeField] private float walkingSpeed = 7.5f;
|
||||
[SerializeField] private float runningSpeed = 11.5f;
|
||||
[SerializeField] private float jumpHeight = 8.0f;
|
||||
[SerializeField] private float gravity = 20.0f;
|
||||
public Camera playerCamera;
|
||||
|
||||
[Header("Grounding")]
|
||||
[SerializeField] private LayerMask groundMask;
|
||||
[SerializeField] private Transform groundedCheck;
|
||||
[SerializeField] private float groundedDistance = 2;
|
||||
|
||||
[Header("Camera")]
|
||||
[SerializeField] private Transform camHolder;
|
||||
[SerializeField] private float lookSpeed = 2.0f;
|
||||
[SerializeField] private float lookXLimit = 45.0f;
|
||||
float rotationX = 0;
|
||||
Vector2 inputDir;
|
||||
|
||||
|
||||
|
||||
public CharacterController characterController { get; private set; }
|
||||
public bool isGrounded { get; private set; }
|
||||
|
||||
Vector3 velocity;
|
||||
|
||||
void Start()
|
||||
{
|
||||
Cursor.lockState = CursorLockMode.Locked;
|
||||
characterController = GetComponent<CharacterController>();
|
||||
}
|
||||
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
if (!isLocalPlayer) return;
|
||||
|
||||
CheckIfGrounded();
|
||||
bool isRunning = Input.GetKey(KeyCode.LeftShift);
|
||||
MovementHandler(isRunning);
|
||||
}
|
||||
|
||||
private void MovementHandler(bool isRunning)
|
||||
{
|
||||
if (isGrounded && velocity.y < 0)
|
||||
velocity.y = 0f;
|
||||
|
||||
Vector3 moveDir = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized;
|
||||
Vector3 fixedMoveDir;
|
||||
|
||||
moveDir *= (isRunning ? runningSpeed : walkingSpeed);
|
||||
moveDir = transform.TransformDirection(moveDir);
|
||||
|
||||
if (Input.GetButtonDown("Jump") && isGrounded)
|
||||
velocity.y += Mathf.Sqrt(jumpHeight * -3.0f * -gravity);
|
||||
|
||||
velocity.y -= gravity * Time.deltaTime;
|
||||
|
||||
fixedMoveDir = moveDir;
|
||||
fixedMoveDir.y = velocity.y;
|
||||
|
||||
characterController.Move(fixedMoveDir * Time.deltaTime);
|
||||
}
|
||||
|
||||
public void CheckIfGrounded()
|
||||
{
|
||||
isGrounded = Physics.Raycast(groundedCheck.position, Vector3.down, groundedDistance, groundMask);
|
||||
}
|
||||
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (!isLocalPlayer) return;
|
||||
|
||||
inputDir = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
|
||||
rotationX += -inputDir.y * lookSpeed;
|
||||
rotationX = Mathf.Clamp(rotationX, -lookXLimit, lookXLimit);
|
||||
camHolder.transform.localRotation = Quaternion.Euler(rotationX, 0, 0);
|
||||
transform.rotation *= Quaternion.Euler(0, inputDir.x * lookSpeed, 0);
|
||||
}
|
||||
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
if (groundedCheck)
|
||||
Gizmos.DrawRay(groundedCheck.position, Vector3.down * groundedDistance);
|
||||
}
|
||||
}
|
11
Assets/Scripts/Movement.cs.meta
Normal file
11
Assets/Scripts/Movement.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1345dc4c8b97453448fc9e22f2205527
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
133
Assets/Scripts/MyClient.cs
Normal file
133
Assets/Scripts/MyClient.cs
Normal file
@ -0,0 +1,133 @@
|
||||
using Mirror;
|
||||
using Steamworks;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
[System.Serializable]
|
||||
public struct PlayerInfoData
|
||||
{
|
||||
public string username;
|
||||
public ulong steamId;
|
||||
|
||||
public PlayerInfoData(string username, ulong steamId)
|
||||
{
|
||||
this.username = username;
|
||||
this.steamId = steamId;
|
||||
}
|
||||
}
|
||||
public class MyClient : NetworkBehaviour
|
||||
{
|
||||
[SyncVar(hook = nameof(PlayerInfoUpdate))]
|
||||
public PlayerInfoData playerInfo;
|
||||
|
||||
[SyncVar(hook = nameof(IsReadyUpdate))]
|
||||
public bool IsReady;
|
||||
|
||||
[Header("Controller")]
|
||||
[SerializeField] private GameObject controllerObj;
|
||||
[SerializeField] private GameObject meshObj;
|
||||
[SerializeField] private GameObject camHolder;
|
||||
[SerializeField] private Behaviour[] controllerComponents;
|
||||
|
||||
public Sprite icon { get; private set; }
|
||||
public CharacterSkinElement characterInstance { get; set; }
|
||||
|
||||
#region Steam PFP
|
||||
protected Callback<AvatarImageLoaded_t> avatarImageLoaded;
|
||||
private void OnAvatarImageLoaded(AvatarImageLoaded_t callback)
|
||||
{
|
||||
Debug.Log("Avatar loaded " + callback.m_steamID);
|
||||
if (callback.m_steamID.m_SteamID != playerInfo.steamId) return;
|
||||
SetIcon(callback.m_steamID);
|
||||
}
|
||||
|
||||
void SetIcon(CSteamID steamId)
|
||||
{
|
||||
Texture2D tex = SteamHelper.GetAvatar(steamId);
|
||||
if (tex)
|
||||
icon = SteamHelper.ConvertTextureToSprite(tex);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void Start()
|
||||
{
|
||||
((MyNetworkManager)NetworkManager.singleton).allClients.Add(this);
|
||||
|
||||
if(CharacterSkinHandler.instance) CharacterSkinHandler.instance.SpawnCharacterMesh(this);
|
||||
avatarImageLoaded = Callback<AvatarImageLoaded_t>.Create(OnAvatarImageLoaded);
|
||||
|
||||
if (SceneManager.GetActiveScene().name != "MainMenu")
|
||||
{
|
||||
ToggleController(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ToggleController(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleController(bool value)
|
||||
{
|
||||
controllerObj.SetActive(value);
|
||||
meshObj.SetActive(value ? !isLocalPlayer : false);
|
||||
camHolder.SetActive(value ? isLocalPlayer : false);
|
||||
|
||||
if (!isLocalPlayer)
|
||||
value = false;
|
||||
|
||||
|
||||
foreach (var component in controllerComponents)
|
||||
{
|
||||
component.enabled = value;
|
||||
}
|
||||
|
||||
GetComponent<CharacterController>().enabled = value;
|
||||
}
|
||||
|
||||
#region Ready Up
|
||||
public void ToggleReady() => Cmd_ToggleReady();
|
||||
|
||||
[Command]
|
||||
private void Cmd_ToggleReady()
|
||||
{
|
||||
IsReady = !IsReady;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SyncVar Hooks
|
||||
private void PlayerInfoUpdate(PlayerInfoData _, PlayerInfoData data)
|
||||
{
|
||||
if (characterInstance)
|
||||
characterInstance.Initialize(this, IsReady);
|
||||
|
||||
SetIcon(new CSteamID(data.steamId));
|
||||
}
|
||||
|
||||
public void IsReadyUpdate(bool _, bool value)
|
||||
{
|
||||
if (characterInstance)
|
||||
characterInstance.Initialize(this, value);
|
||||
if (isLocalPlayer)
|
||||
{
|
||||
MainMenu.instance.UpdateReadyButton(value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (this && ((MyNetworkManager)NetworkManager.singleton))
|
||||
((MyNetworkManager)NetworkManager.singleton).allClients.Remove(this);
|
||||
|
||||
if (characterInstance && !isLocalPlayer)
|
||||
{
|
||||
CharacterSkinHandler.instance.DestroyCharacterMesh(this);
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/MyClient.cs.meta
Normal file
11
Assets/Scripts/MyClient.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c4b5dc7895a402408126e4e9a847dd6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
58
Assets/Scripts/MyNetworkManager.cs
Normal file
58
Assets/Scripts/MyNetworkManager.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using Mirror;
|
||||
using Steamworks;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MyNetworkManager : NetworkManager
|
||||
{
|
||||
public static bool isMulitplayer;
|
||||
|
||||
public List<MyClient> allClients = new List<MyClient>();
|
||||
public override void OnServerAddPlayer(NetworkConnectionToClient conn)
|
||||
{
|
||||
base.OnServerAddPlayer(conn);
|
||||
|
||||
MyClient client = conn.identity.GetComponent<MyClient>();
|
||||
CSteamID steamId = SteamLobby.LobbyID.m_SteamID == 0 ? SteamUser.GetSteamID() : SteamMatchmaking.GetLobbyMemberByIndex(SteamLobby.LobbyID, allClients.Count);
|
||||
client.playerInfo = new PlayerInfoData(SteamFriends.GetFriendPersonaName(steamId), steamId.m_SteamID);
|
||||
}
|
||||
|
||||
public override void OnServerDisconnect(NetworkConnectionToClient conn)
|
||||
{
|
||||
base.OnServerDisconnect(conn);
|
||||
}
|
||||
|
||||
public override void OnStartClient()
|
||||
{
|
||||
if (isMulitplayer)
|
||||
{
|
||||
MainMenu.instance.SetMenuState(MenuState.InParty);
|
||||
PopupManager.instance.Popup_Close();
|
||||
}
|
||||
|
||||
base.OnStartClient();
|
||||
}
|
||||
|
||||
public override void OnStopClient()
|
||||
{
|
||||
if (isMulitplayer)
|
||||
{
|
||||
MainMenu.instance.SetMenuState(MenuState.Home);
|
||||
}
|
||||
|
||||
base.OnStopClient();
|
||||
}
|
||||
|
||||
public void SetMultiplayer(bool value)
|
||||
{
|
||||
isMulitplayer = value;
|
||||
|
||||
if (isMulitplayer)
|
||||
|
||||
NetworkServer.dontListen = false;
|
||||
else
|
||||
|
||||
NetworkServer.dontListen = true;
|
||||
}
|
||||
}
|
11
Assets/Scripts/MyNetworkManager.cs.meta
Normal file
11
Assets/Scripts/MyNetworkManager.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 123bbac7f620cae42b421b72cf58d0bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
68
Assets/Scripts/PopupManager.cs
Normal file
68
Assets/Scripts/PopupManager.cs
Normal file
@ -0,0 +1,68 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class PopupManager : MonoBehaviour
|
||||
{
|
||||
public static PopupManager instance;
|
||||
|
||||
public TMP_Text text_title;
|
||||
|
||||
public GameObject popUp;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public void Popup_Show(string title)
|
||||
{
|
||||
text_title.text = title;
|
||||
popUp.SetActive(true);
|
||||
}
|
||||
public void Popup_Close()
|
||||
{
|
||||
popUp.SetActive(false);
|
||||
}
|
||||
|
||||
}
|
||||
/*public class PopupContent
|
||||
{
|
||||
public string title;
|
||||
public string text;
|
||||
public Sprite icon;
|
||||
public PopupContent_Button[] buttons;
|
||||
|
||||
public PopupContent(string popup_title, string popup_text, Sprite popup_icon, PopupContent_Button[] popup_buttons)
|
||||
{
|
||||
title = popup_title;
|
||||
text = popup_text;
|
||||
icon = popup_icon;
|
||||
buttons = popup_buttons;
|
||||
}
|
||||
}
|
||||
|
||||
public class PopupContent_Button
|
||||
{
|
||||
public string text = "OK";
|
||||
public string function = "";
|
||||
public MonoBehaviour function_caller;
|
||||
|
||||
//shows default ok button
|
||||
public PopupContent_Button()
|
||||
{
|
||||
text = "OK";
|
||||
function = "";
|
||||
function_caller = null;
|
||||
}
|
||||
|
||||
//show special button
|
||||
public PopupContent_Button(string button_text, string button_function, MonoBehaviour button_function_caller)
|
||||
{
|
||||
text = button_text;
|
||||
function = button_function;
|
||||
function_caller = button_function_caller;
|
||||
}
|
||||
}*/
|
11
Assets/Scripts/PopupManager.cs.meta
Normal file
11
Assets/Scripts/PopupManager.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 379041cc65f409e41b6ab54e09095c0f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
195
Assets/Scripts/SteamLobby.cs
Normal file
195
Assets/Scripts/SteamLobby.cs
Normal file
@ -0,0 +1,195 @@
|
||||
using Mirror;
|
||||
using Steamworks;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
[System.Serializable]
|
||||
public class Lobby
|
||||
{
|
||||
public CSteamID lobbyID;
|
||||
public string name;
|
||||
|
||||
public Lobby(CSteamID lobbyID, string name)
|
||||
{
|
||||
this.lobbyID = lobbyID;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public class SteamLobby : MonoBehaviour
|
||||
{
|
||||
private const string HOST_ADDRESS_KEY = "HostAddress";
|
||||
|
||||
public static SteamLobby instance;
|
||||
public static CSteamID LobbyID;
|
||||
|
||||
public List<Lobby> allLobbies = new List<Lobby>();
|
||||
|
||||
//CallBacks
|
||||
protected Callback<LobbyCreated_t> lobbyCreated;
|
||||
protected Callback<GameLobbyJoinRequested_t> joinRequested;
|
||||
protected Callback<LobbyEnter_t> lobbyEntered;
|
||||
protected Callback<LobbyMatchList_t> lobbyMatchList;
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (instance == null)
|
||||
instance = this;
|
||||
|
||||
lobbyMatchList = Callback<LobbyMatchList_t>.Create(OnLobbyMatchList);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (!SteamManager.Initialized) return;
|
||||
|
||||
lobbyCreated = Callback<LobbyCreated_t>.Create(OnLobbyCreated);
|
||||
joinRequested = Callback<GameLobbyJoinRequested_t>.Create(OnJoinRequest);
|
||||
lobbyEntered = Callback<LobbyEnter_t>.Create(OnLobbyEntered);
|
||||
|
||||
ReloadLobbyList();
|
||||
}
|
||||
|
||||
|
||||
#region Steam Lobby
|
||||
public void ReloadLobbyList()
|
||||
{
|
||||
allLobbies.Clear();
|
||||
|
||||
SteamMatchmaking.AddRequestLobbyListDistanceFilter(ELobbyDistanceFilter.k_ELobbyDistanceFilterWorldwide);
|
||||
SteamMatchmaking.AddRequestLobbyListStringFilter("displayable", "true", ELobbyComparison.k_ELobbyComparisonEqual);
|
||||
SteamMatchmaking.RequestLobbyList();
|
||||
}
|
||||
void OnLobbyMatchList(LobbyMatchList_t param)
|
||||
{
|
||||
for (int i = 0; i < param.m_nLobbiesMatching; i++)
|
||||
{
|
||||
CSteamID lobbyID = SteamMatchmaking.GetLobbyByIndex(i);
|
||||
CSteamID ownerID = SteamMatchmaking.GetLobbyOwner(lobbyID);
|
||||
|
||||
allLobbies.Add(new Lobby(lobbyID, SteamMatchmaking.GetLobbyData(lobbyID, "name")));
|
||||
}
|
||||
|
||||
allLobbies.Sort((a, b) => SteamMatchmaking.GetNumLobbyMembers(b.lobbyID).CompareTo(SteamMatchmaking.GetNumLobbyMembers(a.lobbyID)));
|
||||
|
||||
/*for (int i = 0; i < allLobbies.Count; i++)
|
||||
{
|
||||
|
||||
if (SteamMatchmaking.GetLobbyData(allLobbies[i].lobbyID, "displayable") == "true")
|
||||
{
|
||||
var lobbyElement = Instantiate(MainMenu.instance.lobbyElementPrefab, MainMenu.instance.lobbyListContainer).GetComponent<LobbyElement>();
|
||||
lobbyElement.Initialize(allLobbies[i]);
|
||||
allLobbies[i].listElement = lobbyElement.gameObject;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
public void CreateLobby()
|
||||
{
|
||||
SteamMatchmaking.CreateLobby(ELobbyType.k_ELobbyTypePublic, ((MyNetworkManager)NetworkManager.singleton).maxConnections);
|
||||
}
|
||||
|
||||
|
||||
public void JoinLobby(CSteamID lobby)
|
||||
{
|
||||
|
||||
SteamMatchmaking.JoinLobby(lobby);
|
||||
}
|
||||
|
||||
|
||||
private void OnLobbyCreated(LobbyCreated_t callback)
|
||||
{
|
||||
if (callback.m_eResult != EResult.k_EResultOK) { return; }
|
||||
|
||||
string lobbyName = SteamFriends.GetFriendPersonaName(SteamUser.GetSteamID());
|
||||
|
||||
LobbyID = new CSteamID(callback.m_ulSteamIDLobby);
|
||||
|
||||
|
||||
((MyNetworkManager)NetworkManager.singleton).StartHost();
|
||||
|
||||
SteamMatchmaking.SetLobbyData(LobbyID, HOST_ADDRESS_KEY, SteamUser.GetSteamID().ToString());
|
||||
SteamMatchmaking.SetLobbyData(LobbyID, "name", lobbyName);
|
||||
SteamMatchmaking.SetLobbyData(LobbyID, "displayable", "true");
|
||||
|
||||
SetLobbyLocation();
|
||||
}
|
||||
|
||||
|
||||
private void OnJoinRequest(GameLobbyJoinRequested_t callback)
|
||||
{
|
||||
PopupManager.instance.Popup_Show("Joining Party");
|
||||
SteamMatchmaking.JoinLobby(callback.m_steamIDLobby);
|
||||
}
|
||||
|
||||
private void OnLobbyEntered(LobbyEnter_t callback)
|
||||
{
|
||||
//if lobby full leave
|
||||
if (callback.m_bLocked)
|
||||
{
|
||||
SteamMatchmaking.LeaveLobby((CSteamID)callback.m_ulSteamIDLobby);
|
||||
PopupManager.instance.Popup_Close();
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"Entered Lobby {LobbyID}");
|
||||
LobbyID = new CSteamID(callback.m_ulSteamIDLobby);
|
||||
|
||||
|
||||
if (NetworkServer.active)
|
||||
return;
|
||||
((MyNetworkManager)NetworkManager.singleton).SetMultiplayer(true);
|
||||
|
||||
((MyNetworkManager)NetworkManager.singleton).networkAddress = SteamMatchmaking.GetLobbyData(new CSteamID(LobbyID.m_SteamID), HOST_ADDRESS_KEY);
|
||||
((MyNetworkManager)NetworkManager.singleton).StartClient();
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void Leave()
|
||||
{
|
||||
SteamMatchmaking.LeaveLobby(LobbyID);
|
||||
}
|
||||
|
||||
|
||||
public static void SetLobbyLocation()
|
||||
{
|
||||
SteamNetworkingUtils.GetLocalPingLocation(out SteamNetworkPingLocation_t pingLocation);
|
||||
SteamNetworkingUtils.ConvertPingLocationToString(ref pingLocation, out string result, 1024);
|
||||
SteamMatchmaking.SetLobbyData(LobbyID, "location", result);
|
||||
}
|
||||
|
||||
public void FindMatch()
|
||||
{
|
||||
StartCoroutine(FindMatchRoutine());
|
||||
}
|
||||
|
||||
IEnumerator FindMatchRoutine()
|
||||
{
|
||||
PopupManager.instance.Popup_Show("Finding Match..");
|
||||
bool foundMatch = false;
|
||||
|
||||
while (!foundMatch)
|
||||
{
|
||||
ReloadLobbyList();
|
||||
yield return new WaitForSeconds(1);
|
||||
|
||||
foreach (var lobby in allLobbies)
|
||||
{
|
||||
if (SteamMatchmaking.GetNumLobbyMembers(lobby.lobbyID) < NetworkManager.singleton.maxConnections)
|
||||
{
|
||||
JoinLobby(lobby.lobbyID);
|
||||
foundMatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
PopupManager.instance.Popup_Close();
|
||||
|
||||
}
|
||||
}
|
||||
|
11
Assets/Scripts/SteamLobby.cs.meta
Normal file
11
Assets/Scripts/SteamLobby.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74a3fc7eda8dd2747bbcb9546db2aee3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
5
Assets/Scripts/Steamworks.NET.meta
Normal file
5
Assets/Scripts/Steamworks.NET.meta
Normal file
@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62ddefd95a62cbc4ea1a2aabc009a378
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
182
Assets/Scripts/Steamworks.NET/SteamManager.cs
Normal file
182
Assets/Scripts/Steamworks.NET/SteamManager.cs
Normal file
@ -0,0 +1,182 @@
|
||||
// The SteamManager is designed to work with Steamworks.NET
|
||||
// This file is released into the public domain.
|
||||
// Where that dedication is not recognized you are granted a perpetual,
|
||||
// irrevocable license to copy and modify this file as you see fit.
|
||||
//
|
||||
// Version: 1.0.13
|
||||
|
||||
#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX)
|
||||
#define DISABLESTEAMWORKS
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
#if !DISABLESTEAMWORKS
|
||||
using System.Collections;
|
||||
using Steamworks;
|
||||
#endif
|
||||
|
||||
//
|
||||
// The SteamManager provides a base implementation of Steamworks.NET on which you can build upon.
|
||||
// It handles the basics of starting up and shutting down the SteamAPI for use.
|
||||
//
|
||||
[DisallowMultipleComponent]
|
||||
public class SteamManager : MonoBehaviour {
|
||||
#if !DISABLESTEAMWORKS
|
||||
protected static bool s_EverInitialized = false;
|
||||
|
||||
protected static SteamManager s_instance;
|
||||
protected static SteamManager Instance {
|
||||
get {
|
||||
if (s_instance == null) {
|
||||
return new GameObject("SteamManager").AddComponent<SteamManager>();
|
||||
}
|
||||
else {
|
||||
return s_instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected bool m_bInitialized = false;
|
||||
public static bool Initialized {
|
||||
get {
|
||||
return Instance.m_bInitialized;
|
||||
}
|
||||
}
|
||||
|
||||
protected SteamAPIWarningMessageHook_t m_SteamAPIWarningMessageHook;
|
||||
|
||||
[AOT.MonoPInvokeCallback(typeof(SteamAPIWarningMessageHook_t))]
|
||||
protected static void SteamAPIDebugTextHook(int nSeverity, System.Text.StringBuilder pchDebugText) {
|
||||
Debug.LogWarning(pchDebugText);
|
||||
}
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
// In case of disabled Domain Reload, reset static members before entering Play Mode.
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
private static void InitOnPlayMode()
|
||||
{
|
||||
s_EverInitialized = false;
|
||||
s_instance = null;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected virtual void Awake() {
|
||||
// Only one instance of SteamManager at a time!
|
||||
if (s_instance != null) {
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
s_instance = this;
|
||||
|
||||
if(s_EverInitialized) {
|
||||
// This is almost always an error.
|
||||
// The most common case where this happens is when SteamManager gets destroyed because of Application.Quit(),
|
||||
// and then some Steamworks code in some other OnDestroy gets called afterwards, creating a new SteamManager.
|
||||
// You should never call Steamworks functions in OnDestroy, always prefer OnDisable if possible.
|
||||
throw new System.Exception("Tried to Initialize the SteamAPI twice in one session!");
|
||||
}
|
||||
|
||||
// We want our SteamManager Instance to persist across scenes.
|
||||
DontDestroyOnLoad(gameObject);
|
||||
|
||||
if (!Packsize.Test()) {
|
||||
Debug.LogError("[Steamworks.NET] Packsize Test returned false, the wrong version of Steamworks.NET is being run in this platform.", this);
|
||||
}
|
||||
|
||||
if (!DllCheck.Test()) {
|
||||
Debug.LogError("[Steamworks.NET] DllCheck Test returned false, One or more of the Steamworks binaries seems to be the wrong version.", this);
|
||||
}
|
||||
|
||||
try {
|
||||
// If Steam is not running or the game wasn't started through Steam, SteamAPI_RestartAppIfNecessary starts the
|
||||
// Steam client and also launches this game again if the User owns it. This can act as a rudimentary form of DRM.
|
||||
// Note that this will run which ever version you have installed in steam. Which may not be the precise executable
|
||||
// we were currently running.
|
||||
|
||||
// Once you get a Steam AppID assigned by Valve, you need to replace AppId_t.Invalid with it and
|
||||
// remove steam_appid.txt from the game depot. eg: "(AppId_t)480" or "new AppId_t(480)".
|
||||
// See the Valve documentation for more information: https://partner.steamgames.com/doc/sdk/api#initialization_and_shutdown
|
||||
if (SteamAPI.RestartAppIfNecessary(AppId_t.Invalid)) {
|
||||
Debug.Log("[Steamworks.NET] Shutting down because RestartAppIfNecessary returned true. Steam will restart the application.");
|
||||
|
||||
Application.Quit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (System.DllNotFoundException e) { // We catch this exception here, as it will be the first occurrence of it.
|
||||
Debug.LogError("[Steamworks.NET] Could not load [lib]steam_api.dll/so/dylib. It's likely not in the correct location. Refer to the README for more details.\n" + e, this);
|
||||
|
||||
Application.Quit();
|
||||
return;
|
||||
}
|
||||
|
||||
// Initializes the Steamworks API.
|
||||
// If this returns false then this indicates one of the following conditions:
|
||||
// [*] The Steam client isn't running. A running Steam client is required to provide implementations of the various Steamworks interfaces.
|
||||
// [*] The Steam client couldn't determine the App ID of game. If you're running your application from the executable or debugger directly then you must have a [code-inline]steam_appid.txt[/code-inline] in your game directory next to the executable, with your app ID in it and nothing else. Steam will look for this file in the current working directory. If you are running your executable from a different directory you may need to relocate the [code-inline]steam_appid.txt[/code-inline] file.
|
||||
// [*] Your application is not running under the same OS user context as the Steam client, such as a different user or administration access level.
|
||||
// [*] Ensure that you own a license for the App ID on the currently active Steam account. Your game must show up in your Steam library.
|
||||
// [*] Your App ID is not completely set up, i.e. in Release State: Unavailable, or it's missing default packages.
|
||||
// Valve's documentation for this is located here:
|
||||
// https://partner.steamgames.com/doc/sdk/api#initialization_and_shutdown
|
||||
m_bInitialized = SteamAPI.Init();
|
||||
if (!m_bInitialized) {
|
||||
Debug.LogError("[Steamworks.NET] SteamAPI_Init() failed. Refer to Valve's documentation or the comment above this line for more information.", this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
s_EverInitialized = true;
|
||||
}
|
||||
|
||||
// This should only ever get called on first load and after an Assembly reload, You should never Disable the Steamworks Manager yourself.
|
||||
protected virtual void OnEnable() {
|
||||
if (s_instance == null) {
|
||||
s_instance = this;
|
||||
}
|
||||
|
||||
if (!m_bInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_SteamAPIWarningMessageHook == null) {
|
||||
// Set up our callback to receive warning messages from Steam.
|
||||
// You must launch with "-debug_steamapi" in the launch args to receive warnings.
|
||||
m_SteamAPIWarningMessageHook = new SteamAPIWarningMessageHook_t(SteamAPIDebugTextHook);
|
||||
SteamClient.SetWarningMessageHook(m_SteamAPIWarningMessageHook);
|
||||
}
|
||||
}
|
||||
|
||||
// OnApplicationQuit gets called too early to shutdown the SteamAPI.
|
||||
// Because the SteamManager should be persistent and never disabled or destroyed we can shutdown the SteamAPI here.
|
||||
// Thus it is not recommended to perform any Steamworks work in other OnDestroy functions as the order of execution can not be garenteed upon Shutdown. Prefer OnDisable().
|
||||
protected virtual void OnDestroy() {
|
||||
if (s_instance != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
s_instance = null;
|
||||
|
||||
if (!m_bInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
SteamAPI.Shutdown();
|
||||
}
|
||||
|
||||
protected virtual void Update() {
|
||||
if (!m_bInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Run Steam client callbacks
|
||||
SteamAPI.RunCallbacks();
|
||||
}
|
||||
#else
|
||||
public static bool Initialized {
|
||||
get {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif // !DISABLESTEAMWORKS
|
||||
}
|
8
Assets/Scripts/Steamworks.NET/SteamManager.cs.meta
Normal file
8
Assets/Scripts/Steamworks.NET/SteamManager.cs.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef4bffeda13d7a748973ff9204401c07
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
8
Assets/Scripts/Tools.meta
Normal file
8
Assets/Scripts/Tools.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71fa19c60d0d2a6448a115315ee1d8a1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
78
Assets/Scripts/Tools/SceneSwitcher.cs
Normal file
78
Assets/Scripts/Tools/SceneSwitcher.cs
Normal file
@ -0,0 +1,78 @@
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public struct SceneInfo
|
||||
{
|
||||
public string name;
|
||||
public string path;
|
||||
|
||||
public SceneInfo(string name, string path)
|
||||
{
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
}
|
||||
}
|
||||
|
||||
[InitializeOnLoad]
|
||||
public class SceneSwitcher : EditorWindow
|
||||
{
|
||||
private static SceneInfo[] scenes;
|
||||
private static int selectedSceneIndex = 0;
|
||||
|
||||
static SceneSwitcher()
|
||||
{
|
||||
EditorApplication.update += UpdateSceneList;
|
||||
EditorSceneManager.sceneOpened += SceneOpened;
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Scene Switcher")]
|
||||
static void ShowWindow()
|
||||
{
|
||||
GetWindow<SceneSwitcher>("Scene Switcher");
|
||||
}
|
||||
|
||||
private static void UpdateSceneList()
|
||||
{
|
||||
int sceneCount = SceneManager.sceneCountInBuildSettings;
|
||||
scenes = new SceneInfo[sceneCount];
|
||||
|
||||
for (int i = 0; i < sceneCount; i++)
|
||||
{
|
||||
string path = SceneUtility.GetScenePathByBuildIndex(i);
|
||||
string name = System.IO.Path.GetFileNameWithoutExtension(path);
|
||||
scenes[i] = new SceneInfo(name, path);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SceneOpened(Scene scene, OpenSceneMode mode)
|
||||
{
|
||||
UpdateSceneList();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (scenes != null && scenes.Length > 0)
|
||||
{
|
||||
selectedSceneIndex = EditorGUILayout.Popup("Switch Scene", selectedSceneIndex, scenes.Select(s => s.name).ToArray());
|
||||
|
||||
if (GUILayout.Button("Load Scene"))
|
||||
{
|
||||
if (selectedSceneIndex >= 0 && selectedSceneIndex < scenes.Length)
|
||||
{
|
||||
EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
|
||||
EditorSceneManager.OpenScene(scenes[selectedSceneIndex].path);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label("No Scenes in Build Settings");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
11
Assets/Scripts/Tools/SceneSwitcher.cs.meta
Normal file
11
Assets/Scripts/Tools/SceneSwitcher.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12cc48ad2517efa4ab8aa80c4353ef80
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/Scripts/UIElements.meta
Normal file
8
Assets/Scripts/UIElements.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ae0037d7e04d4b4281cf93ecc407525
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user