Pascal Serrarens 17741d862a First commit
2022-01-12 10:50:57 +01:00

181 lines
6.7 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Passer {
using Humanoid;
/// <summary>
/// Component for spawning objects
/// </summary>
public class Spawner : SpawnPoint {
/// <summary>
/// The prefab which will be spawned
/// </summary>
public GameObject prefab;
/// <summary>
/// The available SpawnPoints.
/// </summary>
/// When the list is empty, the scene will be searched for available spawn points when it becomes enabled.
/// If no spawn points can be found, this transform will be used as a SpawnPoint
public SpawnPoint[] spawnPoints;
/// <summary>
/// The SpawnMethod to use for spawning the humanoids.
/// </summary>
public SpawnMethod spawnMethod;
/// <summary>
/// Spawning methods.
/// </summary>
public enum SpawnMethod {
SinglePlayer, ///< Only one humanoid will be spawned. It will be located at the first SpawnPoint.
Random, ///< A SpawnPoint is chosen randomly.
RoundRobin ///< Spawn points are chosen in round robin manner.
}
protected int spawnIndex = 0;
/// <summary>
/// Spawn an object when the scene starts
/// </summary>
public bool spawnAtStart;
/// <summary>
/// Will spawn only one object for this prefab
/// </summary>
/// When spawn is called a second time for the same prefab, the original spawned object
/// will be teleported to the new spawn point
public bool singleInstance;
// used for uniqueObject
private GameObject lastPrefabInstance;
protected virtual void OnEnable() {
if (spawnPoints != null && spawnPoints.Length > 0)
return;
spawnPoints = FindObjectsOfType<SpawnPoint>();
if (spawnPoints.Length == 0) {
SpawnPoint thisSpawnPoint = this.gameObject.AddComponent<SpawnPoint>();
spawnPoints = new SpawnPoint[] { thisSpawnPoint };
}
}
protected virtual void Start() {
if (spawnAtStart)
SpawnObject();
}
/// <summary>
/// Spawn one GameObject using the Spawner settings.
/// </summary>
/// <returns>The instantiated GameObject. Will be null when the prefab could not be instantiated.</returns>
public virtual GameObject SpawnObject() {
if (prefab == null)
return null;
return Instantiate(prefab, transform.position, transform.rotation);
}
public void DoSpawn(GameObject prefab) {
Spawn(prefab);
}
/// <summary>
/// Spawn a GameObject
/// </summary>
/// <param name="prefab">The GameObject prefab to spawn.</param>
/// <returns>The instantiated GameObject. Will be null when the prefab could not be spawned.</returns>
public virtual GameObject Spawn(GameObject prefab) {
return Spawn(prefab, spawnPoints, spawnMethod);
}
/// <summary>
/// Spawn a GameObject
/// </summary>
/// <param name="prefab">The GameObject prefab to spawn.</param>
/// <param name="spawnPoints">The array of possible spawn points.</param>
/// <param name="spawnMethod">The SpawnMethod to use for spawning.</param>
/// <returns>The instantiated GameObject. Will be null when the prefab could not be spawned.</returns>
public virtual GameObject Spawn(GameObject prefab, SpawnPoint[] spawnPoints, SpawnMethod spawnMethod = SpawnMethod.RoundRobin) {
if (prefab == null)
return null;
GameObject newGameObject = null;
SpawnPoint spawnPoint = ChooseSpawnPoint(spawnPoints, spawnMethod);
if (spawnPoint == null)
Debug.Log("Could not find an empty SpawnPoint");
else {
if (singleInstance && lastPrefabInstance != null) {
lastPrefabInstance.transform.position = spawnPoint.transform.position;
lastPrefabInstance.transform.rotation = spawnPoint.transform.rotation;
newGameObject = lastPrefabInstance;
}
else {
//NetworkedTransform networkedTransform = prefab.GetComponent<NetworkedTransform>();
//if (networkedTransform != null)
// newGameObject = NetworkedTransform.Instantiate(prefab, spawnPoint.transform.position, spawnPoint.transform.rotation);
//else
// newGameObject = Instantiate(prefab, spawnPoint.transform.position, spawnPoint.transform.rotation);
newGameObject = Spawn(prefab, spawnPoint.transform.position, spawnPoint.transform.rotation);
lastPrefabInstance = newGameObject;
}
}
return newGameObject;
}
public static GameObject Spawn(GameObject prefab, Vector3 position, Quaternion rotation) {
GameObject newGameObject;
#if hNW_PHOTON
NetworkedTransform networkedTransform = prefab.GetComponent<NetworkedTransform>();
if (networkedTransform != null)
newGameObject = NetworkedTransform.Instantiate(prefab, position, rotation);
else
#endif
newGameObject = Instantiate(prefab, position, rotation);
return newGameObject;
}
protected SpawnPoint ChooseSpawnPoint(SpawnPoint[] spawnPoints, SpawnMethod spawnMethod) {
if (spawnPoints == null)
return null;
List<SpawnPoint> availablePoints = new List<SpawnPoint>();
foreach (SpawnPoint spawnPoint in spawnPoints) {
if (spawnPoint is HumanoidSpawnPoint) {
if (((HumanoidSpawnPoint)spawnPoint).isFree)
availablePoints.Add(spawnPoint);
}
else
availablePoints.Add(spawnPoint);
}
int spawnPointIndex = GetSpawnPointIndex(availablePoints.Count, spawnMethod);
if (spawnPointIndex == -1)
return null;
return availablePoints[spawnPointIndex];
}
private int GetSpawnPointIndex(int nSpawnPoints, SpawnMethod spawnMethod) {
if (nSpawnPoints <= 0)
return -1;
switch (spawnMethod) {
case SpawnMethod.RoundRobin:
return spawnIndex++ & nSpawnPoints;
case SpawnMethod.Random:
default:
return Random.Range(0, nSpawnPoints - 1);
}
}
}
}