I am attempting to implement some basic functionality in Unity using this script attached to an empty which has 6 child objects. I have tried various fixes in my code, but cant seem to achieve the desired result.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectSelector : MonoBehaviour
{
// This array stores the Prefabs
public GameObject[] ObjectArray;
// Integer for stepping through array Prefabs
private int selectedObject = 0;
// Location to instantiate the prefab
private Transform locator;
// Holds the currently instantiated Prefab in the scene
private GameObject tempMesh;
void Start()
{
// Instantiate initial Prefab
tempMesh = Instantiate(ObjectArray[selectedObject], locator.position, locator.rotation);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.RightArrow))
{
// Step to next position in array
ObjectArray++;
// Remove previously instantiated prefab from hierarchy
Destroy(tempMesh);
// Instantiated next Prefab
tempMesh = Instantiate(ObjectArray[selectedObject], locator.position, locator.rotation);
// Print Counter for debug
print(ObjectArray);
// If Array count excedes Array index then go back to first position in array
if (ObjectArray >= ObjectArray.Length)
{
ObjectArray = 0;
}
}
}
}
You are incrementing an array, you need to increment your counter
void Update()
{
if (Input.GetKeyDown(KeyCode.RightArrow))
{
// Step to next position in array
selectedObject++;
// If Array count exceeds Array index then go back to first position in array
if (selectedObject >= ObjectArray.Length)
{
selectedObject = 0;
}
// Remove previously instantiated prefab from hierarchy
Destroy(tempMesh);
// Instantiated next Prefab
tempMesh = Instantiate(ObjectArray[selectedObject], locator.position, locator.rotation);
// Print Counter for debug
print(selectedObject);
}
}
Related
I need a little help again please. I'm currently working on powerups and it's setup so that the powerup affectsthe prefab thats put into its prefab slot, so this is means it is currently only affecting one object (in my case, enemy). When the game starts I spawn about 20 enemies and if i pickup the powerup I want it to affect all those spawned enemies and not only the one that is dragged onto the script, does anyone have a solution or alternate method to do this please?
When instantiate them store them in a list and then iterate through all and update their value
In your case e.g.
// if enemies have a certain Component rather use that type here instead of GameObject
public GameObject enemyPrefab;
// and use the same type here instead of GameObject
private List<GameObject> enemyInstances = new List<GameObject> enemyInstances;
private void Start()
{
for(int i = 0; i < 20; i++)
{
var newEnemy = Instantiate(enemyPrefab);
enemyInstances.Add(newEnemy);
}
}
and then later
public void UpdateEnemies()
{
foreach(var enemy in enemyInstances)
{
// skip already destroyed objects
if(!enemy) continue;
// whatever to be done to the enemies
}
}
To get all game objects to an array you can use the Tag.
Just add an 'Enemy' tag to the prefab and use the code below:
public GameObject[] enemys;
void Start()
{
respawns = GameObject.FindGameObjectsWithTag("Enemy");
}
Full Unity documentation HERE
I need your help with things that are going to blow up my mind...(Don't know why but I can't write "Hello everybody!" at the start of the post. Forum hides it:)
I can't figure out why my List <'My Tile Class> is cleared by itself.
I have few prefabs (with box-collider) with no scripts attached to them and one script on the scene. The idea is to take random prefab, attach random value to it and initiate it. After that player clicks on prefab on the scene and gets its value.
public class Generate_Field : MonoBehaviour {
public class Tiles {
public GameObject My_Tile;
public int My_Value;
}
public List<Tiles> My_List;
private GameObject EmptyObj;
// ... other variables
void Start (){
List<Tiles> My_List = new List<Tiles> ();
// ... below some calculation (about 100 rows)
//Instantiate obj and give its reference to Emptyobj
EmptyObj = Instantiate (My_GameObj_To_Inst, new Vector3(My_X, My_Y, 0f), Quaternion.identity);
Tiles Tile1 = new Tiles ();
Tile1.My_Tile = EmptyObj;
Tile1.My_Value = 1; //
My_List.Add (Tile1); // Add Tile1 (with reference to Gameobj and value to List)
// If I put code inside Void Start () it works ok and print all values
foreach (Tiles SS in My_List) {
print (SS.My_Value);
}
The problem is when I put it to Void Update ().
My_List somehow "Suicide" to zero.count although it is public List. In that case I get error:
"NullReferenceException: Object reference not set to an instance of an object..."
void Update ()
{
if (Input.GetKeyDown (KeyCode.Mouse1)) {
print (My_List.Count);
}
}
You declare a new local list in Start and populate that one. If you mean to initialise the class member, remove the type from the line doing the initialisation.
void Start (){
My_List = new List<Tiles> (); // class member, not new variable.
As a usual guideline, it's better to initialise lists at the declaration point. There's usually no reason to replace the list at a later time.
I have this quiz game that runs with series of 5 questions per category. I want to add an audio when the user pressed the correct answer or incorrect answer. How can i make is possible that when i press the incorrect or correct answer an audio file will play?
Here's my code of the levelcontrolscript2 that runs in the question's scenes.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelControlScript2 : MonoBehaviour
{
// Get references to game objects that should be disabled and enabled
// at the start
GameObject[] toEnable, toDisable;
// References to game objects that should be enabled
// when correct or incorrect answer is given
private int triesLeft = 2; // Set this to 1 (leave after second) or
whatever when a level starts
public GameObject correctSign, incorrectSign, incorrectSign2;
// Variable to contain current scene build index
int currentSceneIndex;
// Use this for initialization
void Start () {
// Getting current scene build index
currentSceneIndex = SceneManager.GetActiveScene ().buildIndex;
// Finding game objects with tags "ToEnable" and "ToDisable"
toEnable = GameObject.FindGameObjectsWithTag ("ToEnable");
toDisable = GameObject.FindGameObjectsWithTag ("ToDisable");
// Disabling game objects with tag "ToEnable"
foreach (GameObject element in toEnable)
{
element.gameObject.SetActive (false);
}
}
// Method is invoked when correct answer is given
public void RightAnswer()
{
// Disabling game objects that are no longer needed
foreach (GameObject element in toDisable)
{
element.gameObject.SetActive (false);
}
// Turn on "correct" sign
correctSign.gameObject.SetActive (true);
// Invoke GotoMainMenu method in 1 second
Invoke ("LoadNextLevel", 1f);
}
// Method is invoked if incorrect answer is given
public void WrongAnswer()
{
// Disabling game objects that are no longer needed
foreach (GameObject element in toDisable)
{
element.gameObject.SetActive (false);
}
// Turn on "incorrect" sign
incorrectSign.SetActive (true);
// Disabling game objects that are no longer needed
foreach (GameObject element in toDisable)
{
element.gameObject.SetActive (true);
}
triesLeft--;
if(triesLeft <= 0)
{
// Disabling game objects that are no longer needed
foreach (GameObject element in toDisable)
{
element.gameObject.SetActive (false);
}
// Turn on "incorrect" sign
incorrectSign2.SetActive (true);
// Invoke GotoMainMenu method in 1 second
Invoke ("GotoCategories", 1f);
}
}
// Method loads next level depending on current scenes build index
void LoadNextLevel()
{
SceneManager.LoadScene (currentSceneIndex + 1);
}
// Method loads Category scene
void GotoCategories()
{
SceneManager.LoadScene ("Easy");
}
}
You will need to use AudioSource & AudioClips for this. Simply put these variables in script and assign the values at runtime.
public class LevelControlScript2 : MonoBehaviour
{
// Get references to game objects that should be disabled and enabled
// at the start
GameObject[] toEnable, toDisable;
// References to game objects that should be enabled
// when correct or incorrect answer is given
private int triesLeft = 2; // Set this to 1 (leave after second) or whatever when a level starts
public GameObject correctSign, incorrectSign, incorrectSign2;
public AudioSource _audioSource;
public AudioClip _incorrect;
public AudioClip _correct;
// Variable to contain current scene build index
int currentSceneIndex;
// Use this for initialization
void Start()
{
// Getting current scene build index
currentSceneIndex = SceneManager.GetActiveScene().buildIndex;
// Finding game objects with tags "ToEnable" and "ToDisable"
toEnable = GameObject.FindGameObjectsWithTag("ToEnable");
toDisable = GameObject.FindGameObjectsWithTag("ToDisable");
// Disabling game objects with tag "ToEnable"
foreach (GameObject element in toEnable)
{
element.gameObject.SetActive(false);
}
}
// Method is invoked when correct answer is given
public void RightAnswer()
{
// Disabling game objects that are no longer needed
foreach (GameObject element in toDisable)
{
element.gameObject.SetActive(false);
}
// Turn on "correct" sign
correctSign.gameObject.SetActive(true);
_audioSource.clip = _correct;
_audioSource.Play();
// Invoke GotoMainMenu method in 1 second
Invoke("LoadNextLevel", 1f);
}
// Method is invoked if incorrect answer is given
public void WrongAnswer()
{
// Disabling game objects that are no longer needed
foreach (GameObject element in toDisable)
{
element.gameObject.SetActive(false);
}
// Turn on "incorrect" sign
incorrectSign.SetActive(true);
// Disabling game objects that are no longer needed
foreach (GameObject element in toDisable)
{
element.gameObject.SetActive(true);
}
triesLeft--;
if (triesLeft <= 0)
{
// Disabling game objects that are no longer needed
foreach (GameObject element in toDisable)
{
element.gameObject.SetActive(false);
}
// Turn on "incorrect" sign
incorrectSign2.SetActive(true);
_audioSource.clip = _incorrect;
_audioSource.Play();
// Invoke GotoMainMenu method in 1 second
Invoke("GotoCategories", 1f);
}
}
// Method loads next level depending on current scenes build index
void LoadNextLevel()
{
SceneManager.LoadScene(currentSceneIndex + 1);
}
// Method loads Category scene
void GotoCategories()
{
SceneManager.LoadScene("Easy");
}
}
So basically assign your correct & incorrect audio clip to _incorrect & _correct to these variables. Then you will need to attach a audio source to game object in scene and assign it to a script. And then just say _audioSource.Play(). This should allow you to play the required clips. More details are located in unity manual on the AudioSource & AudioClip settings. The above answer works on the condition that you are just playing audio clip.
Another thing I noticed in your question title but not in body is play an audio file then the gameobject is set to active? If you want to activate some gameobject after playing a audio then here is solution for that also:
source.Play(clip);
StartCoroutine(MyCoroutine(clipLength));
& here is the coroutine snippet:
private IEnumerator MyCoroutine(float clipLength)
{
yield return new WaitForSeconds(clipLength);
//activate your gameobject here
}
Callback for AudioClip finished use this reference for that
I want to instantiate several instances of a prefab into an array each with their own index number but i keep getting the error code "object reference not set to an instance of an object. How can I get rid of this error and how can I destroy individual objects or retrieve the properties of each individual game object in the array?
using UnityEngine;
using System.Collections;
public class SpawnEnemy : MonoBehaviour {
private GameObject[] enemy;
public GameObject enemyPrefab;
// Use this for initialization
void Start () {
enemy[1] = (GameObject)Instantiate (enemyPrefab, new Vector3 (-119, 52, 483), transform.rotation);
}
// Update is called once per frame
void Update () {
if (Input.GetButtonDown ("Fire2")) {
Destroy (enemy[1]);
}
}
}
As DrUsh mentiones, you need to initialize the array, e.g. like this:
void Start()
{
// initialize array with a size of 5, all elements are empty
enemy = new GameObject[5];
// now you can work with this array, e.g. like you line:
enemy[1] = (GameObject)Instantiate (enemyPrefab, new Vector3 (-119, 52, 483), transform.rotation);
}
The downside of using arrays is that you will have a fixed number of elements (5 in my example). If you don't know the exact number of objects you want at max at the same time stored into your array, you are better of using a List<GameObject> which can be resized dynamically. This also needs to be initialized by putting enemy = new List<GameObject>().
Also, you probably don't want to access the array/list with hardcoded indices. I don't know if that was just for example and you have a better, automated way to create gameobject-index pairs though.
You have not instantiated the array before you set the value for enemy[1]. Also, the index should be 0, not 1, i.e. enemy[0] = ... because the index of a C# array starts from 0.
You can instantiate and set using the below.
enemy = new[]
{
(GameObject)Instantiate(enemyPrefab,
new Vector3 (-119, 52, 483), transform.rotation)
};
im creating a game where the player needs to find and pick up a certain number of keys. Currently ive got a spawn container that generates 5 keys in given locations. I want to be able to generate the 5 keys in 5 random locations. So lets say i have 10 spawn points, i want it to randomly pick any of the 5 points and place a key there.
I have the following code so far
using UnityEngine;
using System.Collections;
public class KeySpawnManager : MonoBehaviour
{
// array to store spawnpoints
private Transform[] spawnTransformList;
// integer to store number of spawnpoints
private int numberOfSpawnpoints;
// the prefab we're going to spawn
public GameObject prefab;
private int collectedCount = 0;
private int currentTime = 0;
// Singleton Instance
public static KeySpawnManager Instance { get; private set; }
// AWAKE Function - fired on initialization
void Awake ()
{
if (Instance == null) Instance = this;
else Destroy( gameObject );
numberOfSpawnpoints = transform.childCount;
spawnTransformList = new Transform[numberOfSpawnpoints];
for (int i = 0; i < numberOfSpawnpoints; i++)
{
// add the spawn to the array
spawnTransformList[i] = transform.GetChild(i); // return transform Component of each child object
}
for (int j = 0; j < numberOfSpawnpoints; j++)
{
GameObject newPrefab = (GameObject) Instantiate(prefab, spawnTransformList[j].position, spawnTransformList[j].rotation);
newPrefab.transform.parent = transform.position;
}
}
}
Any ideas on how to do this?
thanks
create your ten empty gameobject in a list then shuffle the list using Fisher-Yates shuffle then use the first five elements of the list and spawn keys in them
Here is the implementation of a Fisher-Yates shuffle in c#
Create a random method using random class that you can pass in the total number of spawn points. Have it return then index for your spawn location.