Crafting System not working in unity why? - c#

So, I made a rudimentary crafting system but the crafting system is not working and I don't know why it doesn't work
public class CraftingItem: MonoBehaviour
{
public int RequiredItems;
public SCItem[] Item;
private GameObject player;
private GameObject playerAction;
public GameObject FinishItem;
public void Start(){
player = GameObject.FindWithTag("Player");
playerAction = GameObject.FindWithTag("ItemManager");
}
public void CheckForRequiredItems(){
int itemsInManager = playerAction.transform.childCount;
if(itemsInManager > 0){
int itemsFound = 0;
for(int i = 0; i < RequiredItems; i++){
for(int z = 0; z < itemsInManager; z++){
if(playerAction.transform.GetChild(z).GetComponent<Item>() == Item[z]){
itemsFound++;
break;
}
}
}
if(itemsFound >= RequiredItems){
Instantiate(FinishItem, transform.position, transform.rotation);
}
}
}
}
unity inspector panel :
I use a scriptable object to make the item, material, and attack items easy to control. Also, this script doesn't tell an error or syntax error, and I little bit confused. can you explain why and how can i fix this?

I bet you wanted "i" there instead of "z" :)
if(playerAction.transform.GetChild(z).GetComponent<Item>() == Item[**i**]){

Related

Why does Audio not Work in my code unity ? unity c#

For some reason, my code is audio not working only... I have no idea why. can someone help? I am using a AudioClip[] my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LevelManage : MonoBehaviour
{
public GameObject[] animals;
public GameObject[] blackAnimals;
Vector3[] animalStartPos;
Vector3[] animalBlackStartPos;
public AudioSource source;
public AudioClip[] Correct;
public AudioClip InCorrect;
void Start()
{
animalStartPos = new Vector3[animals.Length];
animalBlackStartPos = new Vector3[blackAnimals.Length];
for (int i = 0; i < animals.Length; i++)
{
animalStartPos[i] = animals[i].transform.position;
animalBlackStartPos[i] = blackAnimals[i].transform.position;
}
}
//drag
public void dragAnimal(GameObject animal)
{
animal.transform.position = Input.mousePosition;
}
//drop
public void dropAnimal(GameObject animal)
{
int index = System.Array.IndexOf(animals, animal);
float dist = Vector3.Distance(animal.transform.position, blackAnimals[index].transform.position);
if (dist < 75)
{
animal.transform.position = blackAnimals[index].transform.position;
source.clip = Correct[Random.Range(0, Correct.Length)];
source.Play();
}
else
{
animal.transform.position = animalStartPos[index];
source.clip = InCorrect;
source.Play();
}
}
}
The console has errors:
UnassignedReferenceException: The variable source of LevelManage has not been assigned.
You probably need to assign the source variable of the LevelManage script in the inspector.
Please help!
any answers are greatly appreciated.
1) Make sure your clips are imported correctly and actually play in the unity editor by selecting them in the 'Project' panel and playing like this .
2) Make sure your source.volume is NOT 0.
3) Make sure your source.mute is false.
4) Make sure your AudioListener.volume (the global volume) is NOT 0.
5) Make sure your AudioListener.pause (the global pause) is false.
6) Make sure you have 'Mute Audio' toggle in the editor not toggled this is where you can find it

How do I carry over data between scenes in Unity?

For a game I am developing I have a part when if the user gets too close to an enemy it switches scene to a battle scene. However I have no clue how to load that enemy into the battle screen (given that a user can battle many different enemies). Below is my current cod for the enemy. I was wondering if I could carry over it's name into the next scene or something. I just want my enemy to go from one screen to another when the scene is changed. Code would be appreciated thankyou
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FolllowAndLoad : MonoBehaviour
{
public Transform target;
public Animator anim;
public Rigidbody2D myRigidBody;
public string levelToLoad;
private static string keyname; // value I want to carry over
public float MoveSpeed;
private bool checkTrigger;
public Rigidbody2D targetRigidBody;
void Start()
{
target = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();//getting the position of our player
anim = GetComponent<Animator>();
myRigidBody = GetComponent<Rigidbody2D>(); //getting my components
targetRigidBody = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody2D>();
}
void Update()
{
float distance = Vector2.Distance(target.position, myRigidBody.transform.position); //getting the distance between our player and our enemy
if (distance < 5)
{
transform.position = Vector2.MoveTowards(transform.position, target.position, MoveSpeed * Time.deltaTime); //moving our enemy towards our player
anim.SetBool("checkTrigger", true);
anim.SetFloat("MoveX", moveXvalue()); //updating the animations for our enemy
anim.SetFloat("MoveY", moveYvalue());
}
else if (distance > 5) //if out of range stop walking
{
anim.SetBool("checkTrigger", false);
}
}
int moveXvalue()
{
int value;
if (myRigidBody.transform.position.x < target.transform.position.x && Mathf.Abs(target.position.y - myRigidBody.position.y) < Mathf.Abs(target.position.x - myRigidBody.position.x)) //these are saying if the enemy is closer in x than in y use x animations and vice versa
value = 1;
else if (myRigidBody.transform.position.x > target.transform.position.x && Mathf.Abs(target.position.y - myRigidBody.position.y) < Mathf.Abs(target.position.x - myRigidBody.position.x))
value = -1;
else
value = 0;
return value;
}
int moveYvalue()
{
int value;
if (myRigidBody.transform.position.y < target.transform.position.y && Mathf.Abs(target.position.y - myRigidBody.position.y) > Mathf.Abs(target.position.x - myRigidBody.position.x))
value = 1;
else if (myRigidBody.transform.position.x > target.transform.position.x && Mathf.Abs(target.position.y - myRigidBody.position.y) > Mathf.Abs(target.position.x - myRigidBody.position.x))
value = -1;
else
value = 0;
return value;
}
public void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.name == "Player")
{
Debug.Log(gameObject.name);
anim.SetBool("checkInContact", true);
Application.LoadLevel (levelToLoad); //loading our level
}
}
}
There are a lot of ways to do this, but the simplest way to get something working quickly just until you get more familiar with Unity it to use a simple static class in your project that you can access from any script in any scene.
So if you were to make a new script in your project right now called SharedResources.cs and then pasted this into the script and saved it....
public static class SharedResources
{
public const int kSceneIs_TitleScene = 0;
public const int kSceneIs_ActualGameScene = 1;
public const int kSceneIs_HighScoreScene = 2;
public static int highScore = 0;
public static int enemyID = 0;
public static void sampleFunction()
{
//this is a sample method you can call from any other script
}
}
You could now be in a script in one scene and do this
SharedResources.highScore=SharedResources.highScore+20;
SharedResources.enemyID=5;
You could then open up a new scene and a script in that scene could access the high score
Debug.Log(SharedResources.highScore)
Debug.Log(SharedResources.enemyID)
You can also access constant and run subroutines that are in the static class as shown above.
The correct way to do this is up for debate and really depends on what your ultimate goal is. I will reference another link to a post that goes into more detail....
https://gamedev.stackexchange.com/questions/110958/unity-5-what-is-the-proper-way-to-handle-data-between-scenes
Ideally, you should read and understand the difference between using a simple static class versus one that derives from MonoBehavior, and also the different between a static class and a Singleton, which in many ways is much more powerful (but can also cause issues if you don't code it correctly)
Last but not least, don't forget you can also use the built in PlayerPrefs function in Unity to store scores and other settings that need to carry over between launches of the game....
https://answers.unity.com/questions/1325056/how-to-use-playerprefs-2.html

C# - Unity crashes with this code - creating Transform array based on GameObject tag

I'm working in a 3D environment, a house, with 16 rooms. In each room I placed an invisible cube with a tag called "RoomsToScanTag". I'm working with an asset called Behavior Designer, and in my inspector I have given the tagname to look for (in this case "RoomsToScanTag"). With this tagname, I want the robot to go to room1 first, then continue to room2, up to room16.
This is my code
using UnityEngine;
using BehaviorDesigner.Runtime;
using BehaviorDesigner.Runtime.Tasks;
public class MoveTowardsNew : Action
{
private Transform[] roomsToScanHAHA;
public string targetTagRooms;
public Transform targetyo;
int i = 0;
int controlNumber = 0;
public override void OnAwake()
{
var targets = GameObject.FindGameObjectsWithTag (targetTagRooms);
roomsToScanHAHA = new Transform[targets.Length];
for (int i = 0; i < targets.Length; i++) {
roomsToScanHAHA [i] = targets [i].transform;
}
}
public override TaskStatus OnUpdate()
{
while (controlNumber < roomsToScanHAHA.Length)
{
targetyo = roomsToScanHAHA [controlNumber];
if (Vector3.SqrMagnitude (transform.position - targetyo.position) < 0.5f)
{
if (controlNumber < roomsToScanHAHA.Length) {
controlNumber++;
}
return TaskStatus.Success;
}
}
NavMeshAgent agent = GetComponent<NavMeshAgent> ();
agent.destination = targetyo.position;
return TaskStatus.Running;
}
}
My problem
Unity crashes... It has something to do with this code, I can't figure it out. Anyone has an idea what is going wrong?
Here is an image of what I'm dealing with:
Thanks in advance!
As usual, Its the while loop which is not terminating:
while (controlNumber < roomsToScanHAHA.Length)
{
targetyo = roomsToScanHAHA [controlNumber];
if (Vector3.SqrMagnitude (transform.position - targetyo.position) < 0.5f)
{
if (controlNumber < roomsToScanHAHA.Length) {
controlNumber++;
}
return TaskStatus.Success;
}
}
First run: controlNumber = 0;
lets say your first element in array roomsToScanHAHA doesn't match the condition : (Vector3.SqrMagnitude (transform.position - targetyo.position) < 0.5f). controlNumber wont be incremented and would keep checking the condition for the first element. Which results in infinite loop.
So you can change your code to something like this:
while (controlNumber < roomsToScanHAHA.Length)
{
targetyo = roomsToScanHAHA [controlNumber];
if (Vector3.SqrMagnitude (transform.position - targetyo.position) < 0.5f)
{
return TaskStatus.Success;
}
controlNumber++;
}
Hope this helps

Prefab doesnot activate when collide with object

I'm making a project and there is a problem that I am facing.
I have two gameObject with 2D colliders (coming from a prefab) which moves right to left. When they touch each other they deactivate.
I also have an empty game object in which i add a script Respawner which randomly generates obstacles.
The problem is when they touch each other once, they never get re-activated again.
Respawner Empty GameObject :
Border :
Prefabs :
Respawn Script:
public class Respawn : MonoBehaviour {
[SerializeField]
private GameObject[] obstacles;
private List<GameObject> listname = new List<GameObject>();
void Awake(){
InitilizeObstacle();
}
void Start() {
StartCoroutine(RandomObstacleSpawn());
}
void InitilizeObstacle(){
int index = 0;
for (int i=0; i<obstacles.Length * 3 ; i++) {
GameObject obj = Instantiate(obstacles[index],new Vector3(transform.position.x,transform.position.y,-2f),Quaternion.identity) as GameObject;
listname.Add(obj);
listname[i].SetActive(false);
index++;
if(index==obstacles.Length){
index =0;
}
}
}
void shuffle(){
for (int i=0; i<listname.Count; i++) {
GameObject temp = listname [i];
int random = Random.Range (i, listname.Count);
listname [i] = listname [random];
listname [random] = temp;
}
}
IEnumerator RandomObstacleSpawn(){
yield return new WaitForSeconds(Random.Range(1.5f,2.5f));
int index = Random.Range (0, listname.Count);
while (true) {
if(!listname[index].activeInHierarchy){
listname[index].SetActive(true);
listname[index].transform.position = new Vector3(transform.position.x,transform.position.y,-2f);
break;
} else {
index = Random.Range(0,listname.Count);
}
StartCoroutine(RandomObstacleSpawn());
}
}
}
Script attach to prefab for move:
public class ObstacleMove : MonoBehaviour {
private float speed = -1.25f;
void Start() { }
void Update() {
Vector3 pos = transform.position;
pos.x += speed * Time.deltaTime;
transform.position = pos;
}
}
Scripts attach to prefab for touch border:
public class BorderTouch : MonoBehaviour {
void OnTriggerEnter2D(Collider2D target){
if(target.tag=="Border"){
gameObject.SetActive(false);
}
}
}
New answer based on new question:
If you want to make things happen AFTER the collision. Put a script on Border:
using UnityEngine;
using System.Collections;
public class borderListener : MonoBehaviour {
public Respawn rS;
void OnTriggerEnter2D(Collider2D target){
rS.spawnIt ();
}
}
On Unity Editor, drag the Respawn object to the Border Script on hierarchy.
Do not skip this step or things won't work!
On Respawn script, remove the last StartCoroutine(RandomObstacleSpawn()); line on IEnumerator RandomObstacleSpawn() method. And create a public method (to access from other script) anywhere inside Respawn script:
public void spawnIt(){
StartCoroutine(RandomObstacleSpawn());
}
Old answer based on old code:
From what I see on your package:
while (true) { //A
if(!listname[index].activeInHierarchy){
//B
listname[index].SetActive(true);
listname[index].transform.position = new Vector3(transform.position.x,transform.position.y,-2f);
break; //C
} else {
index = Random.Range(0,listname.Count);
}
StartCoroutine(RandomObstacleSpawn()); //D
}
I am a lil noob, I will try my best to help. But this piece of code makes me wonder:
while(true) what? what is true? (EDIT: found some observation bellow)
The code seem to do this path:
Go inside the while loop (A)
Go at the first option in if statement (B)
Go to the line break; (C)
Never reaches the StartCoroutine (D) > that is why it does not activate again.
If you try and put a StartCoroutine(RandomObstacleSpawn()); before the break; you probably will get an Unity crash. What if you take off the while statement at all? You need to adjust time of yield tho.
This is the code I would use:
IEnumerator RandomObstacleSpawn(){
yield return new WaitForSeconds(Random.Range(3.5f,4.5f));
int index = Random.Range (0, listname.Count);
if(!listname[index].activeInHierarchy){
listname[index].SetActive(true);
listname[index].transform.position = new Vector3(transform.position.x,transform.position.y,-2f);
}else{
index = Random.Range(0,listname.Count);
}
StartCoroutine(RandomObstacleSpawn());
}
EDIT: about the while(true) I've manage to find more information about this concept here: R, How does while (TRUE) work?
But still... the break; on the code is really making the Access to StartCoroutine(RandomObstacleSpawn()); unreachable .
The problem you are seeing is fairly common, when the following code is executed gameObject.SetActive(false); it deactivate everything on that gameObject.
Thus, the next time they would have collided will never be triggered.
I'm not sure what you want to achieve for the behaviour, but if you just want to hide the gameObjects you could disable the Renderer component instead.
gameObject.GetComponent<SpriteRenderer>().enable = false;
And switch it to true when needed.
That's why we must be carefull when we use SetActive(false) on gameObject in Unity.

Android Controller for Unity game

I was making game in Unity 3D
and used the one click converter of unity to convert it in Android .apk
The game is opening in Android phone
but the player is not moving
Player controller Script:
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
public Vector2 moving = new Vector2();
public int Bulletlimit = 0;
public int MaxBulletlimit = 3;
public bool Gun;
private float lastShotTime ;
public float fireDelay = 0.2f;
public Transform BulletDirection;
public Bullet bullet;
// Use this for initialization
void Start () {
lastShotTime = Time.time;
}
// Update is called once per frame
void Update () {
moving.x = moving.y = 0;
if (Input.GetKey ("right")) {
moving.x = 1;
} else if (Input.GetKey ("left")) {
moving.x = -1;
}
if (Input.GetKey ("up")) {
moving.y = 1;
} else if (Input.GetKey ("down")) {
moving.y = -1;
}
if (Input.GetKey ("s")) {
if(Gun){
if(Bulletlimit < MaxBulletlimit)
{
if(Time.time > lastShotTime + fireDelay)
{
Bullet clone = Instantiate (bullet, BulletDirection.position, Quaternion.identity) as Bullet;
Bulletlimit = Bulletlimit + 1;
lastShotTime = Time.time;
}
}
}
}
}
public void BulletCount()
{
Bulletlimit = Bulletlimit - 1;
}
}
How do I make him move in touch screens?
Your code is based on keystrokes - that (probably) wont apply to your touch screen.
There are a few ways you could do this, for something so simple I would probably try adding a Canvas along with some buttons to act as controls.
From there you can use the OnMouseDown()/OnMouseUp()/OnClick() methods (This also converts to touchscreens) instead of keystrokes.
How you code from there is a choice you have to make but in this case I would likely use the buttons to turn on/off movement bools and check/apply them in the Update() method.
If you're unsure of how to use the new unity UI try this...
https://unity3d.com/learn/tutorials/modules/beginner/ui/ui-canvas
If you're running the new version of unity (currently 5.1 I believe), my editor looks different to the tutorials and won't stay as default for some reason. Simply set the editor/inspector view to default if some of the options appear to be missing.
There are more complex things you can do with the actual touch inputs but I don't think you need to worry about it in this particular case.
Hope this helps :)

Categories