I want to spawn a 100 object whit 0.1 seconds in between.
I have this but they still spawn all at once.
private float timer = 0.0f;
bool goSpawn = false;
private void Update()
{
if (goSpawn)
{
timer += Time.deltaTime;
}
}
public void spawnAnimals()
{
goSpawn = true;
for (int i = 0; i < 100;)
{
if (timer > 2f)
{
RndSpawnPos = new Vector3(Random.Range(3.30f, 5.70f), 0.78f, Random.Range(-3.00f, 3.01f));
Instantiate(animal, RndSpawnPos, Quaternion.identity);
i++;
timer = 0.0f;
}
}
}
Use an IEnumerator. I put an example to solve the problem:
public void Start() => StartCoroutine(SpawnObject(100, .1f));
public IEnumerator SpawnObject(int count, float intervalTime)
{
for (var i = 0; i < count; i++)
{
Instantiate(" something in here...");
yield return new WaitForSeconds(intervalTime);
}
}
Related
This question already has an answer here:
Public Dictionary in Unity
(1 answer)
Closed 9 months ago.
I wrote an ObjectPooler code by watching this Brackeys tutorial. It's working fine until I duplicate it to another scene. In the second scene when the scene changes or refreshes object pooler is not working anymore. It's spawning objects but doesn't bring objects and activate them.
Here is my ObjectPooler code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectPool : MonoBehaviour
{
[System.Serializable]
public class Pool
{
public string tag;
public GameObject prefab;
public int size;
}
public static ObjectPool Instance;
public GameObject diamondCollectedFX;
public List<Pool> pools;
public Dictionary<string, Queue<GameObject>> poolDictinory;
private void Awake()
{
Instance = this;
}
private void Start()
{
poolDictinory = new Dictionary<string, Queue<GameObject>>();
foreach (Pool pool in pools)
{
Queue<GameObject> objectPool = new Queue<GameObject>();
for (int i = 0; i < pool.size; i++)
{
GameObject obj = Instantiate(pool.prefab);
obj.SetActive(false);
objectPool.Enqueue(obj);
}
poolDictinory.Add(pool.tag, objectPool);
}
}
public GameObject SpawnFromPool(string tag, Vector3 position, Quaternion rotation)
{
if (!poolDictinory.ContainsKey(tag))
{
Debug.LogWarning("Pool with tag" + tag + "Dosn't Excist");
return null;
}
GameObject objectToSpawn = poolDictinory[tag].Dequeue();
objectToSpawn.SetActive(true);
objectToSpawn.transform.position = position;
objectToSpawn.transform.rotation = rotation;
poolDictinory[tag].Enqueue(objectToSpawn);
return objectToSpawn;
}
}
and this is my GameManager that calls ObjectPool for spawn objects:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Cinemachine;
using UnityEngine.EventSystems;
public class GameManager : MonoBehaviour
{
public static GameManager Instance;
[Header("About Health Variables")]
private int health;
public int collectedDiamonds;
public int collectedCoins;
public bool godMode;
public bool gameStarted;
[SerializeField] private float godModeDuration = 2f;
[SerializeField] private float slowTimeDuration = 2f;
[SerializeField] private GameObject healthObject;
[SerializeField] private GameObject healthParentObject;
[SerializeField] private GameObject menuCanvas;
[SerializeField] private GameObject inGameCanvas;
[SerializeField] private GameObject finishCanvas;
[Header("About Level Progress")]
[SerializeField] private Transform finishTransform;
[SerializeField] private LevelProgressBarManager levelProgressBar;
[SerializeField] private CinemachineVirtualCamera startCam;
[SerializeField] private CinemachineVirtualCamera inGameCam;
[Header("About Collectables")]
[SerializeField] private GameObject diamondSprite;
[SerializeField] private GameObject godModeIcon;
[SerializeField] private TMP_Text diamondCountText;
[SerializeField] private TMP_Text coinCountText;
private float levelLength;
private float remainDistanceToFinish;
private float godModeTimer;
private float slowTimeTimer;
private int obstacleCount = 10;
private int diamondCount = 3;
private int coinCount = 25;
private bool slowTimeBooster;
private GameObject[] spawnPoints;
private PlayerController playerController;
private ObjectPool objectPool;
private EconomyManager economyManager;
void Awake()
{
Instance = this;
playerController = GetComponent<PlayerController>();
objectPool = ObjectPool.Instance;
economyManager = GameObject.FindGameObjectWithTag("EconomyManager").GetComponent<EconomyManager>();
spawnPoints = GameObject.FindGameObjectsWithTag("ObstacleSpawn");
levelLength = Vector3.Distance(transform.position, finishTransform.position);
diamondCountText.text = "0";
coinCountText.text = "0";
}
private void Start()
{
for (int i = 0; i < obstacleCount; i++)
{
ObjectPool.Instance.SpawnFromPool("Obstacle", spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position, Quaternion.Euler(0,90,0));
}
for (int i = 0; i < diamondCount; i++)
{
ObjectPool.Instance.SpawnFromPool("Diamond", spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position + new Vector3(0, 1f, 0), Quaternion.identity);
}
for (int i = 0; i < coinCount; i++)
{
ObjectPool.Instance.SpawnFromPool("Coin", spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position + new Vector3(0, 1f, 0), Quaternion.identity);
}
for (int i = 0; i < 2; i++)
{
ObjectPool.Instance.SpawnFromPool("TimeSlower", spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position + new Vector3(0, 1f, 0), Quaternion.identity);
ObjectPool.Instance.SpawnFromPool("GodModeBooster", spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position + new Vector3(0, 1f, 0), Quaternion.identity);
}
}
void Update()
{
if (!gameStarted && Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject())
{
gameStarted = true;
startCam.Priority = 0;
menuCanvas.SetActive(false);
inGameCanvas.SetActive(true);
for (int i = 0; i < economyManager.heartCount; i++)
{
var heart = Instantiate(healthObject);
heart.transform.parent = healthParentObject.transform;
}
health = economyManager.heartCount;
}
remainDistanceToFinish = Vector3.Distance(transform.position, finishTransform.position);
levelProgressBar.SetProgress(1 - (remainDistanceToFinish / levelLength));
if (godMode)
{
godModeTimer += Time.deltaTime;
if (godModeTimer > godModeDuration)
{
godModeTimer = 0;
godModeIcon.SetActive(false);
godMode = false;
}
}
if (slowTimeBooster)
{
slowTimeTimer += Time.deltaTime;
if (slowTimeTimer >= slowTimeDuration)
{
Time.timeScale = 1;
slowTimeTimer = 0;
slowTimeBooster = false;
}
else
{
Time.timeScale = 0.5f;
}
}
if (health <= 0)
{
LevelFailed();
}
}
void LevelFailed()
{
gameStarted = false;
playerController.isGameStarted = false;
GetComponent<Animator>().SetTrigger("Failed");
startCam.Priority = 10;
StartCoroutine(WaitForFailCanvas());
inGameCanvas.SetActive(false);
}
void LevelPassed()
{
gameStarted = false;
playerController.isGameStarted = false;
inGameCanvas.SetActive(false);
StartCoroutine(WaitForPassedCanvas());
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Diamond"))
{
other.gameObject.SetActive(false);
collectedDiamonds++;
diamondCountText.text = collectedDiamonds.ToString();
diamondCount--;
while (diamondCount < 3)
{
var selectedSpawn = spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position;
//if (remainDistanceToFinish < 15f)
//{
// diamondCount = 3;
//}
if (selectedSpawn.z - transform.position.z > 10 || remainDistanceToFinish < 25f)
{
ObjectPool.Instance.SpawnFromPool("Diamond", spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position + new Vector3(0, 1f,0), Quaternion.identity);
diamondCount++;
}
}
diamondSprite.GetComponent<Animator>().SetTrigger("DiamondCollected");
ObjectPool.Instance.diamondCollectedFX.transform.position = other.transform.position;
ObjectPool.Instance.diamondCollectedFX.SetActive(true);
}
else if (other.gameObject.CompareTag("Coin"))
{
other.gameObject.SetActive(false);
collectedCoins += economyManager.coinMultiplier;
coinCount--;
while (coinCount < 20)
{
var selectedSpawn = spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position;
//if (remainDistanceToFinish < 15f)
//{
// coinCount = 20;
//}
if (selectedSpawn.z - transform.position.z > 10 || remainDistanceToFinish < 25f)
{
ObjectPool.Instance.SpawnFromPool("Coin", spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position + new Vector3(0, 1f, 0), Quaternion.identity);
coinCount++;
}
}
coinCountText.text = collectedCoins.ToString();
}
else if (other.gameObject.CompareTag("Obstacle"))
{
other.gameObject.SetActive(false);
obstacleCount--;
if (!godMode)
{
health--;
Destroy(healthParentObject.transform.GetChild(healthParentObject.transform.childCount - 1).gameObject);
}
while (obstacleCount < 10)
{
var selectedSpawn = spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position;
//if (remainDistanceToFinish < 15f)
//{
// obstacleCount = 10;
//}
if (selectedSpawn.z - transform.position.z > 10 || remainDistanceToFinish < 25f)
{
ObjectPool.Instance.SpawnFromPool("Obstacle", spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position, Quaternion.Euler(0, 90, 0));
obstacleCount++;
}
}
if (health > 0)
{
playerController.GetHitted();
godMode = true;
}
}
else if (other.gameObject.CompareTag("Finish"))
{
startCam.Priority = 10;
playerController.Finished();
LevelPassed();
}
else if (other.gameObject.CompareTag("TimeSlower"))
{
slowTimeBooster = true;
other.gameObject.SetActive(false);
}
else if (other.gameObject.CompareTag("GodMode"))
{
godMode = true;
godModeIcon.SetActive(true);
other.gameObject.SetActive(false);
}
}
IEnumerator WaitForFailCanvas()
{
yield return new WaitForSeconds(2);
finishCanvas.SetActive(true);
finishCanvas.transform.GetChild(0).gameObject.SetActive(true);
}
IEnumerator WaitForPassedCanvas()
{
yield return new WaitForSeconds(2);
finishCanvas.SetActive(true);
finishCanvas.transform.GetChild(1).gameObject.SetActive(true);
}
}
And the error is here:
Yayyyy I found the solution! In any case, if this will be helpful for somebody this question has a solution for my problem guys! All I needed to change the execution order of my ObjectPool and GameManager script.
2D Top Down style game. I’m trying to figure out how to hit an enemy whenever he enters the range of my attack point and get hit every, say, 3 frames if he is still within my attack point. here's my script.
public Animator animator;
public Transform AttackPoint;
public float attackRange = 0.5f;
public LayerMask enemyLayers;
public int attackDamage = 40;
public float attackRate = 1f;
float nextAttackTime = 0f;
// Update is called once per frame
void Update()
{
if(Time.time >= nextAttackTime)
{
if (Input.GetKeyDown(KeyCode.Space))
{
Attack();
nextAttackTime = Time.time + 1f / attackRate;
}
}
}
void Attack()
{
animator.SetTrigger("Attack");
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(AttackPoint.position, attackRange, enemyLayers);
foreach(Collider2D enemy in hitEnemies)
{
enemy.GetComponent<Enemy>().TakeDamage(attackDamage);
}
}
void OnDrawGizmosSelected()
{
if (AttackPoint == null)
return;
Gizmos.DrawWireSphere(AttackPoint.position, attackRange);
}
foreach enemys and check distance with you , and attack it.
and you need a Manager to handle all enemys.
List<Transform> enemys = new List<Transform>();
public void Update()
{
for (int i = 0; i < enemys.Count; i++)
{
float distance = Vector3.Distance(enemys[i].position, transform.position);
if (distance < 10)// in range
{
//todo attack
}
}
}
What Whip should look like
I'm trying to create a whip that can extend in any direction the mouse is facing after pressing a certain button. If there are "grabbable" objects in the way such as an enemy or box, it should latch onto those objects and pull them around to collide with other objects for a certain amount of time.
I know that I need the different sprite shots of the whip extending and latching for animation, but I have no idea how to implement this in code and how to get the whip to stop short if it detects a "grabbable" object.
Attach this script to your player, this should get the job done:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public Transform player = null;
public float speed = 30f;
public string grabbableTag = "grabbable";
private LineRenderer line = null;
private float timer = 0f;
private bool grabbing = false;
private bool reached = false;
private Vector2 from = Vector2.zero;
private Vector2 to = Vector2.zero;
private Vector2 target = Vector2.zero;
private Transform grabbable = null;
private void Start()
{
player = transform;
line = new GameObject("Line").AddComponent<LineRenderer>();
line.startColor = Color.red;
line.endColor = Color.red;
// Assign a material
line.gameObject.SetActive(false);
reached = false;
grabbing = false;
}
private void Update()
{
if(grabbing)
{
Grabbing();
}
else
{
if (Input.GetMouseButtonDown(0))
{
Grab();
}
}
}
private void Grab()
{
Vector3 mousePosition = Input.mousePosition;
mousePosition.z = Vector3.Distance(player.position, Camera.main.transform.position);
to = Camera.main.ScreenToWorldPoint(mousePosition);
from = player.position;
Vector2 direction = (to - from).normalized;
float distance = Vector2.Distance(from, to);
RaycastHit2D[] hits = Physics2D.RaycastAll(from, direction, distance);
grabbable = null;
for (int i = 0; i < hits.Length; i++)
{
if (hits[i].transform.tag == grabbableTag)
{
grabbable = hits[i].transform;
break;
}
}
if (grabbable != null)
{
distance = Vector2.Distance(player.position, grabbable.position);
to = from + direction * distance;
}
grabbing = true;
reached = false;
target = from;
timer = 0;
line.gameObject.SetActive(true);
line.positionCount = 2;
line.SetPosition(0, from);
line.SetPosition(1, from);
}
private void Grabbing()
{
if (reached)
{
target = Vector2.Lerp(target, from, speed * Time.deltaTime);
if (target == from)
{
GrabDone(grabbable);
grabbing = false;
line.gameObject.SetActive(false);
}
}
else
{
target = Vector2.Lerp(target, to, speed * Time.deltaTime);
if(target == to)
{
reached = true;
}
}
line.SetPosition(1, target);
if (reached && grabbable != null)
{
grabbable.position = target;
}
}
private void GrabDone(Transform grabbed)
{
if(grabbed != null)
{
// Do somthing ...
Destroy(grabbed.gameObject);
}
}
}
There is a dynamic Rigidbody that can be launched with the mouse. But at some point, Rigidbody stops reacting to the mouse for some reason. Rigidbody's speed is 0.
To a rigidbody attached two Spring joints.
The only way to awaken the body is to disable and re-enable Spring Joints when debugging.
public class Ball : MonoBehaviour
{
private Rigidbody2D rigidbodyBall;
public SpringJoint2D[] springJoints;
private GameObject speed;
public static Ball instance = null;
#region Life Cycle
void Awake()
{
speed = GameObject.Find("Velocity");
springJoints = GetComponents<SpringJoint2D>();
rigidbodyBall = GetComponent<Rigidbody2D>();
gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
}
private bool clickedOn = false;
void Update()
{
if (clickedOn)
{
Dragging();
UIManager.instance.pauseButton.SetActive(false);
UIManager.instance.totalScoreUI.gameObject.SetActive(false);
}
else
{
UIManager.instance.pauseButton.SetActive(true);
UIManager.instance.totalScoreUI.gameObject.SetActive(true);
}
}
#endregion
#region Launcher
#region Mouse
void OnMouseDown()
{
SpringJointDeactivate();
clickedOn = true;
}
void OnMouseUp()
{
SpringJointActivate();
clickedOn = false;
SetKinematicState(false);
Invoke("SpringJointDeactivate", 0.1f);
}
void Dragging()
{
Vector3 mouseWorldPointStart = transform.position;
Vector3 mouseWorldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mouseWorldPoint.z = 0f;
if (Boundary.ballInBoundary)
{
transform.position = mouseWorldPoint;
float diffX = mouseWorldPoint.x - mouseWorldPointStart.x;
//TODO
for (int i = 0; i < springJoints.Length; i++)
{
springJoints[i].connectedAnchor = new Vector2(springJoints[i].connectedAnchor.x + diffX, springJoints[i].connectedAnchor.y);
}
}
else
{
Debug.Log("Another situation!");
Debug.Log(Boundary.ballInBoundary);
}
}
#endregion
public void SpringJointActivate()
{
foreach (SpringJoint2D joint in springJoints)
{
joint.enabled = true;
}
}
public void SpringJointDeactivate()
{
foreach (SpringJoint2D joint in springJoints)
{
joint.enabled = false;
}
}
public Vector3[] GetSpringJointsConnectedAnchorCoord()
{
Vector3[] springJointsCoord = new[] { Vector3.zero, Vector3.zero };
for (int i = 0; i < springJoints.Length; i++)
{
springJointsCoord[i] = springJoints[i].connectedAnchor;
}
return springJointsCoord;
}
#endregion
public void SetKinematicState(bool kinematicState)
{
rigidbodyBall.isKinematic = kinematicState;
}
}
What is the reason for this? How can this be corrected?
Replaced OnMouseDown() with Input.GetMouseButtonDown(0) and everything worked out.
void Update()
{
if (Input.GetMouseButtonDown(0))
{
SpringJointDeactivate();
clickedOn = true;
}
if (Input.GetMouseButtonUp(0))
{
SpringJointActivate();
clickedOn = false;
SetKinematicState(false);
Invoke("SpringJointDeactivate", 0.1f);
}
}
I'm working on a script for my camera to make objects between itself and the character transparent.
I managed to make it work with RayCast however I don't know how to restablish objects alpha value after they escape the ray.
This is my current code:
private void XRay() {
float characterDistance = Vector3.Distance(transform.position, GameObject.Find("Character").transform.position);
Vector3 fwd = transform.TransformDirection(Vector3.forward);
RaycastHit hit;
if (Physics.Raycast(transform.position, fwd, out hit, characterDistance)) {
// Add transparence
Color color = hit.transform.gameObject.renderer.material.color;
color.a = 0.5f;
hit.transform.gameObject.renderer.material.SetColor("_Color", color);
}
}
This is my final code. Note it only makes transparent one object at a time, but the same implementation can easily be done with RaycastAll and using an array for oldHits.
public class Camara : MonoBehaviour {
RaycastHit oldHit;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void FixedUpdate() {
XRay ();
}
// Hacer a los objetos que interfieran con la vision transparentes
private void XRay() {
float characterDistance = Vector3.Distance(transform.position, GameObject.Find("Character").transform.position);
Vector3 fwd = transform.TransformDirection(Vector3.forward);
RaycastHit hit;
if (Physics.Raycast(transform.position, fwd, out hit, characterDistance)) {
if(oldHit.transform) {
// Add transparence
Color colorA = oldHit.transform.gameObject.renderer.material.color;
colorA.a = 1f;
oldHit.transform.gameObject.renderer.material.SetColor("_Color", colorA);
}
// Add transparence
Color colorB = hit.transform.gameObject.renderer.material.color;
colorB.a = 0.5f;
hit.transform.gameObject.renderer.material.SetColor("_Color", colorB);
// Save hit
oldHit = hit;
}
}
}
I did attach this script to my simple camera following the player. It might help you.
It can actually manage more than one obstructing the view and also you see I pass it a mask which I target with its name instead of checking for the collider name tag. Have fun.
using UnityEngine;
public class followPlayer : MonoBehaviour
{
public Transform player;
public Vector3 offset;
public Transform[] obstructions;
private int oldHitsNumber;
void Start()
{
oldHitsNumber = 0;
}
private void LateUpdate()
{
viewObstructed();
}
void Update()
{
transform.position = player.TransformPoint(offset);
transform.LookAt(player);
}
void viewObstructed()
{
float characterDistance = Vector3.Distance(transform.position, player.transform.position);
int layerNumber = LayerMask.NameToLayer("Walls");
int layerMask = 1 << layerNumber;
RaycastHit[] hits = Physics.RaycastAll(transform.position, player.position - transform.position, characterDistance, layerMask);
if (hits.Length > 0)
{ // Means that some stuff is blocking the view
int newHits = hits.Length - oldHitsNumber;
if (obstructions != null && obstructions.Length > 0 && newHits < 0)
{
// Repaint all the previous obstructions. Because some of the stuff might be not blocking anymore
for (int i = 0; i < obstructions.Length; i++)
{
obstructions[i].gameObject.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;
}
}
obstructions = new Transform[hits.Length];
// Hide the current obstructions
for (int i = 0; i < hits.Length; i++)
{
Transform obstruction = hits[i].transform;
obstruction.gameObject.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly;
obstructions[i] = obstruction;
}
oldHitsNumber = hits.Length;
}
else
{ // Mean that no more stuff is blocking the view and sometimes all the stuff is not blocking as the same time
if (obstructions != null && obstructions.Length > 0)
{
for (int i = 0; i < obstructions.Length; i++)
{
obstructions[i].gameObject.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;
}
oldHitsNumber = 0;
obstructions = null;
}
}
}
}