I am trying to see what gun we currently have equipped and play that specific gun sound, which I am doing by searching for the weapon's tag. However, I am getting the error 'Type PlayerWeapon does not contain a definition for tag and no extension method tag of type PlayerWeapon could be found'.
This is the section of playershoot script attached to the player prefab that handles the tags:
weaponManager = GetComponent<WeaponManager>();
}
void Update ()
{
currentWeapon = weaponManager.GetCurrentWeapon();
if (PauseMenu.IsOn)
return;
if (currentWeapon.fireRate <= 0f)
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
if(currentWeapon.tag = "Tec")
{
CmdPlayTecShootSound();
}
}
And this is the relevant section from the weaponmanager script:
private PlayerWeapon currentWeapon;
private WeaponGraphics currentGraphics;
private Transform currentHolder;
void Start ()
{
currentHolder = awpweaponHolder;
EquipWeapon(primaryWeapon);
}
void Update()
{
if(Input.GetAxis("WeaponSwitch") >0f)
{
currentHolder = tecweaponHolder;
EquipWeapon(secondaryWeapon);
Debug.Log("switched weapon");
}
else if (Input.GetAxis("WeaponSwitch")<0f)
{
currentHolder = awpweaponHolder;
EquipWeapon(primaryWeapon);
Debug.Log("switched weapon back");
}
}
public PlayerWeapon GetCurrentWeapon ()
{
return currentWeapon;
}
public WeaponGraphics GetCurrentGraphics()
{
return currentGraphics;
}
void EquipWeapon (PlayerWeapon _weapon)
{
foreach (Transform child in tecweaponHolder)
{
Destroy(child.gameObject);
}
currentWeapon = _weapon;
UPDATE:
void Update ()
{
currentWeapon = weaponManager.GetCurrentWeapon();
if (PauseMenu.IsOn)
return;
if (currentWeapon.fireRate <= 0f)
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
foreach (Transform child in tecweaponHolder)
{
if(gameObject.tag == "Tec")
{
CmdPlayTecShootSound();
Debug.Log("tec sound played");
}
}
foreach (Transform child in awpweaponHolder)
{
if(gameObject.tag == "Awp")
{
CmdPlayAwpShootSound();
Debug.Log("awp sound played");
}
}
}
currentWeapon is a script instance that is attached to a GameObject. To get the tag, you must first covert it to a GameObject or Transform then you get the tag name.
Also, you compare with multiple = sign not just one. You assign with one = sign.
if(currentWeapon.tag = "Tec") should be if (currentWeapon.gameObject.tag == "Tec")
Finally, for performance reason, you should compare tags with the CompareTag function.
Use currentWeapon.gameObject.tag to get the name of the tag. For example, Debug.Log("Tag: " + currentWeapon.gameObject.tag);
Then use if (currentWeapon.gameObject.CompareTag("Tec")){} to compare tags.
Related
Hello everyone I am trying to make a simple Emote functionality. I have a bubble(like a chat bubble) and inside of that there is an animation. Like in Legends of Runeterra and Clash Royale type games.
public class EmoteBubble : MonoBehaviour
{
private Animator animator;
private Animator childAnimator;
public List<GameObject> objectList;
// Start is called before the first frame update
void Start()
{
animator = gameObject.GetComponent<Animator>();
foreach (GameObject obj in objectList)
{
obj.SetActive(false);
}
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)){
childAnimator = transform.Find(objectList[0].name).GetComponent<Animator>();
objectList[0].SetActive(true);
StartCoroutine(HeroAnimator(2f, objectList[0].name + "Bool"));
}
IEnumerator HeroAnimator(float animationLength, string parameter)
{
animator.SetBool("EmoteBool", true);
childAnimator.SetBool(parameter, true);
yield return new WaitForSeconds(animationLength);
animator.SetBool("EmoteBool", false);
childAnimator.SetBool(parameter, false);
yield return new WaitForSeconds(0.2f);
foreach (GameObject obj in objectList)
{
obj.SetActive(false);
}
}
}
This is the script of the bubble and it has childs in objectList. If I hit space I want a specific animation to kick in like the first one or the second one. I am trying to disable every object in Start function and enable the one that i choose. But when I use prefabs only the real one gets disabled. Should I use prefabs in this emote concept or should I make every object different ?
public class EmoteBubble : MonoBehaviour
{
private Animator animator;
private Animator childAnimator;
public List<GameObject> objectList;
// Start is called before the first frame update
void Start()
{
Debug.Log(objectList[2]);
animator = gameObject.GetComponent<Animator>();
foreach (GameObject obj in objectList)
{
obj.SetActive(false);
}
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)){
objectList[0].SetActive(true);
childAnimator = transform.Find(objectList[0].name).GetComponent<Animator>();
StartCoroutine(HeroAnimator(2f, objectList[0].name + "Bool"));
}
if (Input.GetKeyDown(KeyCode.A)) {
objectList[1].SetActive(true);
childAnimator = transform.Find(objectList[1].name).GetComponent<Animator>();
StartCoroutine(HeroAnimator(2f, objectList[1].name + "Bool"));
}
if (Input.GetKeyDown(KeyCode.S)){
objectList[2].SetActive(true);
childAnimator = transform.Find(objectList[2].name).GetComponent<Animator>();
StartCoroutine(HeroAnimator(2f, objectList[2].name + "Bool"));
}
IEnumerator HeroAnimator(float animationLength, string parameter)
{
animator.SetBool("EmoteBool", true);
childAnimator.SetBool(parameter, true);
yield return new WaitForSeconds(animationLength);
animator.SetBool("EmoteBool", false);
childAnimator.SetBool(parameter, false);
yield return new WaitForSeconds(0.2f);
foreach (GameObject obj in objectList)
{
obj.SetActive(false);
}
}
}
}
I think this works, It looks simple and it works but I don't know if it's the best way.
I want to find the GameObject that is in the hierarchy correctly in the hierarchy. But this does not happen correctly, so I want 'if' to work when the gameobject I have tagged is active, but 'if' works even though there is no other gameobject tag, which is why this problem is caused.
Note: My level of English is not good, I try to explain the problem to you as much as I can, please tell me if there is anything you do not understand, I will try to explain it in detail as much as I can. Thank you for your understanding.
Image tagged gameobject: enter image description here
The point where the problem occurred: enter image description here
Gameobject tag name: enter image description here
Cubes Gameobject: enter image description here
void Update()
{
if (cubes.instance.objPool.Count == 1) //It works when the number of gameobject in the list is 1 when I do a random deletion.
{
RewardSystem();
}
}
public void RewardSystem()
{
GameObject FoundCube = GameObject.FindGameObjectWithTag(cube_Tag_Number);
if (FoundCube == null)
{
SoundManager.instance.GameOverMenuSound();
game_Over_Menu.SetActive(true);
next_Level_Menu.SetActive(false);
confetti.Stop();
clickButton.gameObject.SetActive(false);
missionButton.gameObject.SetActive(false);
enabled = false;
}
if (FoundCube != null)// problematic if
{
if (FoundCube.activeInHierarchy == true) // problematic if
{
SoundManager.instance.NextLevelMenuSound();
next_Level_Menu.SetActive(true);
confetti.Play();
game_Over_Menu.SetActive(false);
clickButton.gameObject.SetActive(false);
missionButton.gameObject.SetActive(false);
enabled = false;
}
}
}
public class cubes : MonoBehaviour
{
public static cubes instance;
public int randomRangeNumber1, randomRangeNumber2;
public List<GameObject> objPool = new List<GameObject>();
private void Awake()
{
if (instance == null)
{
instance = this;
}
else if (instance != null)
{
Destroy(gameObject);
}
}
public void ButtonOnDown()
{
SoundManager.instance.LuckButtonSound();
for (int i = 0; i < 1; i++)
{
int index = Random.Range(randomRangeNumber1, randomRangeNumber2);
GameObject.Destroy(objPool[index]);
objPool.RemoveAt(index);
randomRangeNumber2 = objPool.Count;
}
}
}
I currently have a script that instantiates 2 prefabs as GameObjects. Which have attached to them a script that the game-object is set active to false, then is added to my inventory array. Which is another script, but my issue is the other game object that wasn't selected is still there. It is supposed to be you have a choice of 2. Once you take one the other disappears. I have no idea how to do this, could anyone please help.
public int moralityCounter=0;
public bool Inventory;
public void Store()
{
if (gameObject.CompareTag("Good"))
{
moralityCounter++;
Debug.Log(moralityCounter);
gameObject.SetActive(false);
}
if (gameObject.CompareTag("Bad"))
{
moralityCounter--;
Debug.Log(moralityCounter);
gameObject.SetActive(false);
}
}
If there's only the single good and single bad tagged objects, you can just set everything tagged good and bad to be inactive.
private void DeactivateAllGoodBads()
{
// Deactivate all goods
GameObject[] goodObjects = GameObject.FindGameObjectsWithTag("Good");
foreach (GameObject goodObject in goodObjects)
{
goodObject.SetActive(false);
}
// Deactivate all bads
GameObject[] badObjects = GameObject.FindGameObjectsWithTag("Bad");
foreach (GameObject badObject in badObjects)
{
badObject.SetActive(false);
}
}
public void Store()
{
bool isGood = gameObject.CompareTag("Good");
bool isBad = gameObject.CompareTag("Bad");
if (isGood)
{
moralityCounter++;
Debug.Log(moralityCounter);
}
if (isBad)
{
moralityCounter--;
Debug.Log(moralityCounter);
}
if (isGood || isBad)
{
DeactivateAllGoodBads();
}
}
If there are multiple, you can do something like only disable ones closer to the Stored object than some distance.
private void DeactivateCloseGoodBads(Vector3 position, float maxDistance)
{
// Deactivate close goods
GameObject[] goodObjects = GameObject.FindGameObjectsWithTag("Good");
foreach (GameObject goodObject in goodObjects)
{
// Check distance of found good
if (Vector3.Distance(position, goodObject.transform.position) <= maxDistance) {
goodObject.SetActive(false);
}
}
// Deactivate close bads
GameObject[] badObjects = GameObject.FindGameObjectsWithTag("Bad");
foreach (GameObject badObject in badObjects)
{
// Check distance of found bad
if (Vector3.Distance(position, badObject.transform.position) <= maxDistance) {
badObject.SetActive(false);
}
}
}
public void Store()
{
bool isGood = gameObject.CompareTag("Good");
bool isBad = gameObject.CompareTag("Bad");
if (isGood)
{
moralityCounter++;
Debug.Log(moralityCounter);
}
if (isBad)
{
moralityCounter--;
Debug.Log(moralityCounter);
}
if (isGood || isBad)
{
DeactivateCloseGoodBads(gameObject.transform.position, 10f);
}
}
I am trying to iterate through a list of GameObjects and find the first GameObject that is not active in the hierarchy and return that GameObject.
The problem I am having is my foreach statement keep returning null on "enemy"
"enemy" in this statement below is where the problem is
"GameObject enemy in pizzaEnemyList"
I do have one Gameobject inside of the list. Included in picture below
private List<GameObject> pizzaEnemyList = new List<GameObject> ();
private GameObject FetchPizzaEnemy()
{
GameObject pizzaEnemy = null;
int count = 0;
foreach (GameObject enemy in pizzaEnemyList)
{
if (enemy.activeInHierarchy == false)
{
pizzaEnemy = pizzaEnemyList [count];
pizzaEnemyList.Remove (enemy);
return pizzaEnemy;
}
count += 1;
}
return pizzaEnemy;
}
//Function I am using to add the enemies to the list.
public void DeactivateAndStoreEnemy(GameObject enemy)
{
//decativates the enemy
enemy.SetActive(false);
//Store the enemy into the correct list
if (enemy.name == "PizzaGuy")
{
pizzaEnemyList.Add (enemy);
}
else if (enemy.name == "FiresGuy")
{
friesEnemyList.Add (enemy);
}
else if (enemy.name == "SodaGuy")
{
sodaEnemyList.Add (enemy);
}
}
public int PizzaListUnactiveEnemyCount()
{
int unactiveEnemiesCount = 0;
foreach (GameObject enemies in pizzaEnemyList)
{
if (enemies.activeInHierarchy == false)
{
unactiveEnemiesCount += 1;
}
}
return unactiveEnemiesCount;
}
I have tested your code and can tell you it works if the gameObject are added properly and that they are actually not active.
Your problem is most probably not adding the game objects correctly to the list and maybe also not making sure that pizzaEnemyList has at least 1 item that is set inactive. When all item are active in your list its normal that it returns null because it will never go in if (enemy.activeInHierarchy == false)
It would be better if you had a public List<GameObject> pizzaEnemyList; that you setup in the inspector of unity. Unless if this solution doesn't fit with the game you're building.
As Serlite said you don't need to keep a counter when using foreach, your code could look like this :
private GameObject FetchPizzaEnemy()
{
GameObject pizzaEnemy = null;
foreach (GameObject enemy in pizzaEnemyList)
{
if (enemy.activeInHierarchy == false)
{
pizzaEnemy = enemy;
pizzaEnemyList.Remove(enemy);
return pizzaEnemy;
}
}
return pizzaEnemy;
}
Edit after your edit:
I've tested your code with this and it works :
private List<GameObject> pizzaEnemyList = new List<GameObject>();
void Start()
{
GameObject pizzaGuy = GameObject.Find("PizzaGuy");
DeactivateAndStoreEnemy(pizzaGuy);
Debug.Log(FetchPizzaEnemy());
}
private GameObject FetchPizzaEnemy()
{
GameObject pizzaEnemy = null;
foreach (GameObject enemy in pizzaEnemyList)
{
if (enemy.activeInHierarchy == false)
{
pizzaEnemy = enemy;
pizzaEnemyList.Remove(enemy);
return pizzaEnemy;
}
}
return pizzaEnemy;
}
public void DeactivateAndStoreEnemy(GameObject enemy)
{
enemy.name = "PizzaGuy";
//decativates the enemy
enemy.SetActive(false);
//Store the enemy into the correct list
if (enemy.name == "PizzaGuy")
{
pizzaEnemyList.Add(enemy);
}
}
I have a gameobject named PizzaGuy in my scene.
I have a list of enemys. so i want each enemy have their turn.
First of all :
Player turn --> enemys turn ("here each enemy move one by one untill the end then player move again"). how do i making some waiting time here and forcus on enemy turn?
Any help would be appreciated.
void Start()
{
// find list enemy
enemy = GameObject.FindGameObjectsWithTag("Enemy");
}
void Update()
{
//enemy turn reference to player. after move all enemy we change it to false to change the player turn.
if(StaticClass.enemyTurn == true )
{
for(int i=0;i<enemy.length;i++)
{
// how do i making some waiting time here and forcus on enemy turn?
EnemyTurn(i);
}
}
}
public void EnemyTurn(int id)
{
ChessMoveMent chessMoveScript = enemy[id].GetComponent<ChessMoveMent>();
chessMoveScript.ProcessMove();
id++;
if(id>=enemy.Length)
{
isMove = false;
}
}
I usually use StartCoroutine in this case.
Please try the below code:
public IEnumerator EnemyTurn(int id)
{
yield return null;
ChessMoveMent chessMoveScript = enemy[id].GetComponent<ChessMoveMent>();
chessMoveScript.ProcessMove();
id++;
if(id>=enemy.Length)
{
isMove = false;
}
}
When you want to use it, please use with "StartCoroutine()"
StartCoroutine(EnemyTurn(i));
More details here
You might have a coordinator, who tells the participants when it's their turn.
public class GameCoordinator : MonoBehaviour
{
public List<Participant> participants;
private int currentParticipantIdx = -1;
private Participant CurrentParticipant
{
get { return participants[currentParticipantIdx]; }
}
private void Start()
{
PlayNextMove();
}
private void PlayNextMove()
{
ProceedToNextParticipant();
CurrentParticipant.OnMoveCompleted += OnMoveCompleted;
CurrentParticipant.BeginMove();
}
private void OnMoveCompleted()
{
CurrentParticipant.OnMoveCompleted -= OnMoveCompleted;
StartCoroutine(PlayNextMoveIn(2.0f));
}
private IEnumerator PlayNextMoveIn(float countdown)
{
yield return new WaitForSeconds(countdown);
PlayNextMove();
}
private void ProceedToNextParticipant()
{
++currentParticipantIdx;
if (currentParticipantIdx == participants.Count)
currentParticipantIdx = 0;
}
}
public class Participant : MonoBehaviour
{
public event Action OnMoveCompleted;
public void BeginMove()
{
//
}
}