/// <summary> /// Spawn the specified prefab, syncing it to all clients /// </summary> /// <param name="prefab">Prefab to spawn an instance of. This is intended to be made to work for pretty much any prefab, but don't /// be surprised if it doesn't as there are LOTS of prefabs in the game which all have unique behavior for how they should spawn. If you are trying /// to instantiate something and it isn't properly setting itself up, check to make sure each component that needs to set something up has /// properly implemented necessary lifecycle methods.</param> /// <param name="destination">destination to spawn at</param> /// <param name="count">number of instances to spawn, defaults to 1</param> /// <param name="scatterRadius">radius to scatter the spawned instances by from their spawn position. Defaults to /// null (no scatter).</param> /// <returns>the newly created GameObject</returns> public static SpawnResult ServerPrefab(GameObject prefab, SpawnDestination destination, int count = 1, float?scatterRadius = null) { return(Server( SpawnInfo.Spawnable( SpawnablePrefab.For(prefab), destination, count, scatterRadius))); }
/// <summary> /// Spawn the specified prefab locally, for this client only. /// </summary> /// <param name="prefabName">name of prefab to spawn an instance of. This is intended to be made to work for pretty much any prefab, but don't /// be surprised if it doesn't as there are LOTS of prefabs in the game which all have unique behavior for how they should spawn. If you are trying /// to instantiate something and it isn't properly setting itself up, check to make sure each component that needs to set something up has /// properly implemented necessary lifecycle methods.</param> /// <param name="worldPosition">world position to appear at. Defaults to HiddenPos (hidden / invisible)</param> /// <param name="localRotation">local rotation to spawn with, defaults to Quaternion.identity</param> /// <param name="parent">Parent to spawn under, defaults to no parent. Most things /// should always be spawned under the Objects transform in their matrix. Many objects (due to RegisterTile) /// usually take care of properly parenting themselves when spawned so in many cases you can leave it null.</param> /// <param name="count">number of instances to spawn, defaults to 1</param> /// <param name="scatterRadius">radius to scatter the spawned instances by from their spawn position. Defaults to /// null (no scatter).</param> /// <returns>the newly created GameObject</returns> public static SpawnResult ClientPrefab(string prefabName, Vector3?worldPosition = null, Transform parent = null, Quaternion?localRotation = null, int count = 1, float?scatterRadius = null) { return(Client( SpawnInfo.Spawnable( SpawnablePrefab.For(prefabName), SpawnDestination.At(worldPosition, parent, localRotation), count, scatterRadius))); }
/// <summary> /// Spawn the specified prefab, syncing it to all clients /// </summary> /// <param name="prefabName">name of prefab to spawn an instance of. This is intended to be made to work for pretty much any prefab, but don't /// be surprised if it doesn't as there are LOTS of prefabs in the game which all have unique behavior for how they should spawn. If you are trying /// to instantiate something and it isn't properly setting itself up, check to make sure each component that needs to set something up has /// properly implemented necessary lifecycle methods.</param> /// <param name="worldPosition">world position to appear at. Defaults to HiddenPos (hidden / invisible)</param> /// <param name="localRotation">local rotation to spawn with, defaults to Quaternion.identity</param> /// <param name="parent">Parent to spawn under, defaults to no parent. Most things /// should always be spawned under the Objects transform in their matrix. Many objects (due to RegisterTile) /// usually take care of properly parenting themselves when spawned so in many cases you can leave it null.</param> /// <param name="count">number of instances to spawn, defaults to 1</param> /// <param name="scatterRadius">radius to scatter the spawned instances by from their spawn position. Defaults to /// null (no scatter).</param> /// <param name="cancelIfImpassable">If true, the spawn will be cancelled if the location being spawned into is totally impassable.</param> /// <returns>the newly created GameObject</returns> public static SpawnResult ServerPrefab(string prefabName, Vector3?worldPosition = null, Transform parent = null, Quaternion?localRotation = null, int count = 1, float?scatterRadius = null, bool cancelIfImpassable = false) { return(Server( SpawnInfo.Spawnable( SpawnablePrefab.For(prefabName), SpawnDestination.At(worldPosition, parent, localRotation, cancelIfImpassable), count, scatterRadius))); }
/// <summary> /// Spawn the specified prefab, syncing it to all clients /// </summary> /// <param name="prefab">Prefab to spawn an instance of. This is intended to be made to work for pretty much any prefab, but don't /// be surprised if it doesn't as there are LOTS of prefabs in the game which all have unique behavior for how they should spawn. If you are trying /// to instantiate something and it isn't properly setting itself up, check to make sure each component that needs to set something up has /// properly implemented necessary lifecycle methods.</param> /// <param name="worldPosition">world position to appear at. Defaults to HiddenPos (hidden / invisible)</param> /// <param name="localRotation">local rotation to spawn with, defaults to Quaternion.identity</param> /// <param name="parent">Parent to spawn under, defaults to no parent. Most things /// should always be spawned under the Objects transform in their matrix. Many objects (due to RegisterTile) /// usually take care of properly parenting themselves when spawned so in many cases you can leave it null.</param> /// <param name="count">number of instances to spawn, defaults to 1</param> /// <param name="scatterRadius">radius to scatter the spawned instances by from their spawn position. Defaults to /// null (no scatter).</param> /// <param name="cancelIfImpassable">If true, the spawn will be cancelled if the location being spawned into is totally impassable.</param> /// <returns>the newly created GameObject</returns> public static SpawnResult ServerPrefab(GameObject prefab, Vector3?worldPosition = null, Transform parent = null, Quaternion?localRotation = null, int count = 1, float?scatterRadius = null, bool cancelIfImpassable = false, bool spawnItems = true, bool AutoOnSpawnServerHook = true) { return(Server( SpawnInfo.Spawnable( SpawnablePrefab.For(prefab), SpawnDestination.At(worldPosition, parent, localRotation, cancelIfImpassable), count, scatterRadius, spawnItems: spawnItems), AutoOnSpawnServerHook)); }
/// <summary> /// Special type of spawn, performed on each object mapped in the scene once the scene is done loading. /// </summary> /// <param name="mappedObject">object which was mapped into the scene.</param> /// <returns></returns> public static SpawnInfo Mapped(GameObject mappedObject) { var destination = SpawnDestination.At(mappedObject); //assume prefab var prefab = Spawn.DeterminePrefab(mappedObject); var spawnable = SpawnablePrefab.For(prefab); return(new SpawnInfo(SpawnType.Mapped, spawnable, destination, null, 1, null)); }
/// <summary> /// Spawn the specified prefab, syncing it to all clients /// </summary> /// <param name="prefab">Prefab to spawn an instance of. This is intended to be made to work for pretty much any prefab, but don't /// be surprised if it doesn't as there are LOTS of prefabs in the game which all have unique behavior for how they should spawn. If you are trying /// to instantiate something and it isn't properly setting itself up, check to make sure each component that needs to set something up has /// properly implemented necessary lifecycle methods.</param> /// <param name="destination">destination to spawn at</param> /// <param name="count">number of instances to spawn, defaults to 1</param> /// <param name="scatterRadius">radius to scatter the spawned instances by from their spawn position. Defaults to /// null (no scatter).</param> /// <returns>the newly created GameObject</returns> public static SpawnResult ServerPrefab(GameObject prefab, SpawnDestination destination, int count = 1, float?scatterRadius = null, bool mapspawn = false, bool PrePickRandom = false) { return(Server( SpawnInfo.Spawnable( SpawnablePrefab.For(prefab, PrePickRandom), destination, count, scatterRadius, mapspawn: mapspawn))); }
/// <summary> /// Spawn the specified prefab locally, for this client only. /// </summary> /// <param name="prefab">Prefab to spawn an instance of. This is intended to be made to work for pretty much any prefab, but don't /// be surprised if it doesn't as there are LOTS of prefabs in the game which all have unique behavior for how they should spawn. If you are trying /// to instantiate something and it isn't properly setting itself up, check to make sure each component that needs to set something up has /// properly implemented necessary lifecycle methods.</param> /// <param name="worldPosition">world position to appear at. Defaults to HiddenPos (hidden / invisible)</param> /// <param name="localRotation">local rotation to spawn with, defaults to Quaternion.identity</param> /// <param name="parent">Parent to spawn under, defaults to no parent. Most things /// should always be spawned under the Objects transform in their matrix. Many objects (due to RegisterTile) /// usually take care of properly parenting themselves when spawned so in many cases you can leave it null.</param> /// <param name="count">number of instances to spawn, defaults to 1</param> /// <param name="scatterRadius">radius to scatter the spawned instances by from their spawn position. Defaults to /// null (no scatter).</param> /// <returns>the newly created GameObject</returns> public static SpawnResult ClientPrefab(GameObject prefab, Vector3?worldPosition = null, Transform parent = null, Quaternion?localRotation = null, int count = 1, float?scatterRadius = null, bool mapspawn = false) { return(Client( SpawnInfo.Spawnable( SpawnablePrefab.For(prefab), SpawnDestination.At(worldPosition, parent, localRotation), count, scatterRadius, mapspawn: mapspawn))); }
public SpawnablePrefab(SpawnablePrefab copyPrefabs) { this._prefab = copyPrefabs._prefab; this._probability = copyPrefabs._probability; this._height = copyPrefabs._height; this._fixedHeight = copyPrefabs._fixedHeight; this._scale = copyPrefabs._scale; this._scaleRandom = copyPrefabs._scaleRandom; }
static SpawnablePrefab[] CopyPrefabs(SpawnablePrefab[] prefabs) { SpawnablePrefab[] newPrefabs = new SpawnablePrefab[prefabs.Length]; for (int i = 0; i < newPrefabs.Length; i++) { newPrefabs[i] = new SpawnablePrefab(prefabs[i]); } return(newPrefabs); }
private void SpawnPrefab(SpawnablePrefab spawnable) { if (spawnable.SpawnPoint == null) { spawnable.SpawnPoint = _currentWave.GetSpawnPoint(); } var go = Instantiate(spawnable.Prefab, spawnable.SpawnPoint.transform.position, spawnable.SpawnPoint.transform.rotation); spawnable.OnSpawn(go); _activeGameObjects.Add(go); }
// Used to calculate all the different noises for every spawable public void Setup(float[,] parentNoise, int chunkSize, NoiseSettingsData offsetNoiseSettings, Vector2 center, Vector2 offsetNoiseOffset) { if (parentNoise != null) { _noise = Noise.MergeNoise(chunkSize, chunkSize, 1, _noiseSettingsData.NoiseSettingsDataMerge, parentNoise, _noiseMergeType, new Vector2(center.x, -center.y)); } else { _noise = Noise.GenerateNoiseMap(chunkSize, chunkSize, 1, _noiseSettingsData.NoiseSettingsDataMerge, new Vector2(center.x, -center.y)); } _noise = Noise.Clamp(_noise, _noiseSettingsData); _offsetNoise = Noise.GenerateNoiseMap(chunkSize, chunkSize, 1, offsetNoiseSettings.NoiseSettingsDataMerge, new Vector2(center.x, -center.y) + offsetNoiseOffset); _spreadNoise = Noise.GenerateNoiseMap(chunkSize, chunkSize, 1, offsetNoiseSettings.NoiseSettingsDataMerge, new Vector2(center.x, -center.y) + offsetNoiseOffset * 2); _prefabMaxProbability = SpawnablePrefab.GetMaxSize(_prefabs); for (int i = 0; i < _subSpawners.Length; i++) { _subSpawners[i].Setup(_noise, chunkSize, offsetNoiseSettings, new Vector2(center.x, -center.y), offsetNoiseOffset * 2); } }
/// <summary> /// Spawn a player with the specified occupation /// </summary> /// <param name="occupation">Occupation details to use to spawn this player</param> /// <param name="characterSettings">settings to use for this player</param> /// <param name="playerPrefab">Prefab to use to spawn this player</param> /// <param name="spawnDestination">destinaton to spawn at</param> /// <param name="spawnItems">whether player should spawn naked or with their default loadout</param> /// <returns>the newly created GameObject</returns> /// <returns></returns> public static SpawnInfo Player(Occupation occupation, CharacterSettings characterSettings, GameObject playerPrefab, SpawnDestination spawnDestination, bool spawnItems = false) { return(new SpawnInfo(SpawnType.Player, SpawnablePrefab.For(playerPrefab), spawnDestination, null, 1, occupation, characterSettings: characterSettings, spawnItems: spawnItems)); }
/// <summary> /// Spawn a ghost with the specified occupation /// </summary> /// <param name="occupation">Occupation details to use to spawn this ghost</param> /// <param name="characterSettings">settings to use for this ghost</param> /// <param name="ghostPrefab">Prefab to use to spawn this ghost</param> /// <param name="spawnDestination">destinaton to spawn at</param> /// <returns>the newly created GameObject</returns> /// <returns></returns> public static SpawnInfo Ghost(Occupation occupation, CharacterSettings characterSettings, GameObject ghostPrefab, SpawnDestination spawnDestination) { return(new SpawnInfo(SpawnType.Ghost, SpawnablePrefab.For(ghostPrefab), spawnDestination, null, 1, occupation, characterSettings: characterSettings)); }
private List <SpawnInfo> SpawnFromSpawnables(int detailType, int levelOfDetail, Biome biome, Spawnable[] spawnables, HeightMap heightMap, MeshData meshData, MeshSettings meshSettings, Vector2 chunkPosition, Vector2 chunkCoord, bool firstCall = false) { List <SpawnInfo> spawnInfo = new List <SpawnInfo>(); //Spawn Water - water has detail type of highest level even if it spawns in low LOD because it has no need to check normals if (firstCall) { spawnInfo.Add(new SpawnInfo(biome.WaterChunk, 0, new Vector3(chunkPosition.x, biome.WaterHeight, -chunkPosition.y), Vector3.up, 0, 0, chunkCoord, Vector2.zero, false, new Vector3((meshSettings.ChunkSize - 1) * meshSettings.MeshScale, 1, (meshSettings.ChunkSize - 1) * meshSettings.MeshScale), false)); } for (int i = 0; i < spawnables.Length; i++) { //First spawn the subspawners prefabs as they are harder to make room for if (spawnables[i].SubSpawners.Length > 0) { List <SpawnInfo> childSpawnInfo = SpawnFromSpawnables(detailType, levelOfDetail, biome, spawnables[i].SubSpawners, heightMap, meshData, meshSettings, chunkPosition, chunkCoord); spawnInfo.AddRange(childSpawnInfo); } //This spawnable has nothing to spawn, act only as parent if (!spawnables[i].ParentOnly) { //Get noise specific to this prefab float[,] spawnNoise = spawnables[i].GetNoise; //Local size occupation bool[,] localOccupiedGrid = new bool[_occupiedGrid.GetLength(0), _occupiedGrid.GetLength(1)]; //+ 1 offset in loops are due to border around mesh for (int x = 0; x < meshSettings.ChunkSize - spawnables[i].Size; x++) { for (int y = 0; y < meshSettings.ChunkSize - spawnables[i].Size; y++) { Vector2 itemIndex = new Vector2(x, y); ChunkCoordIndex chunkCoordIndex = new ChunkCoordIndex(chunkCoord, itemIndex); bool shouldSpawn = true; bool partialSpawn = false; if (PrefabSpawnerSaveData.InsideSpawnArea(chunkCoordIndex) && !spawnables[i].OthersCanSpawnInside) { shouldSpawn = false; } //This thing is already picked up! (Size > 0 is just to check if the thing is pickable) if (!spawnables[i].OthersCanSpawnInside && PrefabSpawnerSaveData.ContainsChunkCoordIndex(chunkCoordIndex)) { StoredSaveData data = PrefabSpawnerSaveData.GetStoredSaveData(chunkCoordIndex); if (data.PartialSpawn) { partialSpawn = true; } else { shouldSpawn = false; } } if (shouldSpawn) { bool canObjectSpawnSize = CanObjectSpawnSize(x, y, spawnables[i].Size, meshSettings.ChunkSize, ref localOccupiedGrid) && (CanObjectSpawnSize(x, y, spawnables[i].Spacing, meshSettings.ChunkSize, ref _occupiedGrid) || spawnables[i].OthersCanSpawnInside); bool canObjectSpawnDiff = CanObjectSpawnDiff(x, y, spawnables[i].Size, spawnables[i].OthersCanSpawnInside, heightMap.heightMap, spawnables[i].SpawnDifferencial, meshSettings.ChunkSize); //No use in checking if it can spawn if that square is occopied if (canObjectSpawnSize && canObjectSpawnDiff) { bool insideNoise = spawnNoise[x, y] > spawnables[i].NoiseStartPoint; //is it inside the noise? bool gradientSpawn = spawnNoise[x, y] + spawnables[i].OffsetNoise[x, y] > spawnables[i].Thickness; //If it is, transition? bool uniformSpread = x % spawnables[i].UniformSpreadAmount == 0 && y % spawnables[i].UniformSpreadAmount == 0; //uniform spread? bool noiseSpread = spawnables[i].SpreadNoise[y, x] > spawnables[i].RandomSpread; //Slope Vector3 normal = Vector3.up; //Only on the highest detail level, care about normal if (levelOfDetail == 0) { normal = meshData.GetNormal(y * (meshSettings.ChunkSize) + x); } float slopeAngle = Vector3.Angle(Vector3.up, normal); bool minSlope = (slopeAngle <= spawnables[i].SoftMinSlope * spawnables[i].OffsetNoise[x, y]); minSlope = minSlope && slopeAngle <= spawnables[i].HardMinSlope; bool maxSlope = (slopeAngle >= spawnables[i].SoftMaxSlope * spawnables[i].OffsetNoise[x, y]); maxSlope = maxSlope && slopeAngle >= spawnables[i].HardMaxSlope; //height bools bool minHeight = (heightMap.heightMap[x, y] > spawnables[i].HardMinHeight + spawnables[i].SoftMinAmount * spawnables[i].OffsetNoise[x, y]); bool maxHeight = (heightMap.heightMap[x, y] <= spawnables[i].HardMaxHeight - spawnables[i].SoftMaxAmount * spawnables[i].OffsetNoise[x, y]); SpawnablePrefab spawnPrefab = spawnables[i].GetPrefab(x, y); bool shouldSpawnIfFixedHeight = true; if (spawnables[i].SpawnFixedHeight) { shouldSpawnIfFixedHeight = heightMap.heightMap[x + (int)(STANDARD_GRID_OFFSET * spawnables[i].Size) + 1, y + (int)(STANDARD_GRID_OFFSET * spawnables[i].Size) + 1] + spawnPrefab.Height <= spawnPrefab.FixedHeight + spawnPrefab.Height; } //Things inside the if statement only need to be determined if it should spawn if (insideNoise && gradientSpawn && uniformSpread && noiseSpread && minHeight && maxHeight && minSlope && maxSlope && shouldSpawnIfFixedHeight) { //Since the object can spawn, mark it's space as occopied if (!spawnables[i].OthersCanSpawnInside) { OccupyWithObject(x, y, spawnables[i].Size, meshSettings.ChunkSize, ref _occupiedGrid); } OccupyWithObject(x, y, spawnables[i].Spacing, meshSettings.ChunkSize, ref localOccupiedGrid); float scale = spawnPrefab.ScaleRandom * spawnables[i].OffsetNoise[x, y] + spawnPrefab.Scale; Vector3 newScale = new Vector3(scale, scale, scale); //Current local positions in x and y in chunk, used only to spawn from float xPos = x + STANDARD_GRID_OFFSET + (STANDARD_GRID_OFFSET * spawnables[i].Size) - meshSettings.ChunkSize / 2 - 1; //Due to the border around the mesh + STANDARD_GRID_OFFSET corrects it to the right grid position float zPos = y + STANDARD_GRID_OFFSET + (STANDARD_GRID_OFFSET * spawnables[i].Size) - meshSettings.ChunkSize / 2 - 1; //Due to the border around the mesh + STANDARD_GRID_OFFSET corrects it to the right grid position float yPos = heightMap.heightMap[x + (int)(STANDARD_GRID_OFFSET * spawnables[i].Size) + 1, y + (int)(STANDARD_GRID_OFFSET * spawnables[i].Size) + 1] + spawnPrefab.Height; //Used if the object should not follow the world geometry and spawn at fixed height -> spawn in water // Only allow it if the object won't spawn under the terrain! if (spawnables[i].SpawnFixedHeight) { yPos = spawnPrefab.FixedHeight + spawnPrefab.Height; } //Position from grid in world Vector3 objectPosition = new Vector3((xPos + chunkPosition.x) * meshSettings.MeshScale, yPos, -(zPos + chunkPosition.y) * meshSettings.MeshScale); //Vector to offset from grid slightly to create less uniform distribution Vector3 offsetVector = new Vector3(spawnables[i].OffsetNoise[x, y] * 2 - 1, 0.0f, spawnables[i].SpreadNoise[x, y] * 2 - 1); objectPosition += offsetVector * spawnables[i].OffsetAmount; //How much along the normal should the object point? float tiltAmount = spawnables[i].SurfaceNormalAmount + (spawnables[i].SpreadNoise[x, y] * 2 - 1) * spawnables[i].PointAlongNormalRandomness; float localRotationAmount = spawnables[i].OffsetNoise[x, y] * DEGREES_360 * spawnables[i].RotationAmount; spawnInfo.Add(new SpawnInfo(spawnPrefab.Prefab, detailType, objectPosition, normal, tiltAmount, localRotationAmount, chunkCoord, itemIndex, spawnables[i].Size != 0, newScale, partialSpawn)); } } } } } } } return(spawnInfo); }
/// <summary> /// FOR DEV / TESTING ONLY! Simulates destroying and recreating an item by putting it in the pool and taking it back /// out again. If item is not pooled, simply destroys and recreates it as if calling Despawn and then Spawn /// Can use this to validate that the object correctly re-initializes itself after spawning - /// no state should be left over from its previous incarnation. /// </summary> /// <returns>the re-created object</returns> public static GameObject ServerPoolTestRespawn(GameObject target) { var poolPrefabTracker = target.GetComponent <PoolPrefabTracker>(); if (poolPrefabTracker == null) { //destroy / create using normal approach with no pooling Logger.LogWarningFormat("Object {0} has no pool prefab tracker, thus cannot be pooled. It will be destroyed / created" + " without going through the pool.", Category.ItemSpawn, target.name); //determine prefab var position = target.TileWorldPosition(); var prefab = DeterminePrefab(target); if (prefab == null) { Logger.LogErrorFormat("Object {0} at {1} cannot be respawned because it has no PoolPrefabTracker and its name" + " does not match a prefab name, so we cannot" + " determine the prefab to instantiate. Please fix this object so that it" + " has an attached PoolPrefabTracker or so its name matches the prefab it was created from.", Category.ItemSpawn, target.name, position); return(null); } Despawn.ServerSingle(target); return(ServerPrefab(prefab, position.To3Int()).GameObject); } else { //destroy / create with pooling //save previous position var destination = SpawnDestination.At(target); var worldPos = target.TileWorldPosition(); var transform = target.GetComponent <IPushable>(); var prevParent = target.transform.parent; //this simulates going into the pool Despawn._ServerFireDespawnHooks(DespawnResult.Single(DespawnInfo.Single(target))); if (transform != null) { transform.VisibleState = false; } //this simulates coming back out of the pool target.SetActive(true); target.transform.parent = prevParent; target.transform.position = worldPos.To3Int(); var cnt = target.GetComponent <CustomNetTransform>(); if (cnt) { cnt.ReInitServerState(); cnt.NotifyPlayers(); //Sending out clientState for already spawned items } var prefab = DeterminePrefab(target); SpawnInfo spawnInfo = SpawnInfo.Spawnable( SpawnablePrefab.For(prefab), destination); _ServerFireClientServerSpawnHooks(SpawnResult.Single(spawnInfo, target)); return(target); } }