transform does not exits in current context - c#

I am finding it hard to figure out why my transform is wrong. Can anyone help me on this problem. I am trying to make a FSM for my enemy so it either goes for the player or go for food. But when I try to test it I get a compiler error.
using UnityEngine;
using System.Collections;
public class Enemy : MovingObject
{
public int playerDamage;
private Animator animator;
private Transform target;
private bool skipMove;
private Transform Player;
public AudioClip enemyAttack1;
public AudioClip enemyAttack2;
protected override void Start ()
{
GameManager.instance.AddEnemeyToList(this);
animator = GetComponent<Animator> ();
target = GameObject.FindGameObjectWithTag ("Food").transform;
base.Start ();
AIEnemy();
Player = GameObject.FindWithTag("Player").transform;
}
protected override void AttemptMove<T> (int xDir, int yDir)
{
if (skipMove)
{
skipMove = false;
return;
}
base.AttemptMove <T> (xDir, yDir);
skipMove = true;
}
public void MoveEnemy()
{
int xDir = 0;
int yDir = 0;
if (Mathf.Abs (target.position.x - transform.position.x) < float.Epsilon)
yDir = target.position.y > transform.position.y ? 1 : -1;
else
xDir = target.position.x > transform.position.x ? 1 : -1;
AttemptMove<Player> (xDir, yDir);
}
protected override void OnCantMove <T> (T component)
{
Player hitPlayer = component as Player;
hitPlayer.LoseFood (playerDamage);
animator.SetTrigger("enemyAttack");
SoundManager.instance.RandomizeSfx (enemyAttack1, enemyAttack2);
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Food")
{
other.gameObject.SetActive(false);
}
else if (other.tag == "Soda")
{
other.gameObject.SetActive(false);
}
}
void AIEnemy()
{
int State = 0;
if (State == 0)
{
transform.LookAt(Player);
State++;
}
if (State == 1)
transform.LookAt(target);
Debug.Log("State 1");
State++;
if (State == 2)
{
Debug.Log("State 2");
}
}
}
public Transform FindClosetFood()
{
float minDistance = float.PositiveInfinity;
Transform closetFood = null;
GameObject[] foods = GameObject.FindGameObjectsWithTag("Food");
for(int i = 0; i<foods.Length; i++)
{
float distance = Vector2.Distance(transform.position, foods[i].transform.position);
if (distance < minDistance)
{
minDistance = distance;
closetFood = foods[i].transform;
}
}
return closetFood;
}
}
I added a private Transform Player. So my enemy knows what to look at but I still dont get anything in console. And I tried calling it in start. But now I ended up with this compiler error.
The error comes in this line
float distance = Vector2.Distance("transform".position, foods[i].transform.position);
MovingObject script:
using UnityEngine;
using System.Collections;
public abstract class MovingObject : MonoBehaviour
{
public float moveTime = 0.1f;
public LayerMask blockingLayer;
private BoxCollider2D boxCollider;
private Rigidbody2D rb2D;
private float inverseMoveTime;
// Use this for initialization
protected virtual void Start ()
{
boxCollider = GetComponent<BoxCollider2D> ();
rb2D = GetComponent<Rigidbody2D> ();
inverseMoveTime = 1f / moveTime;
}
protected bool Move (int xDir, int yDir, out RaycastHit2D hit)
{
Vector2 start = transform.position;
Vector2 end = start + new Vector2 (xDir, yDir);
boxCollider.enabled = false;
hit = Physics2D.Linecast (start, end, blockingLayer);
boxCollider.enabled = true;
if (hit.transform == null)
{
StartCoroutine(SmoothMovement (end));
return true;
}
return false;
}
protected IEnumerator SmoothMovement (Vector3 end)
{
float sqrRemainingDistance = (transform.position - end).sqrMagnitude;
while (sqrRemainingDistance > float.Epsilon)
{
Vector3 newPosition = Vector3.MoveTowards (rb2D.position, end, inverseMoveTime * Time.deltaTime);
rb2D.MovePosition(newPosition);
sqrRemainingDistance = (transform.position - end).sqrMagnitude;
yield return null;
}
}
protected virtual void AttemptMove <T> (int xDir, int yDir) where T : Component
{
RaycastHit2D hit;
bool canMove = Move (xDir, yDir, out hit);
if (hit.transform == null)
return;
T hitComponent = hit.transform.GetComponent<T> ();
if(!canMove && hitComponent != null)
OnCantMove (hitComponent);
}
protected abstract void OnCantMove <T> (T component) where T : Component;
}

It can't find transform.position because transform is a variable undeclared under Component. MonoBehaviour drives from Behaviour and Behaviour derives from Component. To get access to the transform variable, your script must derive from one of these. Although MonoBehaviour is what the script should derive from.
In code, your Enemy script already derive from MovingObject script which derives from MonoBehaviour so that should give you access to the transform variable but there is a problem. There is an extra } at the end of the AIEnemy() function in your Enemy script. That extra } at the end of the AIEnemy() function closes or marks the end of the Enemy script therefore making the transform variable unavailable to you. Remove the extra } at the end of the AIEnemy() function and your problem should be fixed.
If you can't find it, use the new Enemy script below:
public class Enemy : MovingObject
{
public int playerDamage;
private Animator animator;
private Transform target;
private bool skipMove;
private Transform Player;
public AudioClip enemyAttack1;
public AudioClip enemyAttack2;
protected override void Start()
{
GameManager.instance.AddEnemeyToList(this);
animator = GetComponent<Animator>();
target = GameObject.FindGameObjectWithTag("Food").transform;
base.Start();
AIEnemy();
Player = GameObject.FindWithTag("Player").transform;
}
protected override void AttemptMove<T>(int xDir, int yDir)
{
if (skipMove)
{
skipMove = false;
return;
}
base.AttemptMove<T>(xDir, yDir);
skipMove = true;
}
public void MoveEnemy()
{
int xDir = 0;
int yDir = 0;
if (Mathf.Abs(target.position.x - transform.position.x) < float.Epsilon)
yDir = target.position.y > transform.position.y ? 1 : -1;
else
xDir = target.position.x > transform.position.x ? 1 : -1;
AttemptMove<Player>(xDir, yDir);
}
protected override void OnCantMove<T>(T component)
{
Player hitPlayer = component as Player;
hitPlayer.LoseFood(playerDamage);
animator.SetTrigger("enemyAttack");
SoundManager.instance.RandomizeSfx(enemyAttack1, enemyAttack2);
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Food")
{
other.gameObject.SetActive(false);
}
else if (other.tag == "Soda")
{
other.gameObject.SetActive(false);
}
}
void AIEnemy()
{
int State = 0;
if (State == 0)
{
transform.LookAt(Player);
State++;
}
if (State == 1)
transform.LookAt(target);
Debug.Log("State 1");
State++;
if (State == 2)
{
Debug.Log("State 2");
}
}
public Transform FindClosetFood()
{
float minDistance = float.PositiveInfinity;
Transform closetFood = null;
GameObject[] foods = GameObject.FindGameObjectsWithTag("Food");
for (int i = 0; i < foods.Length; i++)
{
float distance = Vector2.Distance(transform.position, foods[i].transform.position);
if (distance < minDistance)
{
minDistance = distance;
closetFood = foods[i].transform;
}
}
return closetFood;
}
}

Related

How to make TextArea attribute field to be created for each collider when the events OnTriggerEnter OnTriggerExit occurs?

The script have two states NoEntry and NoExit.
The first problem is the TextToShow.
When the player entered/exited a collider it was showing in the text the same text.
So i changed the textToShow variable to be array type :
public string[] textToShow;
Then according to the state NoEntry/NoExit i used the TextToShow[0] and TextToShow1 and in the inspector i added a text to each textToShow :
What i want to do is to create for each collider for example the player entered or exited a collider, could be i have 10 colliders in the game for that case so if the player hit a collider to identify the collider and add to it some properties in the inspector.
or maybe another way but the idea is to create a TextArea for each collider so i can enter a text and to see in the inspector to what collider or when the text will show.
Same concept for example to the variable : targetToRotateTowards
Now when the player exit/enter he will walk backwards and rotate facing the object in the variable targetToRotateTowards instead i want that in each collider that the player will do something else for example if the collider the state is NoExit move backward face some object but if a collider state is NoEntry so the player should move backwards facing 180 degrees back and not a specific object.
And in the general to extend the script to be more generic for more situations.
Maybe using enum with many cases ? For example if the player enter the small collider he will crash falling dead but if he exit the big collider the player will go backward rotating facing an object.
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityStandardAssets.Characters.ThirdPerson;
public class DistanceCheck : MonoBehaviour
{
public Transform targetToRotateTowards;
public float lerpDuration;
public float rotationSpeed;
[TextArea(1, 2)]
public string[] textToShow;
public GameObject descriptionTextImage;
public TextMeshProUGUI text;
public ThirdPersonUserControl thirdPersonUserControl;
private Animator anim;
private float timeElapsed = 0;
private float startValue = 1;
private float endValue = 0;
private float valueToLerp = 0;
private bool startRotating = false;
private bool slowOnBack = true;
private bool exited = false;
private Vector3 exitPosition;
private float distance;
public string[] TextToShow { get => textToShow; set => textToShow = value; }
void Start()
{
anim = transform.GetComponent<Animator>();
}
private void FixedUpdate()
{
if (startRotating)
{
transform.rotation = Quaternion.RotateTowards(transform.rotation,
Quaternion.LookRotation(targetToRotateTowards.position - transform.position),
rotationSpeed * Time.deltaTime);
}
if (exitPosition != new Vector3(0, 0, 0) && slowOnBack)
{
distance = Vector3.Distance(transform.position, exitPosition);
}
if (distance > 5 && slowOnBack)
{
slowOnBack = false;
StartCoroutine(SlowDown());
}
}
private void OnTriggerExit(Collider other)
{
if (other.tag == "NoExit")
{
descriptionTextImage.SetActive(true);
text.text = TextToShow[0];
RepositionPlayer();
}
else if (other.tag == "NoEntry")
{
OnPlayerRepositioned();
}
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "NoExit")
{
OnPlayerRepositioned();
}
else if (other.tag == "NoEntry")
{
descriptionTextImage.SetActive(true);
text.text = TextToShow[1];
RepositionPlayer();
}
}
private void RepositionPlayer()
{
// Stuff that needs to happen to reposition the player
exited = true;
slowOnBack = true;
exitPosition = transform.position;
thirdPersonUserControl.enabled = false;
StartCoroutine(SlowDown());
}
private void OnPlayerRepositioned()
{
// stuff you need to do to clear the "repositioning" status
exited = false;
startRotating = false;
text.text = "";
descriptionTextImage.SetActive(false);
}
IEnumerator SlowDown()
{
timeElapsed = 0;
while (timeElapsed < lerpDuration)
{
valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
anim.SetFloat("Forward", valueToLerp);
timeElapsed += Time.deltaTime;
yield return null;
}
if (exited)
{
yield return new WaitForSeconds(3f);
startRotating = true;
StartCoroutine(SpeedUp());
}
if (slowOnBack == false)
{
thirdPersonUserControl.enabled = true;
}
}
IEnumerator SpeedUp()
{
timeElapsed = 0;
while (timeElapsed < lerpDuration)
{
valueToLerp = Mathf.Lerp(endValue, startValue, timeElapsed / lerpDuration);
anim.SetFloat("Forward", valueToLerp);
timeElapsed += Time.deltaTime;
yield return null;
}
}
}
After creating the ColliderInfo class i added to the class two properties the second one is :
public Transform rotateTowards;
The class :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColliderInfo : MonoBehaviour
{
[TextArea] public string onEnterText, onExitText;
public Transform rotateTowards;
}
Then in the DistanceCheck script i removed deleted the variable targetToRotateTowards and added a private ColliderInfo variable :
private ColliderInfo colliderInfo;
Then created instance in the Start :
void Start()
{
anim = transform.GetComponent<Animator>();
colliderInfo = new ColliderInfo();
}
And using it in the FixedUpdate :
private void FixedUpdate()
{
if (startRotating)
{
transform.rotation = Quaternion.RotateTowards(transform.rotation,
Quaternion.LookRotation(colliderInfo.rotateTowards.position - transform.position),
rotationSpeed * Time.deltaTime);
}
The problem is that rotateTowrads is type Transform but if i want the transform to rotate by degrees and not facing the rotateTowards transform ?
The complete DistanceCheck script after changes :
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityStandardAssets.Characters.ThirdPerson;
public class DistanceCheck : MonoBehaviour
{
public float lerpDuration;
public float rotationSpeed;
public GameObject descriptionTextImage;
public TextMeshProUGUI text;
public ThirdPersonUserControl thirdPersonUserControl;
private Animator anim;
private float timeElapsed = 0;
private float startValue = 1;
private float endValue = 0;
private float valueToLerp = 0;
private bool startRotating = false;
private bool slowOnBack = true;
private bool exited = false;
private Vector3 exitPosition;
private float distance;
private ColliderInfo colliderInfo;
void Start()
{
anim = transform.GetComponent<Animator>();
colliderInfo = new ColliderInfo();
}
private void FixedUpdate()
{
if (startRotating)
{
transform.rotation = Quaternion.RotateTowards(transform.rotation,
Quaternion.LookRotation(colliderInfo.rotateTowards.position - transform.position),
rotationSpeed * Time.deltaTime);
}
if (exitPosition != new Vector3(0, 0, 0) && slowOnBack)
{
distance = Vector3.Distance(transform.position, exitPosition);
}
if (distance > 5 && slowOnBack)
{
slowOnBack = false;
StartCoroutine(SlowDown());
}
}
private void OnTriggerExit(Collider other)
{
if (other.tag == "NoExit")
{
descriptionTextImage.SetActive(true);
if (other.TryGetComponent(out ColliderInfo info))
{
text.text = info.onExitText;
}
RepositionPlayer();
}
else if (other.tag == "NoEntry")
{
OnPlayerRepositioned();
}
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "NoExit")
{
OnPlayerRepositioned();
}
else if (other.tag == "NoEntry")
{
descriptionTextImage.SetActive(true);
if (other.TryGetComponent(out ColliderInfo info))
{
text.text = info.onEnterText;
}
RepositionPlayer();
}
}
private void RepositionPlayer()
{
// Stuff that needs to happen to reposition the player
exited = true;
slowOnBack = true;
exitPosition = transform.position;
thirdPersonUserControl.enabled = false;
StartCoroutine(SlowDown());
}
private void OnPlayerRepositioned()
{
// stuff you need to do to clear the "repositioning" status
exited = false;
startRotating = false;
text.text = "";
descriptionTextImage.SetActive(false);
}
IEnumerator SlowDown()
{
timeElapsed = 0;
while (timeElapsed < lerpDuration)
{
valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
anim.SetFloat("Forward", valueToLerp);
timeElapsed += Time.deltaTime;
yield return null;
}
if (exited)
{
yield return new WaitForSeconds(3f);
startRotating = true;
StartCoroutine(SpeedUp());
}
if (slowOnBack == false)
{
thirdPersonUserControl.enabled = true;
}
}
IEnumerator SpeedUp()
{
timeElapsed = 0;
while (timeElapsed < lerpDuration)
{
valueToLerp = Mathf.Lerp(endValue, startValue, timeElapsed / lerpDuration);
anim.SetFloat("Forward", valueToLerp);
timeElapsed += Time.deltaTime;
yield return null;
}
}
}
Although there are other ways to solve this problem, centralized methods such as giving all the information to the player script by expanding the project also make it more difficult to control. The best way I can suggest you is to give the colliders information themselves, so create a ColliderInfo script like the one below and place it on the target areas.
public class ColliderInfo : MonoBehaviour
{
[TextArea] public string onEnterText, onExitText;
}
Once this is done, it is enough to call the information of each collider by going to that area, just as easily and with the same efficiency! The following code is written in the player and solves the problem. Keep in mind to create similar colliders just prefab them.
private void OnTriggerEnter(Collider other)
{
if (other.TryGetComponent(out ColliderInfo info))
{
Debug.Log(info.onEnterText);
}
}
private void OnTriggerExit(Collider other)
{
if (other.TryGetComponent(out ColliderInfo info))
{
Debug.Log(info.onExitText);
}
}
Extent of methods
The attribution method is not limited to text, for example you can define an enum of a general collider type to allow the player to react differently to different locations, or even to define the temperature in general.
public enum Type
{
None,
Hot,
Cold,
}
public Type type = Type.Hot;
Below is an example of such a structure that instead of defining a name and tag, how can you define everything related to properties, consider never entering player rotation codes in collider info, below from an object-oriented programming perspective this property belongs To the player.
if (other.TryGetComponent(out ColliderInfo info))
{
Debug.Log(info.onEnterText);
switch (info.type)
{
case ColliderInfo.Type.Hot:
Reposition();
inHotArea = true; // deal damage until staying in hot area
MeshRenderer.material.color = Color.red;
break;
case ColliderInfo.Type.Cold:
inColdArea = true; // slow effect like decreasing movement speed
MeshRenderer.material.color = Color.cyan;
break;
}
}

Ammo Limitations in Unity2D (Top Down)

I am fairly new to C# and am currently trying to expand upon Ruby's Tutorial by adding in an ammo limitation function that controls the amount of Cogs Ruby has at a time as well as her ability to pick up extra ammo. Right now my script is not limiting the number of rounds Ruby can fire and is stuck displaying "Cogs: 4". She is able to pick up the ammo (pickup set to is trigger) but it is not updating the Cogs. Please help, I would love to understand what I am possibly doing wrong as my code is not displaying any errors.
Ruby's Controller Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.SceneManagement;
public class RubyController : MonoBehaviour
{
public float speed = 3.0f;
public int maxHealth = 5;
public GameObject projectilePrefab;
public int Score;
int Cog;
public static int CogAmount = 4;
public TextMeshProUGUI scoreText;
public TextMeshProUGUI CogText;
public GameObject winTextObject;
public GameObject loseTextObject;
public GameObject BackgroundMusicObject;
public GameObject WinSoundObject;
public GameObject LoseSoundObject;
public AudioClip throwSound;
public AudioClip hitSound;
public AudioClip collectedClip;
public int health { get { return currentHealth; }}
int currentHealth;
public float timeInvincible = 2.0f;
bool isInvincible;
float invincibleTimer;
Rigidbody2D rigidbody2d;
float horizontal;
float vertical;
public ParticleSystem HealthIncrease;
public ParticleSystem HealthDecrease;
Animator animator;
Vector2 lookDirection = new Vector2(1,0);
AudioSource audioSource;
// Start is called before the first frame update
void Start()
{
rigidbody2d = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
currentHealth = maxHealth;
audioSource = GetComponent<AudioSource>();
Score = 0;
Cog = 4;
SetCogText();
winTextObject.SetActive(false);
loseTextObject.SetActive(false);
WinSoundObject.SetActive(false);
LoseSoundObject.SetActive(false);
HealthIncrease.Stop();
HealthDecrease.Stop();
}
public void ChangeScore(int scoreAmount)
{
{
Score++;
scoreText.text = "Fixed Robots: " + Score.ToString();
}
}
// Update is called once per frame
void Update()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
Vector2 move = new Vector2(horizontal, vertical);
if(!Mathf.Approximately(move.x, 0.0f) || !Mathf.Approximately(move.y, 0.0f))
{
lookDirection.Set(move.x, move.y);
lookDirection.Normalize();
}
animator.SetFloat("Look X", lookDirection.x);
animator.SetFloat("Look Y", lookDirection.y);
animator.SetFloat("Speed", move.magnitude);
if (isInvincible)
{
invincibleTimer -= Time.deltaTime;
if (invincibleTimer < 0)
isInvincible = false;
}
if(Input.GetKeyDown(KeyCode.C) && Cog >= 1)
{
Cog = Cog -1;
Launch();
}
else if (Input.GetKeyDown(KeyCode.C) && Cog ==0)
{
return;
}
if (Input.GetKeyDown(KeyCode.X))
{
RaycastHit2D hit = Physics2D.Raycast(rigidbody2d.position + Vector2.up * 0.2f, lookDirection, 1.5f, LayerMask.GetMask("NPC"));
if (hit.collider != null)
{
NonPlayerCharacter character = hit.collider.GetComponent<NonPlayerCharacter>();
if (character != null)
{
character.DisplayDialog();
}
}
}
if (CogAmount > 0)
{
CogText.text = "Cogs: " + CogAmount;
}
else if (CogAmount <= 0)
{
CogText.text = "Out of Cogs!";
}
if (Score >= 4)
{
winTextObject.SetActive(true);
{
if(Input.GetKeyDown(KeyCode.R))
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
speed = 0;
WinSoundObject.SetActive(true);
BackgroundMusicObject.SetActive(false);
}
}
else if (currentHealth == 0)
{
loseTextObject.SetActive(true);
{
if(Input.GetKeyDown(KeyCode.R))
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
speed = 0;
LoseSoundObject.SetActive(true);
BackgroundMusicObject.SetActive(false);
}
}
if (Input.GetKeyDown(KeyCode.Escape))
{
Application.Quit();
}
}
void FixedUpdate()
{
Vector2 position = rigidbody2d.position;
position.x = position.x + speed * horizontal * Time.deltaTime;
position.y = position.y + speed * vertical * Time.deltaTime;
rigidbody2d.MovePosition(position);
}
void SetCogText()
{
CogText.text = "Cogs: " + Cog.ToString();
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Cog"))
{
Cog = Cog + 3;
other.gameObject.SetActive(false);
}
}
public void ChangeHealth(int amount)
{
if (amount < 0)
{
if (isInvincible)
return;
isInvincible = true;
invincibleTimer = timeInvincible;
GameObject projectileObject = Instantiate(HealthDecrease.gameObject, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity);
Projectile projectile = projectileObject.GetComponent<Projectile>();
PlaySound(hitSound);
}
if (amount < 5)
{
GameObject projectileObject = Instantiate(HealthIncrease.gameObject, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity);
}
currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
UIHealthBar.instance.SetValue(currentHealth / (float)maxHealth);
}
void Launch()
{
GameObject projectileObject = Instantiate(projectilePrefab, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity);
Projectile projectile = projectileObject.GetComponent<Projectile>();
projectile.Launch(lookDirection, 300);
animator.SetTrigger("Launch");
PlaySound(throwSound);
}
public void PlaySound(AudioClip clip)
{
audioSource.PlayOneShot(clip);
}
}
Projectile Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
Rigidbody2D rigidbody2d;
void Awake()
{
rigidbody2d = GetComponent<Rigidbody2D>();
}
public void Launch(Vector2 direction, float force)
{
rigidbody2d.AddForce(direction * force);
}
void Update()
{
if(transform.position.magnitude > 1000.0f)
{
Destroy(gameObject);
}
}
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "Enemy")
{
EnemyController e = other.collider.GetComponent<EnemyController>();
if (e != null)
{
e.Fix();
}
}
else if (other.gameObject.tag == "HardEnemy")
{
HardEnemyController e = other.collider.GetComponent<HardEnemyController>();
if (e != null)
{
e.Fix();
}
}
Destroy(gameObject);
}
}
Ok after a bit of trial and error I believe I have finally fixed the issue. I will post my updated script for anyone wanting to compare and/or learn from my mistakes lol. Basically I utilized a SetCogText(); variable in the start function and throughout my code to update my TextMeshPro; and removed the public static int CogAmount = 0; I initially used in my code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.SceneManagement;
public class RubyController : MonoBehaviour
{
public float speed = 3.0f;
public int maxHealth = 5;
public GameObject projectilePrefab;
public int Score;
int Cog;
public TextMeshProUGUI scoreText;
public TextMeshProUGUI CogText;
public GameObject winTextObject;
public GameObject loseTextObject;
public GameObject LevelOneTextObject;
public GameObject BackgroundMusicObject;
public GameObject WinSoundObject;
public GameObject LoseSoundObject;
private static int Level;
public AudioClip throwSound;
public AudioClip hitSound;
public AudioClip collectedClip;
public int health { get { return currentHealth; }}
int currentHealth;
public float timeInvincible = 2.0f;
bool isInvincible;
float invincibleTimer;
Rigidbody2D rigidbody2d;
float horizontal;
float vertical;
public ParticleSystem HealthIncrease;
public ParticleSystem HealthDecrease;
Animator animator;
Vector2 lookDirection = new Vector2(1,0);
AudioSource audioSource;
// Start is called before the first frame update
void Start()
{
rigidbody2d = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
currentHealth = maxHealth;
audioSource = GetComponent<AudioSource>();
Score = 0;
Cog = 4;
SetCogText();
winTextObject.SetActive(false);
loseTextObject.SetActive(false);
LevelOneTextObject.SetActive(false);
WinSoundObject.SetActive(false);
LoseSoundObject.SetActive(false);
HealthIncrease.Stop();
HealthDecrease.Stop();
}
public void ChangeScore(int scoreAmount)
{
{
Score++;
scoreText.text = "Fixed Robots: " + Score.ToString();
}
if (Level == 1)
{
if (Score == 4)
{
LevelOneTextObject.SetActive(true);
}
}
if (Level == 2)
{
if(Score == 4)
{
winTextObject.SetActive(true);
{
if(Input.GetKeyDown(KeyCode.R))
SceneManager.LoadScene(1);
speed = 0;
WinSoundObject.SetActive(true);
BackgroundMusicObject.SetActive(false);
}
}
}
}
// Update is called once per frame
void Update()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
Vector2 move = new Vector2(horizontal, vertical);
if(!Mathf.Approximately(move.x, 0.0f) || !Mathf.Approximately(move.y, 0.0f))
{
lookDirection.Set(move.x, move.y);
lookDirection.Normalize();
}
animator.SetFloat("Look X", lookDirection.x);
animator.SetFloat("Look Y", lookDirection.y);
animator.SetFloat("Speed", move.magnitude);
if (isInvincible)
{
invincibleTimer -= Time.deltaTime;
if (invincibleTimer < 0)
isInvincible = false;
}
if(Input.GetKeyDown(KeyCode.C) && Cog >= 1)
{
Cog = Cog -1;
SetCogText();
Launch();
}
else if (Input.GetKeyDown(KeyCode.C) && Cog ==0)
{
return;
}
if (Input.GetKeyDown(KeyCode.X))
{
RaycastHit2D hit = Physics2D.Raycast(rigidbody2d.position + Vector2.up * 0.2f, lookDirection, 1.5f, LayerMask.GetMask("NPC"));
if (hit.collider != null)
{
if (Score >= 4)
{
Level = 2;
SceneManager.LoadScene(2);
Score = 4;
}
else if (Score < 4)
{
NonPlayerCharacter character = hit.collider.GetComponent<NonPlayerCharacter>();
if (character != null)
{
character.DisplayDialog();
}
}
}
}
if (currentHealth == 0)
{
loseTextObject.SetActive(true);
{
if(Input.GetKeyDown(KeyCode.R))
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
speed = 0;
LoseSoundObject.SetActive(true);
BackgroundMusicObject.SetActive(false);
}
}
if (Input.GetKeyDown(KeyCode.Escape))
{
Application.Quit();
}
}
void SetCogText()
{
if (Cog > 0)
{
CogText.text = "Cogs: " + Cog.ToString();
}
else if (Cog <= 0)
{
CogText.text = "Out of Cogs!";
SetCogText();
}
}
void FixedUpdate()
{
Vector2 position = rigidbody2d.position;
position.x = position.x + speed * horizontal * Time.deltaTime;
position.y = position.y + speed * vertical * Time.deltaTime;
rigidbody2d.MovePosition(position);
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Cog"))
{
Cog = Cog + 3;
other.gameObject.SetActive(false);
SetCogText();
}
}
public void ChangeHealth(int amount)
{
if (amount < 0)
{
if (isInvincible)
return;
isInvincible = true;
invincibleTimer = timeInvincible;
GameObject projectileObject = Instantiate(HealthDecrease.gameObject, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity);
Projectile projectile = projectileObject.GetComponent<Projectile>();
PlaySound(hitSound);
}
if (amount < 5)
{
GameObject projectileObject = Instantiate(HealthIncrease.gameObject, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity);
}
currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
UIHealthBar.instance.SetValue(currentHealth / (float)maxHealth);
}
void Launch()
{
GameObject projectileObject = Instantiate(projectilePrefab, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity);
Projectile projectile = projectileObject.GetComponent<Projectile>();
projectile.Launch(lookDirection, 300);
animator.SetTrigger("Launch");
PlaySound(throwSound);
}
public void PlaySound(AudioClip clip)
{
audioSource.PlayOneShot(clip);
}
}

Spawn AI when player is around (Unity3d/C#)

I have a script that currently spawns enemies by set positions (point spawn). I am wondering how am I able to make them spawn ONLY when player is, for example, within 50 meters from spawn-point.
Wander Manager:
public class WanderingManager : MonoBehaviour {
public Transform[] wanderingPoints;
void getNewPos(GameObject target){
target.SendMessage("setNewWanderPos", wanderingPoints[Random.Range(0, wanderingPoints.Length)].position, SendMessageOptions.DontRequireReceiver);
}
}
Enemy Manager script:
[RequireComponent (typeof (WanderingManager))]
public class EnemyManager: MonoBehaviour {
public int maxZombies = 7;
public float spawnInterval = 5.0f;
public string zombiesTag = "Zombie", playerTag = "Player";
public GameObject[] ZombiePrefabs = null;
private GameObject player = null;
private ArrayList Zombies = new ArrayList();
private float lastTime = -10.0f;
private bool loaded = false;
private WanderingManager manager;
void Start () {
manager = GetComponent<WanderingManager>();
findPlayer();
}
// Update is called once per frame
void LateUpdate () {
if(player == null && loaded){
StartCoroutine(Restart());
}
if(Time.time > lastTime){
for(int i=0; i<Zombies.Count; i++){
if(Zombies[i] == null){
Zombies.RemoveAt(i);
}
}
if(Zombies.Count > maxZombies){
Zombies.RemoveAt(Zombies.Count - 1);
}else{
Transform point = manager.wanderingPoints[Random.Range(0, manager.wanderingPoints.Length)];
GameObject Z = Instantiate(ZombiePrefabs[Random.Range(0, ZombiePrefabs.Length)], point.position, point.rotation * Quaternion.Euler(0.0f, Random.Range(0.0f, 180.0f), 0.0f)) as GameObject;
Zombies.Add(Z);
}
lastTime = Time.time + spawnInterval;
}
}
void findPlayer(){
GameObject newPlayer = GameObject.FindWithTag(playerTag);
if(newPlayer != null && !newPlayer.name.Contains("Clone")){
player = newPlayer;
loaded = true;
}else if(newPlayer != null && newPlayer.name.Contains("Clone")){
Destroy(newPlayer);
retrySearch();
}
}
void retrySearch(){
findPlayer();
}
IEnumerator Restart(){
yield return new WaitForSeconds(10.0f);
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
Any help will be appreciated. Thanks!
Just do a distance check. Something like this:
if (Vector3.Distance(player.transform.position,enemySpawn.transform.position) < 50):
{
spawnEnemyLogic();
}

Displaying and decrementing hp based on collision detection

So I have enemy gameobjects attacking a user in a small base. The enemies have an OnCollisionEnter method where it checks to see what it collides with. If it's tagged as the base, it sets an attack boolean to true, where the fixedupdate is supposed to check for that flag. When true, it calls a coroutine in which I try and call the method that removes health from the wall (this script is attached to the wall). The walls health is then displayed on a HUD I have elsewhere in the room Code Below
Problem is, enemies can't do damage to the base and the HUD remains unchanging. Any tips/help? Here is the enemy behaviour script
public class EnemyBehaviour : MonoBehaviour {
private GameObject target;
private Vector3 targetPos;
private WallBehaviour wallBehaviour;
public GameObject collisionObject;
private bool attackMode;
public float speed = 0.1f;
public int hp = 100;
public float attackCooldown = 1.0f;
public int attackPoints = 1;
public float killThreshhold = 1.5f;
public Color defaultColor;
//Use this for initialization
void Start() {
target = GameObject.FindGameObjectWithTag("MainCamera");
targetPos = target.transform.position;
attackMode = false;
}
void FixedUpdate() {
targetPos = target.transform.position;
transform.LookAt(target.transform);
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, targetPos, step);
if (attackMode)
{
StartCoroutine("attemptAttack");
}
else
{
GetComponent<Renderer>().material.color = defaultColor;
}
}
void OnCollisionEnter(Collision collision)
{
collisionObject = collision.gameObject;
if (collision.gameObject.tag == "Bunker") {
wallBehaviour = collision.gameObject.GetComponent<WallBehaviour>();
attackMode = true;
}
}
public IEnumerator Attack()
{
attackMode = false;
GetComponent<Renderer>().material.color = Color.red;
wallBehaviour.ProcessDamage(attackPoints);
yield return new WaitForSeconds(attackCooldown);
attackMode = true;
}
void ProcessDamage(int attackPoints)
{
hp -= attackPoints;
if (hp <= 0)
{
Die();
}
}
public int getHitPoints()
{
return hp;
}
public void Damage(DamageInfo info)
{
hp -= info.damage;
if (hp <= 0) {
Die();
}
}
public void Die()
{
Destroy(gameObject);
}

Bullet spawn stops/buggs randomly

I'm having some difficulties with my shooting script. Normally the bullets works just fine but sometimes(totally random) I can't shoot any more.
I can see the sprite right beside my character but it doesn't move. And if that happens it can't be fixed until I restart the game.
The weapon Script is on the player
public class weaponScript : MonoBehaviour {
public Transform shotPrefab;
public float shootingRate = 0.25f;
private float shootCooldown;
public float xtrans;
void Start(){
shootCooldown = 0f;
}
void Update(){
if (shootCooldown > 0){
shootCooldown -= Time.deltaTime;
}
}
public void Attack(bool isEnemy)
{
if (CanAttack){
if(PinkPlayerControler.playerFaceRight == true)
xtrans = transform.position.x + 2f;
else if(PinkPlayerControler.playerFaceRight == false)
xtrans = transform.position.x - 2f;
shootCooldown = shootingRate;
var shotTransform = Instantiate(shotPrefab) as Transform;
//shotTransform.position = transform.position;
shotTransform.position = new Vector3(xtrans, transform.position.y,transform.position.z);
}
}
public bool CanAttack
{
get{
return shootCooldown <= 0f;
}
}
}
And the other two on the bullet
public class bulletMove : MonoBehaviour {
public Vector2 jumpVector;
public int speed;
void Update(){
startMovement ();
}
void startMovement(){
if (PinkPlayerControler.playerFaceRight == true) {
rigidbody2D.velocity = transform.right.normalized * speed;
Destroy(this);
}
else {
rigidbody2D.velocity = -transform.right.normalized * speed;
Destroy(this);
}
}
void OnTriggerEnter2D(Collider2D other){
if (other.tag == "bulletDeath" || other.tag == "groundTrap")
Destroy (this.gameObject);
else if (other.tag == "destroyByBullet") {
Debug.Log("blockHit");
Destroy (other.gameObject);
Destroy(this.gameObject);
}
}
}
Shoot Script
public class shootScript : MonoBehaviour {
public static int damage = 1;
public static bool hit = false;
void Start()
{
Destroy(gameObject, 2);
}
void Update(){
if (hit == true)
Destroy (this.gameObject);
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "bullet") {
Destroy(other.gameObject);
}
}
}
I don't get why it stops to work so randomly.
Thanks in advance :)
Chrizzly

Categories

Resources