I want to make it so when I click on the enemy, an ammo drop appears on the screen - monogame

Here is my code piece of code (I already have it so that when you click a ghost the ammo spawns, I just didn't include that because it was in a procedure.) My problem is with the RNG spawning of the ammo; it works fine at first and then after like 20 seconds it just does not spawn at all.
private void ammoSpawn()
{
ammoSpawner = rng.Next(1, 101);
if (ammoSpawner > 50)
{
ammoTimer.Activate();
if (ammoTimer.IsActive())
{
ammoRec.X = rng.Next(100, 1720);
ammoRec.Y = rng.Next(100, 700);
if (ammoTimer.IsFinished())
{
ammoRec.X = -100;
ammoRec.Y = -100;
ammoTimer.ResetTimer(true);
}
}
}
}
Any help is appreciated

I'm guessing that you're reusing the same ammo object, and that the variables such as ammoSpawner and ammoTimer are public variables in game1.
I would recommend creating a seperate class for the ammo object. So all related code can remain in the ammo object, and that also makes it easier to create multiple items. (In case you're going to expand on that in the future)
An example of a create method in the Ammo Class:
int spawner = 0;
int timer = 0;
Texture2D ammoSprite = new Texture2D;
Rectangle rec = new Rectangle(x, y, width, height);
public void Ammo(Texture2D ammoSprite, _spawner, _timer) //this should be the constructor that creates the class
{
spawner = _spawner;
timer = _timer;
rec.X = rng.Next(100, 1720);
rec.Y = rng.Next(100, 700);
}
public void Update()
{
//function where you put your update logic for the ammo object
}
public void Draw(Spritebatch spriteBatch)
{
//function where you put your draw logic for the ammo object
spriteBatch.Draw(ammoSprite, rect, Color.White);
}
then in the place where you'll use the ammo Class:
public Ammo ammo = null; //declared as a field on top of the page
private void ammoSpawn()
{
Ammo ammo = new Ammo(); //creating an Ammo object, should be inside
}
public void Update()
{
ammo.Update();
}
public void Draw()
{
SpriteBatch spriteBatch = new SpriteBatch();
ammo.Draw(spriteBatch);
}
Creating classes for objects are a core concept in C# to be able to reuse them. This also allows you to create multiple items/enemies that behave differently, but still keep the basic functions. I'd certainely recommend to learn about classes.

Related

How to Randomly disable box collider in unity

i have two simple 3d cube objects a,b. so my task is to randomly disable box collider one of the object every time game start.
my initial thought is randomly generate Boolean and if it is false then disable the box collider.
You can add you cube's to array and use Random.Range(0, yourArray.Length) to get index of the cube which should be deactivated. In your case it will be some overhead but this solution will be work for different cube`s count in the future.
In code it will looks like:
// You can serialize this array and add cubes from Inspector in Editor
// or add script with this code to the parent gameobject
// and use GetComponentsInChildren<BoxCollider>() to get all colliders
var cubes = new BoxCollider[2] {firstCube, secondCube};
var cubeToDeactivationIndex = Random.Range(0, cubes.Length);
cubes[cubeToDeactivationIndex].enabled = false;
About your second question. If I understand correctly, implementation will be next:
using System;
using UnityEngine;
using UnityEngine.Assertions;
using Random = UnityEngine.Random;
// Interface need to provide limited API
// without open references to gameobject and transform of the object
public interface ICollidable
{
event Action<ICollidable> OnCollided;
int HierarchyIndex { get; }
void DisableCollider();
}
// This component you should add to the object which will collide with player
public class CollidableObject : MonoBehaviour, ICollidable
{
[SerializeField]
private Collider _objectCollider;
public event Action<ICollidable> OnCollided;
public int HierarchyIndex => transform.GetSiblingIndex();
private void Start()
{
Assert.IsNotNull(_objectCollider);
}
//Here you can use your own logic how to detect collision
//I written it as example
private void OnCollisionEnter(Collision collision)
{
if (collision.transform.CompareTag("Player")) {
OnCollided?.Invoke(this);
}
}
public void DisableCollider()
{
_objectCollider.enabled = false;
}
}
// This component should be on the parent gameobject for your `
// collidable objects. As alternative you can serialize array
// and add all collidable objects from the Inspector but in that
// case signature of the array should be CollidableObject[]
// because Unity can`t serialize interfaces
public class RamdomizedActivitySwitcher : MonoBehaviour
{
private ICollidable[] _collidableObjects;
private void Awake()
{
_collidableObjects = GetComponentsInChildren<ICollidable>(true);
foreach (var collidable in _collidableObjects)
{
collidable.OnCollided += DisableObjectWhenMatch;
}
}
private void DisableObjectWhenMatch(ICollidable collidedObject)
{
var randomIndex = Random.Range(0, _collidableObjects.Length);
if (randomIndex == collidedObject.HierarchyIndex) {
collidedObject.DisableCollider();
}
}
}
}

How can I make a variable that I can access in any unity scene? - Unity

I want to make a variable I can access in any unity scene.
I need this to see what level the player was in before death, so he can respawn at the level he died.
Please say the best method to do this if you can.
There might be other ways of doing this but I have got to know these two.
Either: You can create a static class like this.
public static class Globals
{
const int ScreenFadingIn = -1;
const int ScreenIdle = 0;
const int ScreenFadingOut = 1;
public static float ScreenFadeAlpha = 1.0f;
public static int ScreenFadeStatus = ScreenFadingIn;
}
Code took from this thread C# Global Variables Available To All Scenes
OR: You can create a gameobject and attach the script which contains your desired variable and make that put line DontDestroyOnLoad(this);
Like this
void Awake() {
if(Instance != null) {
Destroy(this.gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(this);
}

Unity3d Sprite change with prefabs

Ive a question about how to change spirte images during runtime for a bunch of objects.
So i made a tiny racer 2d game, and therefore you can choose differend themes. You have this option in an integraded menu (not a seperate scene).
My question:
Can i switch the sprites easy during the runtime? Ive made prefabs for each track element - and i changed the sprites of those prefabs, but the change only gets visible, after the scene is reloaded. So i would need to avoid this.
Has someone a solution or a hint how i could do that?
Thanks in advance!
Code:
public class Background_Controller : MonoBehaviour {
public Camera mainCamera;
public Color colorNormal;
public GameObject[] Prefabs;
public Sprite[] normalSprites;
public Sprite[] tronSprites;
// Use this for initialization
void Awake () {
SwitchBackgroundFunction();
}
public void SwitchBackground(string Theme)
{
switch(Theme)
{
case "GreenHell":
PlayerPrefs.SetString("Theme", "Normal");
break;
case "NeonCity":
PlayerPrefs.SetString("Theme", "Tron");
break;
}
SwitchBackgroundFunction();
}
private void SwitchBackgroundFunction()
{
int prefabCount = Prefabs.Length;
if (PlayerPrefs.GetString("Theme") == "Normal")
{
mainCamera.backgroundColor = colorNormal;
for (int i = 0; i <= prefabCount - 1; i++)
{
Prefabs[i].GetComponent<SpriteRenderer>().sprite = normalSprites[i];
}
}
if (PlayerPrefs.GetString("Theme") == "Tron")
{
mainCamera.backgroundColor = Color.black;
for (int i = 0; i <= prefabCount - 1; i++)
{
Prefabs[i].GetComponent<SpriteRenderer>().sprite = tronSprites[i];
}
}
}
// Update is called once per frame
void Update () {
}
}
You can do something along the following lines to swap in a sprite from within your resources folder during runtime.
Sprite spr;
spr = Resources.Load<Sprite>("mysprite"); //insert name and file path to sprite within Resources folder
GetComponent<SpriteRenderer>().sprite = spr;

Object not destroying after reaching a certain point Unity

Okay so i'm making an infinite runner and the technique I've used is to keep the player static and move and instantiate the platform objects.
For that I've created an Array List of objects that are the platforms.
And then I'm adding them in and spawning them.
I am also translating them along the z-axis and i want to destroy the objects that go below 0 in the z axis and then add another object in replacement.
The problem is that it doesn't translate the objects unless I add another script just to do that and it doesn't destroy or add even if I add another script for translation.
My code is as follows. If you have trouble understanding my problem, please ask I would try to explain again.
I have two scripts.
1) PlatformManager: This one is applied on the empty GameObject and contains the ArrayList.
public class PlatformManager : MonoBehaviour
{
[HideInInspector]
public List<GameObject> platforms = new List<GameObject>(); // List of Platfroms.
public GameObject[] prefab; // Allow user to add as many prefabs through the inspactor.
public static float noOfPlatforms; // a variable to hold how many platoforms.
[HideInInspector]
public static float objectPosition; // Z position of the game object.
[HideInInspector]
public static float objectScale;
// Use this for initialization
void Start ()
{
noOfPlatforms = 6.0f;
objectPosition = 0.0f;
objectScale = 0.0f;
platforms.Add((GameObject)Instantiate(prefab[Random.Range(0,prefab.Length)], new Vector3(0,0,0) ,Quaternion.identity));
//platforms.Add((GameObject)Instantiate(prefab[Random.Range(0, prefab.Length)], new Vector3(0, 0, 40.40114f), Quaternion.identity));
for(int i = 0; i < noOfPlatforms; i++){
objectScale = platforms[platforms.Count-1].transform.localScale.z;
objectPosition = platforms[platforms.Count-1].transform.localPosition.z;
platforms.Add((GameObject)Instantiate(prefab[Random.Range(0,prefab.Length)], new Vector3(0,0,(objectPosition + objectScale)+277f) ,Quaternion.identity));
}
}
// Update is called once per frame
void Update ()
{
}
}
2) PlatformController: This one is supposed to instantiate and destroy and translate the objects.
public class PlatformController : MonoBehaviour {
//private bool canBeDestroy = true; // Flag to check whether the gameObject shoud be destroyed or not.
[HideInInspector]
public PlatformManager managePlateform; // Reference to plateformManager script.
[HideInInspector]
public float plateformSpeed = 10f;
[HideInInspector]
public GameObject allPlatforms;
[HideInInspector]
// Awake is called when the script instance is being loaded.
void Awake()
{
// Accessing the plateformManager script for the Plateform.
managePlateform = GameObject.FindGameObjectWithTag("Platform").GetComponent<PlatformManager>();
}
void Start()
{
}
// Update is called once per frame
void Update()
{
// Get the first platform object.
GameObject firstPlatform = managePlateform.platforms[0];
// Get the last platform object.
GameObject lastPlatform = managePlateform.platforms[managePlateform.platforms.Count - 1];
if (firstPlatform.transform.localPosition.z < 0f)
{
Destroy(firstPlatform.gameObject); // destroy the first plateform gameObject.
managePlateform.platforms.Remove(firstPlatform); // also remove the destroyed object from the list.
// When the game object is destroyed then instantiate one gameobject into list and add at the last point.
managePlateform.platforms.Add((GameObject)Instantiate(managePlateform.prefab[Random.Range(0, managePlateform.prefab.Length)], new Vector3(0, 0, (lastPlatform.transform.localPosition.z + lastPlatform.transform.localScale.z) + 277f), Quaternion.identity));
}
// Move the available platforms in the list along the z-axis
foreach (GameObject platform in managePlateform.platforms)
{
platform.transform.Translate(0, 0, -plateformSpeed * Time.deltaTime);
}
}
}

Unity 3d - Material Selection for Rendering

I am trying to change the Material of wall at run time. I import the model of house from Google Sketchup, which has different materials all in one object (this is shown in the inspector). Whenever I click the next button (>>), it changes the first material of the object. How do I get the references to the other elements? This is what I have so far:
public class Material_GUI : MonoBehaviour {
public Material[] mats;
public GameObject go;
private int index = 0;
// Use this for initialization
void Start () {
go.renderer.material= mats[index];
}
// Update is called once per frame
void Update () {
}
void OnGUI(){
GUILayout.BeginArea(new Rect(Screen.width/2-100,Screen.height-60,200,50));
GUI.Box (new Rect(10,10,190,40),"");
GUI.Label(new Rect(62,20,100,20),"Wall Testing"+(index +1));
if(GUI.Button (new Rect(15,15,30,30),"<<")){
index--;
if(index<0){
index = mats.Length - 1;
}
go.renderer.material = mats[index];
}
if(GUI.Button (new Rect(165,15,30,30),">>")){
index++;
if(index > mats.Length -1){
index = 0;
}
go.renderer.material = mats[index];
}
GUILayout.EndArea();
}
}
If you want to change the other material of the renderer, you can use
go.renderer.materials
http://docs.unity3d.com/Documentation/ScriptReference/Renderer-materials.html?from=MeshRenderer
For example:
go.renderer.materials[0] = mats[0];
go.renderer.materials[1] = mats[1];