first commit
This commit is contained in:
@ -0,0 +1,136 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="ConnectAndJoinRandom.cs" company="Exit Games GmbH">
|
||||
// Part of: Photon Unity Utilities,
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Simple component to call ConnectUsingSettings and to get into a PUN room easily.
|
||||
// </summary>
|
||||
// <remarks>
|
||||
// A custom inspector provides a button to connect in PlayMode, should AutoConnect be false.
|
||||
// </remarks>
|
||||
// <author>developer@exitgames.com</author>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
//#if UNITY_EDITOR
|
||||
//using UnityEditor;
|
||||
//#endif
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
//using Photon.Pun;
|
||||
using Photon.Realtime;
|
||||
|
||||
namespace Photon.Pun.UtilityScripts
|
||||
{
|
||||
/// <summary>Simple component to call ConnectUsingSettings and to get into a PUN room easily.</summary>
|
||||
/// <remarks>A custom inspector provides a button to connect in PlayMode, should AutoConnect be false.</remarks>
|
||||
public class ConnectAndJoinRandom : MonoBehaviourPunCallbacks
|
||||
{
|
||||
/// <summary>Connect automatically? If false you can set this to true later on or call ConnectUsingSettings in your own scripts.</summary>
|
||||
public bool AutoConnect = true;
|
||||
|
||||
/// <summary>Used as PhotonNetwork.GameVersion.</summary>
|
||||
public byte Version = 1;
|
||||
|
||||
/// <summary>Max number of players allowed in room. Once full, a new room will be created by the next connection attemping to join.</summary>
|
||||
[Tooltip("The max number of players allowed in room. Once full, a new room will be created by the next connection attemping to join.")]
|
||||
public byte MaxPlayers = 4;
|
||||
|
||||
public int playerTTL = -1;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (this.AutoConnect)
|
||||
{
|
||||
this.ConnectNow();
|
||||
}
|
||||
}
|
||||
|
||||
public void ConnectNow()
|
||||
{
|
||||
Debug.Log("ConnectAndJoinRandom.ConnectNow() will now call: PhotonNetwork.ConnectUsingSettings().");
|
||||
|
||||
|
||||
PhotonNetwork.ConnectUsingSettings();
|
||||
PhotonNetwork.GameVersion = this.Version + "." + SceneManagerHelper.ActiveSceneBuildIndex;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// below, we implement some callbacks of the Photon Realtime API.
|
||||
// Being a MonoBehaviourPunCallbacks means, we can override the few methods which are needed here.
|
||||
|
||||
|
||||
public override void OnConnectedToMaster()
|
||||
{
|
||||
Debug.Log("OnConnectedToMaster() was called by PUN. This client is now connected to Master Server in region [" + PhotonNetwork.CloudRegion +
|
||||
"] and can join a room. Calling: PhotonNetwork.JoinRandomRoom();");
|
||||
PhotonNetwork.JoinRandomRoom();
|
||||
}
|
||||
|
||||
public override void OnJoinedLobby()
|
||||
{
|
||||
Debug.Log("OnJoinedLobby(). This client is now connected to Relay in region [" + PhotonNetwork.CloudRegion + "]. This script now calls: PhotonNetwork.JoinRandomRoom();");
|
||||
PhotonNetwork.JoinRandomRoom();
|
||||
}
|
||||
|
||||
public override void OnJoinRandomFailed(short returnCode, string message)
|
||||
{
|
||||
Debug.Log("OnJoinRandomFailed() was called by PUN. No random room available in region [" + PhotonNetwork.CloudRegion + "], so we create one. Calling: PhotonNetwork.CreateRoom(null, new RoomOptions() {maxPlayers = 4}, null);");
|
||||
|
||||
RoomOptions roomOptions = new RoomOptions() { MaxPlayers = this.MaxPlayers };
|
||||
if (playerTTL >= 0)
|
||||
roomOptions.PlayerTtl = playerTTL;
|
||||
|
||||
PhotonNetwork.CreateRoom(null, roomOptions, null);
|
||||
}
|
||||
|
||||
// the following methods are implemented to give you some context. re-implement them as needed.
|
||||
public override void OnDisconnected(DisconnectCause cause)
|
||||
{
|
||||
Debug.Log("OnDisconnected(" + cause + ")");
|
||||
}
|
||||
|
||||
public override void OnJoinedRoom()
|
||||
{
|
||||
Debug.Log("OnJoinedRoom() called by PUN. Now this client is in a room in region [" + PhotonNetwork.CloudRegion + "]. Game is now running.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#if UNITY_EDITOR
|
||||
//[CanEditMultipleObjects]
|
||||
//[CustomEditor(typeof(ConnectAndJoinRandom), true)]
|
||||
//public class ConnectAndJoinRandomInspector : Editor
|
||||
//{
|
||||
// void OnEnable() { EditorApplication.update += Update; }
|
||||
// void OnDisable() { EditorApplication.update -= Update; }
|
||||
|
||||
// bool isConnectedCache = false;
|
||||
|
||||
// void Update()
|
||||
// {
|
||||
// if (this.isConnectedCache != PhotonNetwork.IsConnected)
|
||||
// {
|
||||
// this.Repaint();
|
||||
// }
|
||||
// }
|
||||
|
||||
// public override void OnInspectorGUI()
|
||||
// {
|
||||
// this.isConnectedCache = !PhotonNetwork.IsConnected;
|
||||
|
||||
|
||||
// this.DrawDefaultInspector(); // Draw the normal inspector
|
||||
|
||||
// if (Application.isPlaying && !PhotonNetwork.IsConnected)
|
||||
// {
|
||||
// if (GUILayout.Button("Connect"))
|
||||
// {
|
||||
// ((ConnectAndJoinRandom)this.target).ConnectNow();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//#endif
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c1b84a427010e0469ce0df07ab64dbc
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
@ -0,0 +1,111 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="OnJoinedInstantiate.cs" company="Exit Games GmbH">
|
||||
// Part of: Photon Unity Utilities,
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Very basic component to move a GameObject by WASD and Space.
|
||||
// </summary>
|
||||
// <remarks>
|
||||
// Requires a PhotonView.
|
||||
// Disables itself on GameObjects that are not owned on Start.
|
||||
//
|
||||
// Speed affects movement-speed.
|
||||
// JumpForce defines how high the object "jumps".
|
||||
// JumpTimeout defines after how many seconds you can jump again.
|
||||
// </remarks>
|
||||
// <author>developer@exitgames.com</author>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
using Photon.Pun;
|
||||
using Photon.Realtime;
|
||||
|
||||
namespace Photon.Pun.UtilityScripts
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Very basic component to move a GameObject by WASD and Space.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Requires a PhotonView.
|
||||
/// Disables itself on GameObjects that are not owned on Start.
|
||||
///
|
||||
/// Speed affects movement-speed.
|
||||
/// JumpForce defines how high the object "jumps".
|
||||
/// JumpTimeout defines after how many seconds you can jump again.
|
||||
/// </remarks>
|
||||
[RequireComponent(typeof(PhotonView))]
|
||||
public class MoveByKeys : Photon.Pun.MonoBehaviourPun
|
||||
{
|
||||
public float Speed = 10f;
|
||||
public float JumpForce = 200f;
|
||||
public float JumpTimeout = 0.5f;
|
||||
|
||||
private bool isSprite;
|
||||
private float jumpingTime;
|
||||
private Rigidbody body;
|
||||
private Rigidbody2D body2d;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
//enabled = photonView.isMine;
|
||||
this.isSprite = (GetComponent<SpriteRenderer>() != null);
|
||||
|
||||
this.body2d = GetComponent<Rigidbody2D>();
|
||||
this.body = GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
|
||||
// Update is called once per frame
|
||||
public void FixedUpdate()
|
||||
{
|
||||
if (!photonView.IsMine)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Input.GetAxisRaw("Horizontal") < -0.1f) || (Input.GetAxisRaw("Horizontal") > 0.1f))
|
||||
{
|
||||
transform.position += Vector3.right * (Speed * Time.deltaTime) * Input.GetAxisRaw("Horizontal");
|
||||
}
|
||||
|
||||
// jumping has a simple "cooldown" time but you could also jump in the air
|
||||
if (this.jumpingTime <= 0.0f)
|
||||
{
|
||||
if (this.body != null || this.body2d != null)
|
||||
{
|
||||
// obj has a Rigidbody and can jump (AddForce)
|
||||
if (Input.GetKey(KeyCode.Space))
|
||||
{
|
||||
this.jumpingTime = this.JumpTimeout;
|
||||
|
||||
Vector2 jump = Vector2.up * this.JumpForce;
|
||||
if (this.body2d != null)
|
||||
{
|
||||
this.body2d.AddForce(jump);
|
||||
}
|
||||
else if (this.body != null)
|
||||
{
|
||||
this.body.AddForce(jump);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.jumpingTime -= Time.deltaTime;
|
||||
}
|
||||
|
||||
// 2d objects can't be moved in 3d "forward"
|
||||
if (!this.isSprite)
|
||||
{
|
||||
if ((Input.GetAxisRaw("Vertical") < -0.1f) || (Input.GetAxisRaw("Vertical") > 0.1f))
|
||||
{
|
||||
transform.position += Vector3.forward * (Speed * Time.deltaTime) * Input.GetAxisRaw("Vertical");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99b4daedc5e674a429acdf1e77da6a55
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
@ -0,0 +1,72 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="OnClickDestroy.cs" company="Exit Games GmbH">
|
||||
// Part of: Photon Unity Utilities
|
||||
// </copyright>
|
||||
// <summary>A compact script for prototyping.</summary>
|
||||
// <author>developer@exitgames.com</author>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace Photon.Pun.UtilityScripts
|
||||
{
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
/// <summary>
|
||||
/// Destroys the networked GameObject either by PhotonNetwork.Destroy or by sending an RPC which calls Object.Destroy().
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Using an RPC to Destroy a GameObject is typically a bad idea.
|
||||
/// It allows any player to Destroy a GameObject and may cause errors.
|
||||
///
|
||||
/// A client has to clean up the server's event-cache, which contains events for Instantiate and
|
||||
/// buffered RPCs related to the GO.
|
||||
///
|
||||
/// A buffered RPC gets cleaned up when the sending player leaves the room, so players joining later
|
||||
/// won't get those buffered RPCs. This in turn, may mean they don't destroy the GO due to coming later.
|
||||
///
|
||||
/// Vice versa, a GameObject Instantiate might get cleaned up when the creating player leaves a room.
|
||||
/// This way, the GameObject that a RPC targets might become lost.
|
||||
///
|
||||
/// It makes sense to test those cases. Many are not breaking errors and you just have to be aware of them.
|
||||
///
|
||||
///
|
||||
/// Gets OnClick() calls by Unity's IPointerClickHandler. Needs a PhysicsRaycaster on the camera.
|
||||
/// See: https://docs.unity3d.com/ScriptReference/EventSystems.IPointerClickHandler.html
|
||||
/// </remarks>
|
||||
public class OnClickDestroy : MonoBehaviourPun, IPointerClickHandler
|
||||
{
|
||||
public PointerEventData.InputButton Button;
|
||||
public KeyCode ModifierKey;
|
||||
|
||||
public bool DestroyByRpc;
|
||||
|
||||
|
||||
void IPointerClickHandler.OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (!PhotonNetwork.InRoom || (this.ModifierKey != KeyCode.None && !Input.GetKey(this.ModifierKey)) || eventData.button != this.Button )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (this.DestroyByRpc)
|
||||
{
|
||||
this.photonView.RPC("DestroyRpc", RpcTarget.AllBuffered);
|
||||
}
|
||||
else
|
||||
{
|
||||
PhotonNetwork.Destroy(this.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[PunRPC]
|
||||
public IEnumerator DestroyRpc()
|
||||
{
|
||||
Destroy(this.gameObject);
|
||||
yield return 0; // if you allow 1 frame to pass, the object's OnDestroy() method gets called and cleans up references.
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9dab7328ba500e944a99d62065fba6c0
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
@ -0,0 +1,56 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="OnClickInstantiate.cs" company="Exit Games GmbH">
|
||||
// Part of: Photon Unity Utilities
|
||||
// </copyright>
|
||||
// <summary>A compact script for prototyping.</summary>
|
||||
// <author>developer@exitgames.com</author>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace Photon.Pun.UtilityScripts
|
||||
{
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a networked GameObject on click.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Gets OnClick() calls by Unity's IPointerClickHandler. Needs a PhysicsRaycaster on the camera.
|
||||
/// See: https://docs.unity3d.com/ScriptReference/EventSystems.IPointerClickHandler.html
|
||||
/// </remarks>
|
||||
public class OnClickInstantiate : MonoBehaviour, IPointerClickHandler
|
||||
{
|
||||
public enum InstantiateOption { Mine, Scene }
|
||||
|
||||
|
||||
public PointerEventData.InputButton Button;
|
||||
public KeyCode ModifierKey;
|
||||
|
||||
public GameObject Prefab;
|
||||
|
||||
[SerializeField]
|
||||
private InstantiateOption InstantiateType = InstantiateOption.Mine;
|
||||
|
||||
|
||||
void IPointerClickHandler.OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (!PhotonNetwork.InRoom || (this.ModifierKey != KeyCode.None && !Input.GetKey(this.ModifierKey)) || eventData.button != this.Button)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch (this.InstantiateType)
|
||||
{
|
||||
case InstantiateOption.Mine:
|
||||
PhotonNetwork.Instantiate(this.Prefab.name, eventData.pointerCurrentRaycast.worldPosition + new Vector3(0, 0.5f, 0), Quaternion.identity, 0);
|
||||
break;
|
||||
case InstantiateOption.Scene:
|
||||
PhotonNetwork.InstantiateRoomObject(this.Prefab.name, eventData.pointerCurrentRaycast.worldPosition + new Vector3(0, 0.5f, 0), Quaternion.identity, 0, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b79a9b62449de940a073364858c3f9b
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
@ -0,0 +1,89 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="OnClickInstantiate.cs" company="Exit Games GmbH">
|
||||
// Part of: Photon Unity Utilities
|
||||
// </copyright>
|
||||
// <summary>A compact script for prototyping.</summary>
|
||||
// <author>developer@exitgames.com</author>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace Photon.Pun.UtilityScripts
|
||||
{
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This component will instantiate a network GameObject when in a room and the user click on that component's GameObject.
|
||||
/// Uses PhysicsRaycaster for positioning.
|
||||
/// </summary>
|
||||
public class OnClickRpc : MonoBehaviourPun, IPointerClickHandler
|
||||
{
|
||||
public PointerEventData.InputButton Button;
|
||||
public KeyCode ModifierKey;
|
||||
|
||||
public RpcTarget Target;
|
||||
|
||||
void IPointerClickHandler.OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (!PhotonNetwork.InRoom || (this.ModifierKey != KeyCode.None && !Input.GetKey(this.ModifierKey)) || eventData.button != this.Button)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.photonView.RPC("ClickRpc", this.Target);
|
||||
}
|
||||
|
||||
|
||||
#region RPC Implementation
|
||||
|
||||
private Material originalMaterial;
|
||||
private Color originalColor;
|
||||
private bool isFlashing;
|
||||
|
||||
[PunRPC]
|
||||
public void ClickRpc()
|
||||
{
|
||||
//Debug.Log("ClickRpc Called");
|
||||
this.StartCoroutine(this.ClickFlash());
|
||||
}
|
||||
|
||||
public IEnumerator ClickFlash()
|
||||
{
|
||||
if (isFlashing)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
isFlashing = true;
|
||||
|
||||
this.originalMaterial = GetComponent<Renderer>().material;
|
||||
if (!this.originalMaterial.HasProperty("_EmissionColor"))
|
||||
{
|
||||
Debug.LogWarning("Doesn't have emission, can't flash " + gameObject);
|
||||
yield break;
|
||||
}
|
||||
|
||||
bool wasEmissive = this.originalMaterial.IsKeywordEnabled("_EMISSION");
|
||||
this.originalMaterial.EnableKeyword("_EMISSION");
|
||||
|
||||
this.originalColor = this.originalMaterial.GetColor("_EmissionColor");
|
||||
this.originalMaterial.SetColor("_EmissionColor", Color.white);
|
||||
|
||||
for (float f = 0.0f; f <= 1.0f; f += 0.08f)
|
||||
{
|
||||
Color lerped = Color.Lerp(Color.white, this.originalColor, f);
|
||||
this.originalMaterial.SetColor("_EmissionColor", lerped);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
this.originalMaterial.SetColor("_EmissionColor", this.originalColor);
|
||||
if (!wasEmissive) this.originalMaterial.DisableKeyword("_EMISSION");
|
||||
isFlashing = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2cd0ed7420882554fa146aab6aeb2e80
|
||||
timeCreated: 1536748184
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,32 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="OnJoinedInstantiate.cs" company="Exit Games GmbH">
|
||||
// Part of: Photon Unity Utilities,
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// This component will quit the application when escape key is pressed
|
||||
// </summary>
|
||||
// <author>developer@exitgames.com</author>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Photon.Pun.UtilityScripts
|
||||
{
|
||||
/// <summary>
|
||||
/// This component will quit the application when escape key is pressed
|
||||
/// </summary>
|
||||
public class OnEscapeQuit : MonoBehaviour
|
||||
{
|
||||
[Conditional("UNITY_ANDROID"), Conditional("UNITY_IOS")]
|
||||
public void Update()
|
||||
{
|
||||
// "back" button of phone equals "Escape". quit app if that's pressed
|
||||
if (Input.GetKeyDown(KeyCode.Escape))
|
||||
{
|
||||
Application.Quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fbabafd914a48f4eb6108d8d8f43d29
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
@ -0,0 +1,450 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="OnJoinedInstantiate.cs" company="Exit Games GmbH">
|
||||
// Part of: Photon Unity Utilities,
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// This component will instantiate a network GameObject when a room is joined
|
||||
// </summary>
|
||||
// <author>developer@exitgames.com</author>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
using Photon.Realtime;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Photon.Pun.UtilityScripts
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This component will instantiate a network GameObject when a room is joined
|
||||
/// </summary>
|
||||
public class OnJoinedInstantiate : MonoBehaviour
|
||||
, IMatchmakingCallbacks
|
||||
{
|
||||
public enum SpawnSequence { Connection, Random, RoundRobin }
|
||||
|
||||
#region Inspector Items
|
||||
|
||||
// Old field, only here for backwards compat. Value copies over to SpawnPoints in OnValidate
|
||||
[HideInInspector] private Transform SpawnPosition;
|
||||
|
||||
[HideInInspector] public SpawnSequence Sequence = SpawnSequence.Connection;
|
||||
|
||||
[HideInInspector] public List<Transform> SpawnPoints = new List<Transform>(1) { null };
|
||||
|
||||
[Tooltip("Add a random variance to a spawn point position. GetRandomOffset() can be overridden with your own method for producing offsets.")]
|
||||
[HideInInspector] public bool UseRandomOffset = true;
|
||||
|
||||
[Tooltip("Radius of the RandomOffset.")]
|
||||
[FormerlySerializedAs("PositionOffset")]
|
||||
[HideInInspector] public float RandomOffset = 2.0f;
|
||||
|
||||
[Tooltip("Disables the Y axis of RandomOffset. The Y value of the spawn point will be used.")]
|
||||
[HideInInspector] public bool ClampY = true;
|
||||
|
||||
[HideInInspector] public List<GameObject> PrefabsToInstantiate = new List<GameObject>(1) { null }; // set in inspector
|
||||
|
||||
[FormerlySerializedAs("autoSpawnObjects")]
|
||||
[HideInInspector] public bool AutoSpawnObjects = true;
|
||||
|
||||
#endregion
|
||||
|
||||
// Record of spawned objects, used for Despawn All
|
||||
public Stack<GameObject> SpawnedObjects = new Stack<GameObject>();
|
||||
protected int spawnedAsActorId;
|
||||
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
protected void OnValidate()
|
||||
{
|
||||
/// Check the prefab to make sure it is the actual resource, and not a scene object or other instance.
|
||||
if (PrefabsToInstantiate != null)
|
||||
for (int i = 0; i < PrefabsToInstantiate.Count; ++i)
|
||||
{
|
||||
var prefab = PrefabsToInstantiate[i];
|
||||
if (prefab)
|
||||
PrefabsToInstantiate[i] = ValidatePrefab(prefab);
|
||||
}
|
||||
|
||||
/// Move any values from old SpawnPosition field to new SpawnPoints
|
||||
if (SpawnPosition)
|
||||
{
|
||||
if (SpawnPoints == null)
|
||||
SpawnPoints = new List<Transform>();
|
||||
|
||||
SpawnPoints.Add(SpawnPosition);
|
||||
SpawnPosition = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate, and if valid add this prefab to the first null element of the list, or create a new element. Returns true if the object was added.
|
||||
/// </summary>
|
||||
/// <param name="prefab"></param>
|
||||
public bool AddPrefabToList(GameObject prefab)
|
||||
{
|
||||
var validated = ValidatePrefab(prefab);
|
||||
if (validated)
|
||||
{
|
||||
// Don't add to list if this prefab already is on the list
|
||||
if (PrefabsToInstantiate.Contains(validated))
|
||||
return false;
|
||||
|
||||
// First try to use any null array slots to keep things tidy
|
||||
if (PrefabsToInstantiate.Contains(null))
|
||||
PrefabsToInstantiate[PrefabsToInstantiate.IndexOf(null)] = validated;
|
||||
// Otherwise, just add this prefab.
|
||||
else
|
||||
PrefabsToInstantiate.Add(validated);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the supplied GameObject is an instance of a prefab, or the actual source Asset,
|
||||
/// and returns a best guess at the actual resource the dev intended to use.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected static GameObject ValidatePrefab(GameObject unvalidated)
|
||||
{
|
||||
if (unvalidated == null)
|
||||
return null;
|
||||
|
||||
if (!unvalidated.GetComponent<PhotonView>())
|
||||
return null;
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
|
||||
GameObject validated = null;
|
||||
|
||||
if (unvalidated != null)
|
||||
{
|
||||
|
||||
if (PrefabUtility.IsPartOfPrefabAsset(unvalidated))
|
||||
return unvalidated;
|
||||
|
||||
var prefabStatus = PrefabUtility.GetPrefabInstanceStatus(unvalidated);
|
||||
var isValidPrefab = prefabStatus == PrefabInstanceStatus.Connected || prefabStatus == PrefabInstanceStatus.Disconnected;
|
||||
|
||||
if (isValidPrefab)
|
||||
validated = PrefabUtility.GetCorrespondingObjectFromSource(unvalidated) as GameObject;
|
||||
else
|
||||
return null;
|
||||
|
||||
if (!PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(validated).Contains("/Resources"))
|
||||
Debug.LogWarning("Player Prefab needs to be a Prefab in a Resource folder.");
|
||||
}
|
||||
#else
|
||||
GameObject validated = unvalidated;
|
||||
|
||||
if (unvalidated != null && PrefabUtility.GetPrefabType(unvalidated) != PrefabType.Prefab)
|
||||
validated = PrefabUtility.GetPrefabParent(unvalidated) as GameObject;
|
||||
#endif
|
||||
return validated;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
PhotonNetwork.AddCallbackTarget(this);
|
||||
}
|
||||
|
||||
public virtual void OnDisable()
|
||||
{
|
||||
PhotonNetwork.RemoveCallbackTarget(this);
|
||||
}
|
||||
|
||||
|
||||
public virtual void OnJoinedRoom()
|
||||
{
|
||||
// Only AutoSpawn if we are a new ActorId. Rejoining should reproduce the objects by server instantiation.
|
||||
if (AutoSpawnObjects && !PhotonNetwork.LocalPlayer.HasRejoined)
|
||||
{
|
||||
SpawnObjects();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SpawnObjects()
|
||||
{
|
||||
if (this.PrefabsToInstantiate != null)
|
||||
{
|
||||
foreach (GameObject o in this.PrefabsToInstantiate)
|
||||
{
|
||||
if (o == null)
|
||||
continue;
|
||||
#if UNITY_EDITOR
|
||||
Debug.Log("Auto-Instantiating: " + o.name);
|
||||
#endif
|
||||
Vector3 spawnPos; Quaternion spawnRot;
|
||||
GetSpawnPoint(out spawnPos, out spawnRot);
|
||||
|
||||
|
||||
var newobj = PhotonNetwork.Instantiate(o.name, spawnPos, spawnRot, 0);
|
||||
SpawnedObjects.Push(newobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroy all objects that have been spawned by this component for this client.
|
||||
/// </summary>
|
||||
/// <param name="localOnly">Use Object.Destroy rather than PhotonNetwork.Destroy.</param>
|
||||
public virtual void DespawnObjects(bool localOnly)
|
||||
{
|
||||
|
||||
while (SpawnedObjects.Count > 0)
|
||||
{
|
||||
var go = SpawnedObjects.Pop();
|
||||
if (go)
|
||||
{
|
||||
if (localOnly)
|
||||
Object.Destroy(go);
|
||||
else
|
||||
PhotonNetwork.Destroy(go);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnFriendListUpdate(List<FriendInfo> friendList) { }
|
||||
public virtual void OnCreatedRoom() { }
|
||||
public virtual void OnCreateRoomFailed(short returnCode, string message) { }
|
||||
public virtual void OnJoinRoomFailed(short returnCode, string message) { }
|
||||
public virtual void OnJoinRandomFailed(short returnCode, string message) { }
|
||||
public virtual void OnLeftRoom() { }
|
||||
|
||||
protected int lastUsedSpawnPointIndex = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next SpawnPoint from the list using the SpawnSequence, and applies RandomOffset (if used) to the transform matrix.
|
||||
/// Override this method with any custom code for coming up with a spawn location. This method is used by AutoSpawn.
|
||||
/// </summary>
|
||||
public virtual void GetSpawnPoint(out Vector3 spawnPos, out Quaternion spawnRot)
|
||||
{
|
||||
|
||||
// Fetch a point using the Sequence method indicated
|
||||
Transform point = GetSpawnPoint();
|
||||
|
||||
if (point != null)
|
||||
{
|
||||
spawnPos = point.position;
|
||||
spawnRot = point.rotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
spawnPos = new Vector3(0, 0, 0);
|
||||
spawnRot = new Quaternion(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
if (UseRandomOffset)
|
||||
{
|
||||
Random.InitState((int)(Time.time * 10000));
|
||||
spawnPos += GetRandomOffset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the transform of the next SpawnPoint from the list, selected using the SpawnSequence setting.
|
||||
/// RandomOffset is not applied, only the transform of the SpawnPoint is returned.
|
||||
/// Override this method to change how Spawn Point transform is selected. Return the transform you want to use as a spawn point.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual Transform GetSpawnPoint()
|
||||
{
|
||||
// Fetch a point using the Sequence method indicated
|
||||
if (SpawnPoints == null || SpawnPoints.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (Sequence)
|
||||
{
|
||||
case SpawnSequence.Connection:
|
||||
{
|
||||
int id = PhotonNetwork.LocalPlayer.ActorNumber;
|
||||
return SpawnPoints[(id == -1) ? 0 : id % SpawnPoints.Count];
|
||||
}
|
||||
|
||||
case SpawnSequence.RoundRobin:
|
||||
{
|
||||
lastUsedSpawnPointIndex++;
|
||||
if (lastUsedSpawnPointIndex >= SpawnPoints.Count)
|
||||
lastUsedSpawnPointIndex = 0;
|
||||
|
||||
/// Use Vector.Zero and Quaternion.Identity if we are dealing with no or a null spawnpoint.
|
||||
return SpawnPoints == null || SpawnPoints.Count == 0 ? null : SpawnPoints[lastUsedSpawnPointIndex];
|
||||
}
|
||||
|
||||
case SpawnSequence.Random:
|
||||
{
|
||||
return SpawnPoints[Random.Range(0, SpawnPoints.Count)];
|
||||
}
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When UseRandomeOffset is enabled, this method is called to produce a Vector3 offset. The default implementation clamps the Y value to zero. You may override this with your own implementation.
|
||||
/// </summary>
|
||||
protected virtual Vector3 GetRandomOffset()
|
||||
{
|
||||
Vector3 random = Random.insideUnitSphere;
|
||||
if (ClampY)
|
||||
random.y = 0;
|
||||
return RandomOffset * random.normalized;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
[CustomEditor(typeof(OnJoinedInstantiate), true)]
|
||||
[CanEditMultipleObjects]
|
||||
public class OnJoinedInstantiateEditor : Editor
|
||||
{
|
||||
|
||||
SerializedProperty SpawnPoints, PrefabsToInstantiate, UseRandomOffset, ClampY, RandomOffset, Sequence, autoSpawnObjects;
|
||||
GUIStyle fieldBox;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
SpawnPoints = serializedObject.FindProperty("SpawnPoints");
|
||||
PrefabsToInstantiate = serializedObject.FindProperty("PrefabsToInstantiate");
|
||||
UseRandomOffset = serializedObject.FindProperty("UseRandomOffset");
|
||||
ClampY = serializedObject.FindProperty("ClampY");
|
||||
RandomOffset = serializedObject.FindProperty("RandomOffset");
|
||||
Sequence = serializedObject.FindProperty("Sequence");
|
||||
|
||||
autoSpawnObjects = serializedObject.FindProperty("AutoSpawnObjects");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
const int PAD = 6;
|
||||
|
||||
if (fieldBox == null)
|
||||
fieldBox = new GUIStyle("HelpBox") { padding = new RectOffset(PAD, PAD, PAD, PAD) };
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
EditableReferenceList(PrefabsToInstantiate, new GUIContent(PrefabsToInstantiate.displayName, PrefabsToInstantiate.tooltip), fieldBox);
|
||||
|
||||
EditableReferenceList(SpawnPoints, new GUIContent(SpawnPoints.displayName, SpawnPoints.tooltip), fieldBox);
|
||||
|
||||
/// Spawn Pattern
|
||||
EditorGUILayout.BeginVertical(fieldBox);
|
||||
EditorGUILayout.PropertyField(Sequence);
|
||||
EditorGUILayout.PropertyField(UseRandomOffset);
|
||||
if (UseRandomOffset.boolValue)
|
||||
{
|
||||
EditorGUILayout.PropertyField(RandomOffset);
|
||||
EditorGUILayout.PropertyField(ClampY);
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
/// Auto/Manual Spawn
|
||||
EditorGUILayout.BeginVertical(fieldBox);
|
||||
EditorGUILayout.PropertyField(autoSpawnObjects);
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a basic rendered list of objects from a SerializedProperty list or array, with Add/Destroy buttons.
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="gc"></param>
|
||||
public void EditableReferenceList(SerializedProperty list, GUIContent gc, GUIStyle style = null)
|
||||
{
|
||||
EditorGUILayout.LabelField(gc);
|
||||
|
||||
if (style == null)
|
||||
style = new GUIStyle("HelpBox") { padding = new RectOffset(6, 6, 6, 6) };
|
||||
|
||||
EditorGUILayout.BeginVertical(style);
|
||||
|
||||
int count = list.arraySize;
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
if (GUI.Button(EditorGUILayout.GetControlRect(GUILayout.MaxWidth(20)), "+", (GUIStyle)"minibutton"))
|
||||
{
|
||||
int newindex = list.arraySize;
|
||||
list.InsertArrayElementAtIndex(0);
|
||||
list.GetArrayElementAtIndex(0).objectReferenceValue = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// List Elements and Delete buttons
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
bool add = (GUI.Button(EditorGUILayout.GetControlRect(GUILayout.MaxWidth(20)), "+", (GUIStyle)"minibutton"));
|
||||
EditorGUILayout.PropertyField(list.GetArrayElementAtIndex(i), GUIContent.none);
|
||||
bool remove = (GUI.Button(EditorGUILayout.GetControlRect(GUILayout.MaxWidth(20)), "x", (GUIStyle)"minibutton"));
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (add)
|
||||
{
|
||||
Add(list, i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (remove)
|
||||
{
|
||||
list.DeleteArrayElementAtIndex(i);
|
||||
//EditorGUILayout.EndHorizontal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.GetControlRect(false, 4);
|
||||
|
||||
if (GUI.Button(EditorGUILayout.GetControlRect(), "Add", (GUIStyle)"minibutton"))
|
||||
Add(list, count);
|
||||
|
||||
}
|
||||
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void Add(SerializedProperty list, int i)
|
||||
{
|
||||
{
|
||||
int newindex = list.arraySize;
|
||||
list.InsertArrayElementAtIndex(i);
|
||||
list.GetArrayElementAtIndex(i).objectReferenceValue = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed3b5dcba7bf9114cb13fc59e0a71f55
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
@ -0,0 +1,24 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="OnStartDelete.cs" company="Exit Games GmbH">
|
||||
// Part of: Photon Unity Utilities,
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// This component will destroy the GameObject it is attached to (in Start()).
|
||||
// </summary>
|
||||
// <author>developer@exitgames.com</author>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Photon.Pun.UtilityScripts
|
||||
{
|
||||
/// <summary>This component will destroy the GameObject it is attached to (in Start()).</summary>
|
||||
public class OnStartDelete : MonoBehaviour
|
||||
{
|
||||
// Use this for initialization
|
||||
private void Start()
|
||||
{
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f8d56a54ae062da4a87516fb994f4e30
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
Reference in New Issue
Block a user