Doom-like face system using unity UI - c#

As you can see in the code below , i have a OnGUI method that "draws" texture depending on the number i give to this method . is there a way to do this by using unity's UI system instead of GUI ? I've tried to do it myself , but was not able to make a method that would change the image on the screen depending on the given number .
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class FaceSystem : MonoBehaviour
{
// HP = HitPoints, SHT = While Shooting, DMG = While taking damage
// FW = Forward, L = Left, R = Right
// Numbers are the HP ranges for the different faces
public Texture2D HP80100FW;
public Texture2D HP80100L;
public Texture2D HP80100R;
public Texture2D HP6079FW;
public Texture2D HP6079L;
public Texture2D HP60790R;
public Texture2D HP4059FW;
public Texture2D HP4059L;
public Texture2D HP4059R;
public Texture2D HP2039FW;
public Texture2D HP2039L;
public Texture2D HP2039R;
public Texture2D HP119FW;
public Texture2D HP119L;
public Texture2D HP119R;
public Texture2D HP0;
public Texture2D SHT80100;
public Texture2D SHT6079;
public Texture2D SHT4059;
public Texture2D SHT2039;
public Texture2D SHT119;
public Texture2D DMG80100;
public Texture2D DMG6079;
public Texture2D DMG4059;
public Texture2D DMG2039;
public Texture2D DMG119;
int pick;
Texture2D[] imgs;
int i;
float timer;
public PlayerHealth PlayerHealth;
public Image healthIndicator;
public Sprite madddead;
void Start()
{
// have every image in an array for easy access
imgs = new Texture2D[26];
imgs[0] = HP80100FW;
imgs[1] = HP80100L;
imgs[2] = HP80100R;
imgs[3] = HP6079FW;
imgs[4] = HP6079L;
imgs[5] = HP60790R;
imgs[6] = HP4059FW;
imgs[7] = HP4059L;
imgs[8] = HP4059R;
imgs[9] = HP2039FW;
imgs[10] = HP2039L;
imgs[11] = HP2039R;
imgs[12] = HP119FW;
imgs[13] = HP119L;
imgs[14] = HP119R;
imgs[15] = HP0;
imgs[16] = SHT80100;
imgs[17] = SHT6079;
imgs[18] = SHT4059;
imgs[19] = SHT2039;
imgs[20] = SHT119;
imgs[21] = DMG80100;
imgs[22] = DMG6079;
imgs[23] = DMG4059;
imgs[24] = DMG2039;
imgs[25] = DMG119;
}
void Update()
{
Faces();
}
public void Faces()
{
timer -= Time.deltaTime;
// modify the timers to your liking
if (PlayerHealth.health >= 80 & PlayerHealth.health <= 100 || PlayerHealth.health >100)
{
if (Input.GetMouseButton(0))
{
timer = 1f;
pick = 16;
}
if (PlayerHealth.isDamaged == true) // add a bool for when damaged in your health script!
{
timer = 0.5f;
pick = 21;
}
if (timer < 0 & !Input.GetMouseButton(0))
{
timer = 1.5f;
// get a random number not equal to current
i = pick;
while (i == pick)
{
pick = Random.Range(0, 3);
}
}
}
if (PlayerHealth.health >= 60 & PlayerHealth.health <= 79)
{
if (Input.GetMouseButton(0))
{
timer = 1f;
pick = 17;
}
if (PlayerHealth.isDamaged == true)
{
timer = 0.5f;
pick = 22;
}
if (timer < 0 & !Input.GetMouseButton(0))
{
timer = 1.5f;
// get a random number not equal to current
i = pick;
while (i == pick)
{
pick = Random.Range(3, 6);
}
}
}
if (PlayerHealth.health >= 40 & PlayerHealth.health <= 59)
{
if (Input.GetMouseButton(0))
{
timer = 1f;
pick = 18;
}
if (PlayerHealth.isDamaged == true)
{
timer = 0.5f;
pick = 23;
}
if (timer < 0 & !Input.GetMouseButton(0))
{
timer = 1.5f;
// get a random number not equal to current
i = pick;
while (i == pick)
{
pick = Random.Range(6, 9);
}
}
}
if (PlayerHealth.health >= 20 & PlayerHealth.health <= 39)
{
if (Input.GetMouseButton(0))
{
timer = 1f;
pick = 19;
}
if (PlayerHealth.isDamaged == true)
{
timer = 0.5f;
pick = 24;
}
if (timer < 0 & !Input.GetMouseButton(0))
{
timer = 1.5f;
// get a random number not equal to current
i = pick;
while (i == pick)
{
pick = Random.Range(9, 12);
}
}
}
if (PlayerHealth.health >= 1 & PlayerHealth.health <= 19)
{
if (Input.GetMouseButton(0))
{
timer = 1f;
pick = 20;
}
if (PlayerHealth.isDamaged == true)
{
timer = 0.5f;
pick = 25;
}
if (timer < 0 & !Input.GetMouseButton(0))
{
timer = 1.5f;
// get a random number not equal to current
i = pick;
while (i == pick)
{
pick = Random.Range(12, 15);
}
}
}
if (PlayerHealth.health <= 0)
{
pick = 15;
}
}
private void OnGUI()
{
if(PlayerHealth.health >0)
{
GUI.DrawTexture(new Rect(695,830, 515, 315), imgs[pick]);
}
else
{
healthIndicator.sprite= madddead;
}
}
}

Pseudo-algorithm:
create your interface with UI, add either Image or RawImage, depending your input
sprite for Image, texture for RawImage
add in your behavior a property, i.e. Image or RawImage and assign it in the inspector
your behavior now knows which UI control to assign an image to
do your logic and set that UI control image accordingly
https://docs.unity3d.com/Packages/com.unity.ugui#1.0/manual/script-Image.html
https://docs.unity3d.com/Packages/com.unity.ugui#1.0/manual/script-RawImage.html

Related

Unity - how do i move the pencil higher then the mouse

The problem is that the pencil it's way too close to the mousePosition. i want to put the pencil higher than the mousePosition.
here is an image as reference : https://ibb.co/s6v25t9
The thing i want to achieve, it's the pencil to be higher than the line drawn
This is taken from a project. it's not my own code but i am trying to figure out how to fix some bugs and this one i cant really figure out how to fix
using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using System.IO;
public class GameManager : MonoBehaviour
{
[Tooltip("The color of the drawn lines")]
public Color lineColor;
public Material lineMaterial;
public Transform Pencil;
public Sprite SurpriseGlass;
public Sprite HappyGlass;
public Sprite SadGlass;
public Slider PenCapacity;
public Text PenPercent;
[HideInInspector]
public GameObject[] Hint;
public Image Star1;
public Image Star2;
public Image Star3;
public GameObject LevComp;
private GameObject[] Obs;
private List<GameObject> listLine = new List<GameObject>();
public List<Vector2> listPoint = new List<Vector2>();
private GameObject currentLine;
public GameObject currentColliderObject;
private GameObject hintTemp;
private GameObject[] waterTap;
private GameObject Glass;
private Vector3 LastMosPos;
private BoxCollider2D currentBoxCollider2D;
private LineRenderer lines;
private LineRenderer currentLineRenderer;
private bool stopHolding;
private bool allowDrawing = true;
[HideInInspector]
public bool completed;
int clickCont;
private List<Rigidbody2D> listObstacleNonKinematic = new List<Rigidbody2D>();
private GameObject[] obstacles;
float mosDis;
bool canCreate;
RaycastHit2D hit_1;
RaycastHit2D hit_2;
RaycastHit2D hit_3;
GameObject TemLine;
void Start()
{
Pencil.gameObject.SetActive(false);
waterTap = GameObject.FindGameObjectsWithTag("Interactive");
Glass = GameObject.FindGameObjectWithTag("GlassParent");
Glass.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Static;
Hint = GameObject.FindGameObjectsWithTag("Hint");
for (int i = 0; i < Hint.Length; i++)
{
Hint[i].SetActive(false);
}
lineMaterial.SetColor("_Color", lineColor);
Obs = GameObject.FindGameObjectsWithTag("Obstacle");
for (int i = 0; i < Obs.Length; i++)
{
Obs[i].GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Static;
}
}
void Update()
{
if (PenCapacity.value <= 0.01f || !Input.GetMouseButton(0))
{
Pencil.gameObject.SetActive(false);
}
if (Input.GetMouseButtonDown(0))
{
GameObject thisButton = UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject; //Get the button on click
if (thisButton != null) //Is click on button
{
allowDrawing = false;
print("cant drwa");
}
else //Not click on button
{
allowDrawing = true;
stopHolding = false;
listPoint.Clear();
CreateLine(Input.mousePosition);
print("draw");
}
}
else if (Input.GetMouseButton(0) && !stopHolding && allowDrawing && PenCapacity.value > 0)
{
RaycastHit2D rayHit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if (LastMosPos != Camera.main.ScreenToWorldPoint(Input.mousePosition))
{
if (rayHit.collider == null)
{
Pencil.gameObject.SetActive(true);
Pencil.position = new Vector3(LastMosPos.x, LastMosPos.y, 0);
if (canCreate == false)
{
float dist = Vector3.Distance(LastMosPos, Camera.main.ScreenToWorldPoint(Input.mousePosition));
Pencil.GetComponent<TrignometricRotation>().enabled = true;
PenCapacity.value = PenCapacity.value - dist / 25;
PenPercent.text = Mathf.FloorToInt(PenCapacity.value * 100).ToString() + " %";
if (Mathf.FloorToInt(PenCapacity.value * 100) < 75)
{
Star3.gameObject.SetActive(false);
}
if (Mathf.FloorToInt(PenCapacity.value * 100) < 50)
{
Star2.gameObject.SetActive(false);
}
if (Mathf.FloorToInt(PenCapacity.value * 100) < 25)
{
Star1.gameObject.SetActive(false);
}
}
}
}
else
{
Pencil.GetComponent<TrignometricRotation>().enabled = false;
}
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
float ab = Vector2.Distance(LastMosPos, mousePos);
mosDis = mosDis + ab;
if (!listPoint.Contains(mousePos) && mosDis > .02f)
{
mosDis = 0;
//Add mouse pos, set vertex and position for line renderer
if (canCreate == false)
{
if (rayHit.collider == null)
{
listPoint.Add(mousePos);
}
In the code you posted the value of LastMosPos is never changed so I can't say where you get it from.
However instead of the line
Pencil.position = new Vector3(LastMosPos.x, LastMosPos.y, 0);
you probably could simply add a certain offset like e.g.
Pencil.position = new Vector3(LastMosPos.x, LastMosPos.y + 20f, 0);
to make the pencil appear 20 Unity units (in a Screenspace Overlay canvas this euqals 20 Pixels) above the LastMosPos.

Array inaccessible only at certain times

I am currently building a parallax background effect in Unity and starting with some starter code that I'm trying to work though. The code works for the most part, with some small issues I'm slowly getting through.
I have been testing out various stats of public vs. private, etc. but can't seem to work out exactly why and where the issue I'm facing is occurring.
When I run the same script and it calls Update() every frame, I would expect to have the same size "poolObjects" length. However, when I call it with a starting pool size of 10, I get 10, then 2, then 0, then 10, 2, 0, etc.
I am truncating it but posting what I think to be relevant here. Hope you can help me see what is likely obvious!
I do see "In GetPool Object" but because the length is never > 0, I never see within the For Loop, which is essential. I can't figure out why the poolObjects length would be showing up as 0.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Parallaxer : MonoBehaviour {
class PoolObject {
public Transform transform;
public bool inUse;
public PoolObject(Transform t) { transform = t; }
public void Use() { inUse = true; }
public void Dispose() { inUse = false; }
}
...
public int poolSize;
public float shiftSpeed;
public float spawnRate;
...
float spawnTimer;
PoolObject[] poolObjects;
float targetAspect;
GameManager game;
void Awake() {
Configure();
}
void Start() {
game = GameManager.Instance;
}
...
void Update() {
Debug.Log(poolObjects.Length + "Len here of pool objects");
if (game.GameOver) return;
Shift();
spawnTimer += Time.deltaTime;
if (spawnTimer > spawnRate) {
Spawn();
spawnTimer = 0;
}
}
void Configure() {
//spawning pool objects
targetAspect = targetAspectRatio.x / targetAspectRatio.y;
// targetAspect = Camera.main.aspect;
// Debug.Log(targetAspectRatio.x +" " + targetAspectRatio.y);
poolObjects = new PoolObject[poolSize];
for (int i = 0; i < poolObjects.Length; i++) {
GameObject go = Instantiate(Prefab) as GameObject;
Transform t = go.transform;
t.SetParent(transform);
t.position = Vector3.one * 1000;
poolObjects[i] = new PoolObject(t);
}
if (spawnImmediate) {
SpawnImmediate();
}
}
void Spawn() {
//moving pool objects into place
Transform t = GetPoolObject();
Debug.Log("In to Spawn" + t);
if (t == null) return;
Vector3 pos = Vector3.zero;
pos.y = Random.Range(ySpawnRange.minY, ySpawnRange.maxY);
pos.x = (defaultSpawnPos.x * Camera.main.aspect) / targetAspect;
// Debug.Log("Spwaning");
// Debug.Log(Camera.main.aspect);
// Debug.Log(immediateSpawnPos.x + " " + immediateSpawnPos.y + " " + targetAspect);
t.position = pos;
// Debug.Log(pos);
}
void SpawnImmediate() {
Transform t = GetPoolObject();
if (t==null) return;
Vector3 pos = Vector3.zero;
pos.y = Random.Range(ySpawnRange.minY, ySpawnRange.maxY);
pos.x = (immediateSpawnPos.x * Camera.main.aspect) / targetAspect;
t.position = pos;
Spawn();
}
void Shift() {
//loop through pool objects
//moving them
//discarding them as they go off screen
Debug.Log(poolObjects.Length + "Finding Length");
for (int i = 0; i < poolObjects.Length; i++) {
poolObjects[i].transform.position += -Vector3.right * shiftSpeed * Time.deltaTime;
Debug.Log(poolObjects[i].transform.position);
CheckDisposeObject(poolObjects[i]);
}
}
void CheckDisposeObject(PoolObject poolObject) {
//place objects off screen
if (poolObject.transform.position.x < (-defaultSpawnPos.x * Camera.main.aspect) / targetAspect) {
poolObject.Dispose();
poolObject.transform.position = Vector3.one * 1000;
}
}
Transform GetPoolObject() {
//retrieving first available pool object
Debug.Log("In GetPool Object" + poolObjects.Length);
for (int i = 0; i < poolObjects.Length; i++) {
Debug.Log("This is not showing up "+ poolObjects[i].inUse);
if (!poolObjects[i].inUse) {
poolObjects[i].Use();
return poolObjects[i].transform;
}
}
return null;
}
}

Unity what's wrong with my instantiating algorithm?

I dont know if I can call this algorithm. But I am working on a game in which player will move in a circular path.
As you can see in the picture player is suppose to orbit the circle. And obstacle shall be instantiated in the circle.I am trying to first create the obstacle in first half(left to the long cube) and then in the second half. But things are getting created in the next half too when code is not supposed to do that. Also, it is showing argument exception error. Please have a look at my code and tell me whether my method is wrong or my formulas are wrong or anything else.
public class ObjectInstantiater : MonoBehaviour {
DataHolder dataholder;
GameObject Obstacle;
LevelData leveldata;
private int currentlevel=0; // default level starts from 0
private List<GameObject> Inactivegameobject = new List<GameObject>(); // this object can be used
private List<GameObject> Activegameobject = new List<GameObject>();
private int totalgameobjects;
private int firsthalfgameobjects, secondhalfgameobjects;
public float outerradius;
public float innerradius;
private bool shallspawnouterradiues = true;
// Use this for initialization
void Awake () {
dataholder = (Object)GameObject.FindObjectOfType<DataHolder>() as DataHolder;
Obstacle = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
leveldata = dataholder.Leveldata[0];
}
void Start()
{
Updateleveldata();
FirstHalf();
}
public int Currentlevel
{
get { return currentlevel; }
set { currentlevel = value;
leveldata = dataholder.Leveldata[currentlevel];//sets the level data
}
}
private void Updateleveldata() // this function gets called after a round
{
totalgameobjects = Random.Range(leveldata.MinimumObstacle, leveldata.MaximumObstacle);
firsthalfgameobjects = Mathf.RoundToInt(totalgameobjects / 2);
secondhalfgameobjects = totalgameobjects - firsthalfgameobjects;
}
private void FirstHalf()
{
Debug.Log(firsthalfgameobjects);
Vector3 pos;
if (Inactivegameobject.Count < firsthalfgameobjects)
{
for (int x = 0; x <= (firsthalfgameobjects - Inactivegameobject.Count); x++)
{
GameObject obs = Instantiate(Obstacle) as GameObject;
obs.SetActive(false);
Inactivegameobject.Add(obs);
}
}
float spawnangledivision = 180 / firsthalfgameobjects;
float spawnangle = 180f;
for(int x = 0; x < firsthalfgameobjects; x++)
{
float proceduralRandomangle = spawnangle;
proceduralRandomangle = Random.Range(proceduralRandomangle , proceduralRandomangle + 2f);
if (shallspawnouterradiues)
{
pos = new Vector3(outerradius * Mathf.Cos(spawnangle), outerradius * Mathf.Sin(spawnangle), 0f);
shallspawnouterradiues = false;
}else
{
pos = new Vector3(innerradius * Mathf.Cos(spawnangle), innerradius * Mathf.Sin(spawnangle), 0f);
shallspawnouterradiues = true;
}
spawnangle += spawnangledivision;
Inactivegameobject[0].SetActive(true); // set it to 0
Inactivegameobject[0].transform.position = pos;
Activegameobject.Add(Inactivegameobject[0]);
Inactivegameobject.RemoveAt(0);
}
}
private void SecondHalf()// No need to check this
{
if (Inactivegameobject.Count < firsthalfgameobjects)
{
GameObject obs = Instantiate(Obstacle) as GameObject;
obs.SetActive(false);
Inactivegameobject.Add(obs);
}
}
}

can't change sprite on an object of dictionary

I am trying to change sprite of an object of dictionary when i click a key on keyboard. But i can't do that. this my code
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
public class plantingScript : MonoBehaviour {
public float plantV = 0f;
public float coordX = 0f;
public float coordY = 0f;
public float koordX = 0f;
public float koordY = 0f;
public walkingScript ws = new walkingScript();
public loadGame loadLand ;
public GameObject gameObj;
//public SpriteRenderer spriteObj;
public Dictionary<string,Tanah> tempTanah = new Dictionary<string, Tanah>();
public Dictionary<string,GameObject> tempObjTanah = new Dictionary<string, GameObject>();
void Awake(){
//spriteObj = gameObj.AddComponent<SpriteRenderer>();
loadLand = GameObject.Find ("loadGameObject").GetComponent<loadGame>();
tempTanah = loadLand.myTanah;
tempObjTanah = loadLand.objTanah;
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(Input.GetKeyDown(KeyCode.V))
cekLokasi();
}
void cekLokasi(){
Debug.Log ("V pressed!");
GameObject temp = null;
coordX = (int)(gameObject.transform.localPosition.x / 0.8f + gameObject.transform.localPosition.y / 0.4f) / 2;
coordY = (int)(gameObject.transform.localPosition.y / 0.4f - (gameObject.transform.localPosition.x / 0.8f)) / 2;
if(ws.hadapAtas == true && ws.hadapKanan == true)
{
koordY = (int) coordY;
koordX = (int) coordX + 1;
}
else if(ws.hadapAtas == false && ws.hadapKanan == true)
{
koordY = (int) coordY;
koordX = (int) coordX - 1;
}
else if(ws.hadapAtas == false && ws.hadapKanan == false)
{
koordY = (int) coordY + 1;
koordX = (int) coordX;
}
else if(ws.hadapAtas == true && ws.hadapKanan == false)
{
koordY = (int) coordY + 1;
koordX = (int) coordX;
}
if(tempObjTanah.TryGetValue("land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#"),out temp))
{
Sprite mySprite = null;
Debug.Log ("Land found!");
mySprite = loadLand.myTanah["land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#")].spriteTanah["Garap"];
Debug.Log ("Sprite found!");
gameObj = tempObjTanah["land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#")];
gameObj.AddComponent<SpriteRenderer>();
gameObj.GetComponent<SpriteRenderer>().sprite = mySprite;
/*
Sprite mySprite = null;
Debug.Log ("Land found!");
mySprite = loadLand.myTanah["land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#")].spriteTanah["Garap"];
Debug.Log ("Sprite found!");
tempObjTanah["land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#")].AddComponent<SpriteRenderer>();
SpriteRenderer mySpriteRend = tempObjTanah["land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#")].GetComponent<SpriteRenderer>();
mySpriteRend.sprite = mySprite;
}
*/
}
}
}
this is how that dictionary of gameObject was made
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
public class loadGame : MonoBehaviour {
public static loadGame loadSave;
public GameObject objPrince;
public Pangeran charPrince;
public Transform prefPrince;
public Sprite[] spriteTanah;
public Dictionary<string, Tanah> myTanah = new Dictionary<string, Tanah>();
public Dictionary<string, GameObject>objTanah = new Dictionary<string, GameObject>();
public Tanah tempTanah;
public GameObject tempObjTanah;
public Transform prefTanah;
public float mapX;
public float mapY;
public int i = 0;
public int j = 0;
public int rows = 9;
public int column = 9;
void Awake(){
if(loadSave == null)
{
DontDestroyOnLoad(gameObject);
loadSave = this;
}
else if(loadSave != this)
Destroy(gameObject);
}
// Use this for initialization
void Start () {
Load ();
}
// Update is called once per frame
void Update () {
}
public void Load(){
if(File.Exists(Application.persistentDataPath + "/playerInfo.dat"))
{
}
else
{
charPrince = new Pangeran ("Prince", "04Okt1993", 0, 0, 0, 0, 0, false, false);
objPrince = GameObject.Instantiate (prefPrince, new Vector3 (0, 0, 0), Quaternion.identity) as GameObject;
//objPrince.name = "Prince";
charPrince.locationY = 0f;
charPrince.locationX = 0f;
charPrince.hadapAtas = false;
charPrince.hadapKanan = true;
charPrince.stamina = 100f;
charPrince.exp = 0f;
charPrince.speed = 0f;
for(i = 0 ; i < rows ; i ++)
{
for(j = 0; j<column ; j++)
{
mapX = (i-j) * 0.8f;
mapY = (i+j) * 0.4f;
if(i>=1 && j>=1 && i<=5 && j<=5)
{
prefTanah.name = "land-"+j.ToString("0#")+"-"+i.ToString("0#");
tempTanah = new Tanah("land-"+j.ToString("0#")+"-"+i.ToString("0#"),mapX,mapY,"land",spriteTanah[0],spriteTanah[1],spriteTanah[2]);
myTanah.Add("land-"+j.ToString("0#")+"-"+i.ToString("0#"),tempTanah);
tempObjTanah = GameObject.Instantiate(prefTanah, new Vector3(mapX,mapY,0),Quaternion.identity)as GameObject;
objTanah.Add("land-"+j.ToString("0#")+"-"+i.ToString("0#"),tempObjTanah);
}
else
{
prefTanah.name = "snow-"+j.ToString("0#")+"-"+i.ToString("0#");
tempTanah = new Tanah("snow-"+j.ToString("0#")+"-"+i.ToString("0#"),mapX,mapY,"snow");
myTanah.Add("snow-"+j.ToString("0#")+"-"+i.ToString("0#"),tempTanah);
tempObjTanah = GameObject.Instantiate(prefTanah, new Vector3(mapX,mapY,0),Quaternion.identity)as GameObject;
objTanah.Add("snow-"+j.ToString("0#")+"-"+i.ToString("0#"),tempObjTanah);
}
}
}
}
}
}
and it made an error that said
NullReferenceException: Object reference not set to an instance of an
object plantingScript.cekLokasi () (at
Assets/Scripts/plantingScript.cs:78)
line 78 is
tempObjTanah["land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#")].GetComponent<SpriteRenderer>().sprite = mySprite;
I am trying to change the sprite with other ways, but i didn't work.
please Help me. Thank you.
If Unity says it doesn't have a SpriteRenderer, then it doesn't have a SpriteRenderer.
gameObj.GetComponent<SpriteRenderer>() is what's null, and when you try to access the sprite property from it, you get the NullReferenceException.
Check how you've created your objects and make sure they have the right components attached. SpriteRenderer is not a default component.
EDIT: After reading your new code sample, I have a few more comments but unfortunately not a definite solution to your problem.
Your code is extremely difficult to read and understand, mostly due to the use of common variable names describing different things.
prefTanah.name = ...
tempTanah = ...
myTanah.Add(...);
tempObjTanah = ...
objTanah.Add(
prefTanah is a prefab, but you're changing its name to something that is dynamically generated. This name makes sense, but changing the name like this does not.
Then you create a Tanah object which I assume is some kind of data model. Then you add this to a dictionary of Tanah objects called myTanah.
But you're also maintaining a separate dictionary of GameObjects which appear to be related to the Tanah objects.
Also, tempObjTanah is assigned a GameObject in the second code sample, but it is referred to as a dictionary in the first one. Even if these are in different scopes, it's hard to understand for an outside observer.
Unfortunately, I don't see a direct solution to your original problem, but I'm certain that it is a result of your script being very messy and hard to understand. If the prefab referred to by prefTanah does indeed have a SpriteRenderer, my only guess is that your dictionary does not contain what you think it contains. My advice is to go over your script and make sure it's doing what you think it's doing. You can also try posting the entire script to pastebin or something so we can have more context about what's going on.

Only one gameobject being affected by script

Making a state machine AI "game" I have 3 states Movement, Combat, and View. They all work very well, now I'm making a flee (by the way if anyone has any good links to tutorials or info that they have off hand I would love that) state so I want to make all three previous state in their Idle mode. Which works perfectly when I have 1 AI. As soon as I put the rest (there is 6 total now) it will still only affect 1, but then after some time it will "release" I guess it the best term the script and just goes back to the three states that are supposed to be idle. I think that in my Coin script I am saying find and I think it needs to be something else, I'm just not sure if that's even right but based off of my previous experiences that's usually the case with Unity. I'll post some code, but here's some info that may help your eyes by not having to read through everything:
-I have a bool set up in my AIClass that is false until one of my gameobjects collides with a 'coin', and coin is jsut a gameobject i put in my game to test out my AI behaviors. When that bool is true, in my update in my AIClass(sorry it's at the very bottom of the script you can scroll down, but I had to put other code just in case I was doing something in that to cause my problem.) It sets the state of MovementState to Idle, CombatState to Idle and ViewState to Idle.
-Also, when that bool is false is the only time that the call for the transition of states occur. For example, normally the AI will search around trying to find player, if they find him they go near him, and if they are in a certain distance they fire. Pretty simple. The movement between those states happens at the end of each IENumerator when the 'NextMovementState()' or 'NextCombatState()' or 'NextViewState()' are called. So when the bool is true those should never be called, halting the AI from moving to another state other than Idle (to what it's set at when the bool is true in the update).
And this works fine when I have only 1 AI in the game.
CoinScript.cs
using UnityEngine;
using System.Collections;
public class CoinScript : MonoBehaviour {
private AIClass a;
// Use this for initialization
void Start () {
a = GameObject.Find ("Enemy").GetComponent<AIClass>();
}
// Update is called once per frame
void Update () {
}
void OnCollisionEnter(Collision collision)
{
if (collision.collider)
{
if(collision.gameObject.tag == "Enemy" || collision.gameObject.tag == "EnemyProjectile")
{
Physics.IgnoreCollision(rigidbody.collider,collision.collider);
//Debug.Log ("Enemy");
}
if(collision.gameObject.tag == "Player")
{
Debug.Log ("triggered!");
a.fleeBool = true;
Destroy(gameObject);
}
}
}
}
AIClass.cs
using UnityEngine;
using System.Collections;
public class AIClass : MonoBehaviour
{
public NavMeshAgent agent;
//Ammo in gun before reloading is required
public int ammo = 30;
public int maxAmmo = 30;
//Number of bullets a gun fires in sequence on 1 trigger pull
public int chamber = 3;
public int maxChamber = 3;
//Pause between bursts or mouse presses, set to 0 for fully automatic
public double chamberTime = 120;
//How fast a gun fires in RPS
public int fireRate = 7;
public int fireTimer = 0;
//How fast a gun can reload
public int reloadTime = 3;
public int reloadTimer = 0;
//Number of bullets fired per shot
public int bulletsFired = 1;
public GameObject bulletClone;
//Acceptable degrees as to which the AI will begin firing at its target
public int firingAngle = 5;
//Vision cone of degrees to left and right
public int visionAngle = 35;
public int visionDistance = 100;
public int vRotationSpeed = 3;
public int vIdleTimer = 0;
public int vIdleTime = 300;
public int searchTimer = 0;
public int searchTime = 300;
public int mIdleTimer = 0;
public int mIdleTime = 300;
public bool isFocusedOnPlayer = false;
public bool seesPlayer = false;
//
public bool fleeBool;
public bool flee;
public enum MovementState
{
MSearch,
MMoving,
MIdle,
}
public enum CombatState
{
CFiring,
CReloading,
CIdle,
}
public enum ViewState
{
VSearch,
VFocus,
VIdle,
}
public enum FleeState
{
FSearch,
FMoving,
FIdle
}
public CombatState combatState;
public ViewState viewState;
public MovementState movementState;
public FleeState fleeState;
//Search state (knows where player is and will head to the player's location)
IEnumerator MSearchState ()
{
mIdleTimer = 0;
int stuckTimer = 0;
while (movementState == MovementState.MSearch)
{
//I've arrived at my location, if idle too long, then go back to idle state
if(Vector3.Distance(transform.position,agent.destination) < 3)
mIdleTimer++;
//I'm stuck and haven't moved in a while, go back to idle state
if(agent.velocity.magnitude < 1)
stuckTimer++;
if(seesPlayer || mIdleTimer > mIdleTime + 200 || stuckTimer > 300)
{
agent.destination = transform.position;
movementState = MovementState.MIdle;
}
yield return 0;
}
if (!flee) {
NextMovementState();
}
}
//Wander state
IEnumerator MMovingState ()
{
while (movementState == MovementState.MMoving)
{
//Wander code... Create a random angle and convert it to radians
float randomAngle = (float)(3.14/180)*Random.Range(0,360);
//Normalize direction vector, as we will be using it to calculate where we place the circle
Vector3 tempV = agent.velocity;
Vector3.Normalize (tempV);
//Using our relative position, 5 units in front of us. Use the generated angle to find the point on the circle that we want to go to
agent.destination = transform.position + tempV * 3 + new Vector3(Mathf.Cos (randomAngle)*3,0,Mathf.Sin (randomAngle)*3);
//Check to see if we are within the arena bounds, if not, push our projected vector back inside
if(agent.destination.x > 24)
agent.destination = agent.destination + new Vector3(-7,0,0);
if(agent.destination.x < -24)
agent.destination = agent.destination + new Vector3(7,0,0);
if(agent.destination.z > 24)
agent.destination = agent.destination + new Vector3(0,0,-7);
if(agent.destination.z < -24)
agent.destination = agent.destination + new Vector3(0,0,7);
if(seesPlayer)
{
agent.destination = transform.position;
movementState = MovementState.MIdle;
}
yield return 0;
}
if (!flee) {
NextMovementState ();
}
}
//Not moving, if I don't see the player for awhile, then go wander
IEnumerator MIdleState ()
{
mIdleTimer = 0;
while (movementState == MovementState.MIdle)
{
if(seesPlayer)
mIdleTimer = 0;
else
mIdleTimer++;
if(mIdleTimer > mIdleTime + Random.Range (-100,100))
movementState = MovementState.MMoving;
yield return 0;
}
if (!flee) {
NextMovementState ();
}
}
//Visual search state, randomly look around and check to see if we see the player
IEnumerator VSearchState ()
{
Transform target = GameObject.FindWithTag ("Player").transform;
Vector3 targetPosition = target.position;
while (viewState == ViewState.VSearch)
{
searchTimer--;
//Vision Cone calculation
Vector3 targetDir = target.position - transform.position;
Vector3 forward = transform.forward;
float angle = Vector3.Angle(targetDir, forward);
//If player is within vision cone then proceed
if (angle < visionAngle)
{
//Check to see if there are any object between player and myself
RaycastHit hit;
if (Physics.Raycast(transform.position, targetDir, out hit))
{
if(hit.transform == target)
{
seesPlayer = true;
viewState = ViewState.VFocus;
}
}
}
//Look in another direction
if(searchTimer < 0)
{
searchTimer = searchTime + Random.Range (-100,100);
targetPosition = new Vector3(Random.Range (-100,100),transform.position.y,Random.Range (-100,100));
}
transform.rotation = Quaternion.Slerp(transform.rotation,Quaternion.LookRotation(targetPosition - transform.position), vRotationSpeed*Time.deltaTime);
yield return 0;
}
if (!flee) {
NextViewState ();
}
}
//Focus on player
IEnumerator VFocusState ()
{
Transform target = GameObject.FindWithTag ("Player").transform;
while (viewState == ViewState.VFocus)
{
//Vision Cone calculation
Vector3 targetDir = target.position - transform.position;
Vector3 forward = transform.forward;
float angle = Vector3.Angle(targetDir, forward);
if (angle > visionAngle)
viewState = ViewState.VIdle;
else
{
RaycastHit hit;
//Check if there are any objects in the way
if (Physics.Raycast(transform.position, targetDir, out hit))
{
if(hit.transform == target)
{
//Tell other AI where player is
GameObject[] objArray = GameObject.FindGameObjectsWithTag ("Enemy");
AIClass[] enemyArray = new AIClass[objArray.Length];
for(int i = 0; i < enemyArray.Length; i++)
{
enemyArray[i] = (AIClass)objArray[i].GetComponent(typeof(AIClass));
if(i >= enemyArray.Length/2)
enemyArray[i].agent.destination = target.position;
else
enemyArray[i].agent.destination = target.position + target.forward*5;
enemyArray[i].movementState = MovementState.MSearch;
}
seesPlayer = true;
transform.rotation = Quaternion.Slerp(transform.rotation,Quaternion.LookRotation(target.position - transform.position), vRotationSpeed*Time.deltaTime);
//Check to see player is within sights of the gun
if (angle < firingAngle)
isFocusedOnPlayer = true;
else
isFocusedOnPlayer = false;
}
else
{
//I no longer see the player
seesPlayer = false;
viewState = ViewState.VIdle;
isFocusedOnPlayer = false;
}
}
}
yield return 0;
}
if (!flee) {
NextViewState ();
}
}
//Visual idle state, basically the ai is just looking forward
IEnumerator VIdleState ()
{
vIdleTimer = 0;
Transform target = GameObject.FindWithTag ("Player").transform;
while (viewState == ViewState.VIdle)
{
//Vision cone calculation
vIdleTimer++;
Vector3 targetDir = target.position - transform.position;
Vector3 forward = transform.forward;
float angle = Vector3.Angle(targetDir, forward);
//Check to see if there is an object is between the ai and the player
if (angle < visionAngle)
{
RaycastHit hit;
if (Physics.Raycast(transform.position, targetDir, out hit))
{
if(hit.transform == target)
{
seesPlayer = true;
viewState = ViewState.VFocus;
}
}
}
if(vIdleTimer > vIdleTime)
viewState = ViewState.VSearch;
yield return 0;
}
if (!flee) {
NextViewState ();
}
}
//Firing gun state
IEnumerator CFiringState ()
{
while (combatState == CombatState.CFiring)
{
if(!isFocusedOnPlayer)
combatState = CombatState.CIdle;
fireTimer--;
if(ammo > 0)
{
if(chamber > 0)
{
if(fireTimer <= 0)
{
for(int i = 0; i < bulletsFired;i++)
{
GameObject temp = (GameObject) Instantiate (bulletClone,transform.position + transform.forward,transform.rotation);
temp.rigidbody.AddForce(transform.forward*500);
}
fireTimer = 60 / fireRate;
ammo--;
chamber--;
}
}
else
{
chamber = maxChamber;
fireTimer = (int)(60/chamberTime);
}
}
else
{
combatState = CombatState.CReloading;
}
yield return 0;
}
if (!flee) {
NextCombatState ();
}
}
IEnumerator CReloadingState ()
{
reloadTimer = reloadTime * 60;
while (combatState == CombatState.CReloading)
{
reloadTimer--;
if(reloadTimer <= 0)
{
ammo = maxAmmo;
combatState = CombatState.CIdle;
}
yield return 0;
}
if (!flee) {
NextCombatState ();
}
}
IEnumerator CIdleState ()
{
while (combatState == CombatState.CIdle)
{
if(isFocusedOnPlayer)
combatState = CombatState.CFiring;
yield return 0;
}
if (!flee) {
NextCombatState ();
}
}
void Start ()
{
fleeBool = false;
flee = false;
NextCombatState();
NextViewState();
NextMovementState();
}
void NextMovementState()
{
string methodName = movementState.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
void NextCombatState ()
{
string methodName = combatState.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
void NextViewState ()
{
string methodName = viewState.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
void NextFleeState()
{
string methodName = viewState.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
void Update()
{
Debug.DrawLine(transform.position, transform.position+transform.forward*5, Color.red);
if (fleeBool == true)
{
flee = true;
}
if (flee == true)
{
Debug.Log ("flee is true");
combatState = CombatState.CIdle;
movementState = MovementState.MIdle;
viewState = ViewState.VIdle;
Debug.Log ("End of idles");
}
}
}
You can use GameObject.FindObjectsOfType() or GameObject.FindGameObjectsWithTag
you can do that with store all the AIClass into array and then loop it become specific, so every enemy can affected
AIClass[] AIObject = GameObject.Find("Enemy").GetComponents<AIClass>();
foreach(AIClass a in AIObject ){
//do something with a
}
it should work.

Categories