I'm making a 'run' game in Unity and I'm making a prototype with a ball, that has other balls following him. If the followers hit an object they get destroyed after some time. To make it so you don't run out of enemies I made a trigger that spawns new enemies. In the code this is the function Addzombies.
How do I make them spawn not on the same point, if i run it now they
start on eachother and bounce around as an explosion.
How do i make some start in the air, i tried it but they don't
spawn.
My code:
using UnityEngine;
using System.Collections;
public class Ball : MonoBehaviour {
public float InputForce;
public GUIText guiText;
public float rotationHorizontal;
public AudioClip ACeffect2;
public GameObject zombiePrefab;
void FixedUpdate() {
rigidbody.AddForce( Camera.main.transform.right * Input.GetAxis("Horizontal") * InputForce);
rigidbody.AddForce( Camera.main.transform.forward * Input.GetAxis("Vertical") * InputForce);
transform.position += Vector3.forward *InputForce * Time.deltaTime;
rotationHorizontal = Input.GetAxis("Horizontal") * InputForce;
rotationHorizontal *= Time.deltaTime;
rigidbody.AddRelativeTorque (Vector3.back * rotationHorizontal);
}
void OnCollisionEnter(Collision col){
if (col.gameObject.name == "Zombie") {
Debug.Log ("Player geraakt, nu ben je eigenlijk dood");
}
if (col.gameObject.name == "Obstakel1") {
Debug.Log ("Obstakel1 geraakt");
audio.PlayOneShot(ACeffect2);
InputForce = 0;
}
if (col.gameObject.name == "Obstakel2") {
Debug.Log ("Obstakel2 geraakt");
}
}
void AddZombies(int aantal){
for (int i = 0; i < aantal; i++){
GameObject go = GameObject.Instantiate(zombiePrefab, transform.position - new Vector3(0, 0, 7 + i),Quaternion.identity) as GameObject;
Zombie zb = go.GetComponent<Zombie>();
zb.target = gameObject.transform;
}
}
void OnTriggerEnter(Collider col) {
Debug.Log ("Enter" +col.name);
if (col.tag == "AddZombies"){
AddZombies(4);
}
}
void OnTriggerExit(Collider col) {
Debug.Log ("Leaving with" +col.name);
}
}
I will advice on how things could be done, but you will have to make changes to make it suit your requirement
public Transform zombiePrefab; // From the editor drag and drop your prefab
void addZombies()
{
// as you need them to be not on the same point
int randomX = Random.Range(-10.0F, 10.0F);
for (int i = 0; i < aantal; i++){
// make a transform
var zombieTransform = Instantiate(zombiePrefab) as Transform;
zombieTransform.position = new Vector3(randomX, 0, 7 + i);
transform.GetComponent<Rigidbody>().enabled = false;
// make it enable when you need and add force to make them fall
}
}
I would suggest passing the number of zombies to pass, and an integer representing the range of space that they can spawn in. Then just use UnityEngine.Random with said integer for each zombie to produce several different co-ordinates for spawning the zombies.
As for getting them to spawn in the air, just increase the y co-ordinate when you instantiate the zombie.
Related
I am very new to c# and I've come across a problem with my enemy spawner. I am making an endless top-down shooter, and after 20 enemies have been spawned and then destroyed, the enemies stop appearing. My score counter continues to increase though, which leads me to believe they're somehow being destroyed.
Here is the enemy spawn controller:
void Update()
{
if (!spawningObject && GameController.EnemyCount < spawnSettings[0].maxObjects)
{
spawningObject = true;
float pick = Random.value * totalWeight;
int chosenIndex = 0;
float cumulativeWeight = enemySpawnables[0].weight;
while(pick > cumulativeWeight && chosenIndex < enemySpawnables.Count - 1)
{
chosenIndex++;
cumulativeWeight += enemySpawnables[chosenIndex].weight;
}
StartCoroutine(SpawnObject(enemySpawnables[chosenIndex].type, Random.Range(spawnSettings[0].minWait / GameController.DifficultyMultiplier, spawnSettings[0].maxWait / GameController.DifficultyMultiplier)));
Spawn();
}
}
private IEnumerator SpawnObject(string type, float time)
{
yield return new WaitForSeconds(time);
randomSpawnPoint = Random.Range(0, enemySpawners.Length);
randomEnemy = Random.Range(0, enemy.Length);
enemyPool.SpawnObject(enemySpawners[randomSpawnPoint].position, transform.rotation);
spawningObject = false;
GameController.EnemyCount++;
}
And here is the enemy controller (attached to enemy prefab):
public void Start()
{
myRB = GetComponent<Rigidbody>();
player = FindObjectOfType<PlayerController>();
}
private void OnEnable()
{
player = FindObjectOfType<PlayerController>();
}
void Update()
{
if (health <= 0)
{
Die();
}
}
void FixedUpdate()
{
transform.LookAt(player.transform.position);
myRB.velocity = (transform.forward * moveSpeed);
//Falling
if(myRB.velocity.y < 0)
{
myRB.velocity += Vector3.up * Physics.gravity.y * (fallMultiplier - 1) * Time.deltaTime;
}
}
public void Die()
{
print("Enemy" + this.gameObject.name + " has died!");
EnemySpawn.instance.enemyPool.ReturnObject(this.gameObject);
player.GetComponent<PlayerController>().points += pointsToGive;
ScoreController.scoreValue += 1;
}
The only thing that should affect enemy health is the bullet. Here is the part of the bullet controller that affects enemy health:
public void OnTriggerEnter(Collider other)
{
if(other.tag == "Enemy")
{
triggeringEnemy = other.gameObject;
triggeringEnemy.GetComponent<EnemyController>().health -= damage;
PlayerController.instance.bulletPool.ReturnObject(gameObject);
}
}
The issue always happens after 20 enemies have been spawned/destroyed and 20 points have been achieved. Before then, enemy movement is normal and everything seems to be working as it should. It could very well be something very simple that I'm missing, but I'd appreciate any help!
When you do engage logic mistake good way to find it is Visual Studio debugging.
Here is good official article about whole process - https://docs.unity3d.com/Manual/ManagedCodeDebugging.html.
I would place breakpoint right at start of Update method to see that EnemyCount increases over time and then you will understand that you forgot to do decrement it.
Hey Guys I've been having a problem lately that I cant seem to solve.
A sprite is supposed to roam around (as it does) while nothing is inside its radius, however if the player moves close to it the sprite should theoretically move towards it and stop roaming.
The sprite doesn't follow the player and cant even see its tag since I cant even see the contents of the "Collider2D[] hits".
using System.Collections.Generic;
using UnityEngine;
public class FireCultist : MonoBehaviour
{
public float moveTimeSeconds; //Time it will take object to move, in seconds.
private float xMax = 10.0f; // The boundaries of the spawn area
private float yMax = 10.0f;
private float xMin = -10.0f; // The boundaries of the spawn area
private float yMin = -10.0f;
public int xDistanceRange; // The max distance you can move at one time
public int yDistanceRange;
private BoxCollider2D boxCollider; //The BoxCollider2D component attached to this object.
private Rigidbody2D rb2D; //The Rigidbody2D component attached to this object.
private float inverseMoveTime; //Used to make movement more efficient.
public Vector2 start;
public Vector2 end;
public bool roam = true;
public Collider2D[] hits;
void Start()
{
boxCollider = GetComponent<BoxCollider2D>();
rb2D = GetComponent<Rigidbody2D>();
inverseMoveTime = 1f / moveTimeSeconds;
InvokeRepeating("RandomMove", 0.0f, 5.0f);
}
void Update()
{
Collider2D[] hits = Physics2D.OverlapCircleAll(transform.position, 10); // returns all colliders within radius of enemy
int i = 0;
while(hits.Length > i)
{
Debug.Log("Sees");
Debug.Log(hits[i]);
i++;
}
followPlayer();
if (roam)
{
Debug.Log("Roam");
transform.position = Vector2.MoveTowards(transform.position, end, inverseMoveTime * Time.deltaTime); //Random move to new position
}
}
public void followPlayer()
{
foreach (Collider2D hit in hits)
{
if (hit.tag == "Player") // if the player is within a radius
{
Debug.Log("Chasing Player");
transform.position = Vector2.MoveTowards(transform.position, GameObject.Find("Prefabs/Player").GetComponent<Transform>().position, inverseMoveTime * Time.deltaTime); // chase player
roam = false;
}
else
{
Debug.Log("Continues");
roam = true; // Continue RandomMove()
}
}
}
public void RandomMove() // gets random coordinates near enemy and moves there
{
float xDistance = Random.Range(-xDistanceRange, xDistanceRange); // check
float yDistance = Random.Range(-yDistanceRange, yDistanceRange);// check
if (xDistance < xMax && xDistance > xMin && yDistance < yMax && yDistance > yMin && roam == true) // If within boundaries of walking space
{
start = transform.position;
end = start + new Vector2(xDistance, yDistance);
Debug.Log("Roaming From : " + start + " To : " + end);
}
}
}
The roaming algorithm works however not too sure about the tag detection.
The script belongs to this enemy object
Player Object Properties
It looks like you are declaring a new hits variable during every update instead of using your class-level variable. This means the variable inside of followPlayer() will never be instantiated, and the information will not be passed between the two methods.
Try this:
void Update()
{
hits = Physics2D.OverlapCircleAll(transform.position, 10);
//...
}
You might also consider attaching a trigger collider to the enemy which sends a notification when the player enters/exits the trigger instead of relying on OverlapCircleAll()
void OnTriggerEnter2D(Collider2D col)
{
if(col.gameObject.tag == "Player"){
roam = false;
}
}
void OnTriggerExit2D(Collider2D col)
{
if(col.gameObject.tag == "Player"){
roam = true;
}
}
Hi all I am developing an endless runner game and need help on solving an issue. My version of the endless runner is where the player moves along the z-axis while tiles spawning in-front of the player. The tiles have 3 lanes. So my issue is this. I have this spawning script which I got from researching the net and ran into the issue the script is written where the tiles moving under the player rather than player running forward. I tried to convert it so that that objects are spawned in front of the player (z-axis) but I didn't quite achieve what I intended for.
So my errors are,
objects (obstacles) are spawning behind the player and eventually stops
objects are spawned only in one lane.
So how do I how do I rectify above errors?
Here's my script.
public class Spawner : MonoBehaviour {
[Space(10)]
[Header("Obstacles:")]
public float objectSpawnWait;
public Vector3 randPos1;
public Vector3 randPos2;
public Vector3 randPos3;
public float spawnZ; //distance between player and the object
public float spawnDistance; //distance between object
public GameObject[] obstacles;
private Transform playerTranform;
void Start()
{
playerTranform = GameObject.FindGameObjectWithTag("Player").transform;
}
void Update()
{
if(playerTranform.position.z > spawnZ * spawnDistance)
{
StartCoroutine(SpawnObstacle());
}
}
IEnumerator SpawnObstacle()
{
if (obstacles.Length > 0)
{
int randomObstacle = Random.Range(0, obstacles.Length);
GameObject obstacle = Instantiate(obstacles[randomObstacle]);
obstacle.transform.SetParent(transform);
MoveObjectsToTheFront(obstacle);
}
yield return new WaitForSeconds(5);
}
private void MoveObjectsToTheFront(GameObject moveObject)
{
int randomPosNum = Random.Range(0, 2);
Vector3 randomPosition;
if (randomPosNum == 0)
randomPosition = randPos1; // Vector3(2, 0.5, 5)
else if (randomPosNum == 1)
randomPosition = randPos2; // Vector3(0, 0.5, 5)
else
randomPosition = randPos3; // Vector3(-2, 0.5, 5)
moveObject.transform.position = randomPosition * spawnZ;
spawnZ += spawnDistance;
}
}
Any help would be greatly appreciated. Thanks.
This question already has answers here:
Rotate GameObject over time
(2 answers)
Closed 5 years ago.
in my project i have a bridge at the moment when i colide with the bridge it rotates and don't stop rotate, what i want is to rotate that bridge trough a specific point and stop rotate, that bridge is inside a gameobject that is my pivotPoint in general i rotate the pivotPoint not the bridge, so i did this:
using UnityEngine;
using System.Collections;
public class fallBridge : MonoBehaviour {
private Rigidbody ball;
public GameObject bridgePivot;
private bool colided;
private bool rotating = true;
// Update is called once per frame
void Start(){
colided = false;
}
void Update () {
if (colided) {
if (rotating) {
Vector3 to = new Vector3 (0, 0, -85);
if (Vector3.Distance (bridgePivot.transform.eulerAngles, to) > 0.01f) {
bridgePivot.transform.eulerAngles = Vector3.Lerp (bridgePivot.transform.rotation.eulerAngles, to, Time.deltaTime);
} else {
bridgePivot.transform.eulerAngles = to;
rotating = false;
}
}
}
}
void OnCollisionEnter(Collision other)
{
ball = GameObject.FindWithTag ("Player").GetComponent<Rigidbody> ();
if (other.gameObject.tag == "Player" && ball.transform.localScale == new Vector3(2.0f,2.0f,2.0f)) {
Debug.Log("ENTER");
colided = true;
}
}
}
what am i doing wrong?? the colision detection works perfectly but on the update method it never stops rotate :S
You should do this with coroutine. Call the coroutine function and pass in the GameOjbect to rotate and the angle to rotate to when OnCollisionEnter is called. You can read how this function work here.
Te example below will rotate the GameObject -85 degree in z-axis within 3 seconds.
You can change that to whatever suits you.
public class fallBridge : MonoBehaviour
{
private Rigidbody ball;
public GameObject bridgePivot;
bool rotating = false;
void OnCollisionEnter(Collision other)
{
ball = GameObject.FindWithTag("Player").GetComponent<Rigidbody>();
if (other.gameObject.CompareTag("Player") && ball.transform.localScale == new Vector3(2.0f, 2.0f, 2.0f))
{
Debug.Log("ENTER");
Vector3 rotationAngle = new Vector3(0, 0, -85);
StartCoroutine(RotateObject(bridgePivot, rotationAngle, 3f));
}
}
IEnumerator RotateObject(GameObject gameObjectToMove, Vector3 eulerAngles, float duration)
{
if (rotating)
{
yield break;
}
rotating = true;
Vector3 newRot = gameObjectToMove.transform.eulerAngles + eulerAngles;
Vector3 currentRot = gameObjectToMove.transform.eulerAngles;
float counter = 0;
while (counter < duration)
{
counter += Time.deltaTime;
gameObjectToMove.transform.eulerAngles = Vector3.Lerp(currentRot, newRot, counter / duration);
yield return null;
}
rotating = false;
}
The error is in this line:
bridgePivot.transform.eulerAngles = Vector3.Lerp (bridgePivot.transform.rotation.eulerAngles, to, Time.deltaTime);
When you use Lerp you typically have a fixed beginning and end, and you make the last parameter (t) go from 0 to 1. In your case the endpoint is fixed, the t parameters is fixed also and you vary your start. This means that each update you take a small step towards your goal, but this step is a percentage of the way. So each update you come closer, and your next step will be smaller.
What you should do is remember where you were when you started, and at what time you started. You also need to define a speed for your bridge. Then you can move the bridge from start to end and you get control over the speed.
public class fallBridge : MonoBehaviour {
private Rigidbody ball;
public GameObject bridgePivot;
public float rotateDuration = 2; // Time in seconds
// When you begin rotating you fill these three variables
private float startTime;
private Vector3 from;
private bool rotating = false;
// If the target doesn't change you might as well define it beforehand
private Vector3 to = new Vector3 (0, 0, -85);
void Update () {
if (rotating) {
float t = (Time.time - startTime) / rotateDuration;
if (t < 1) {
bridgePivot.transform.eulerAngles = Vector3.Lerp (from, to, t);
} else {
bridgePivot.transform.eulerAngles = to;
rotating = false;
}
}
}
void OnCollisionEnter(Collision other)
{
ball = GameObject.FindWithTag ("Player").GetComponent<Rigidbody> ();
if (other.gameObject.tag == "Player" && ball.transform.localScale == new Vector3(2.0f,2.0f,2.0f)) {
Debug.Log("ENTER");
startTime = Time.time; // Begin now
from = bridgePivot.transform.eulerAngles; // Remember the start position
rotating = true; // Signal to start rotating
}
}
}
I want to make my spawned objects (enemy prefabs) movement speed up every 10 points my player collects.
This is my movement script, attached to my enemy prefab (so that it can be spawned in my game and move):
public static int movespeed = 20;
public Vector3 userDirection = Vector3.right;
public void Update()
{
transform.Translate(userDirection * movespeed * Time.deltaTime);
}
}
And this is my score script attached to my player:
public Text ScoreText;
public AudioClip Coinsound;
public Text Highscoretext;
public GameObject enemy;
Movement movement;
private int Score;
public int highScore = 0;
void Start ()
{
Score = 0;
SetScoreText ();
if (PlayerPrefs.HasKey ("Highscore"))
{
highScore = PlayerPrefs.GetInt("Highscore");
}
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag ("Pick Up")) {
other.gameObject.SetActive (false);
Score = Score + 1;
SetScoreText ();
AudioSource.PlayClipAtPoint (Coinsound, transform.position);
}
}
As mentioned before I want to make my spawned enemy prefabs to move faster when my player collects every ten points. Thank you :)
You use the % symbol to do that. After adding 1 to Score, Check if there is a reminder when Score is divided by 10. If there is no remainder, increment. Don't increment of there is a remainder.
if (Score % 10 == 0){
//Increment movespeed variable from Movement script
Movement.movespeed += 4;
}
Put the code above in your OnTriggerEnter2D function.
For some reason, this looks very similar to another question but the OP failed to get that answer working.