I have a problem with collision. Sometimes it works right, but when I move with blue object inside red object, collision changes side and works bad. For example I add ZIP file: here
Generator script:
public class Generator : MonoBehaviour
{
public GameObject obstaclePrefab;
Dictionary<string, GameObject> obstacles;
Dictionary<string, Quaternion> rotations; // default rotation = open to the left
void Start()
{
rotations = new Dictionary<string, Quaternion>()
{
{ "left", Quaternion.Euler(0,0,0) },
{ "down", Quaternion.Euler(0,0,90) },
{ "right", Quaternion.Euler(0,180,0) },
{ "up", Quaternion.Euler(0,0,270) }
};
obstacles = new Dictionary<string, GameObject>();
SpawnObstacle(new Vector2(3,0),"left");
}
void SpawnObstacle(Vector2 position, string openSide)
{
//TODO
print("SpawnObstacle()");
GameObject go = (GameObject)Instantiate(obstaclePrefab, position, rotations[openSide]);
go.GetComponent<Obstacle>().openSide = openSide;
string pos = position.x + "_" + position.y;
obstacles.Add(pos, go);
}
public GameObject GetObjectAt(Vector3 position)
{
string pos = position.x + "_" + position.y;
if (obstacles.ContainsKey(pos) == true)
{
print(obstacles[pos]);
return obstacles[pos];
}
else return null;
}
}
PlayerMove script:
public class PlayerMove : MonoBehaviour
{
public Generator generator;
Vector3 pos;
public float speed;
void Start()
{
pos = transform.position;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
GameObject go = generator.GetObjectAt(transform.position - new Vector3(speed, 0, 0));
if (go == null || go.GetComponent<Obstacle>().canEnterFromSide("left"))
{
print(go);
pos.x -= speed;
}
}
else if (Input.GetKeyDown(KeyCode.RightArrow))
{
GameObject go = generator.GetObjectAt(transform.position + new Vector3(speed, 0, 0));
if (go == null || go.GetComponent<Obstacle>().canEnterFromSide("right"))
{
print(go);
pos.x += speed;
}
}
else if (Input.GetKeyDown(KeyCode.UpArrow))
{
GameObject go = generator.GetObjectAt(transform.position + new Vector3(0, speed, 0));
if (go == null || go.GetComponent<Obstacle>().canEnterFromSide("up"))
{
print(go);
pos.y += speed;
}
}
else if (Input.GetKeyDown(KeyCode.DownArrow))
{
GameObject go = generator.GetObjectAt(transform.position - new Vector3(0, speed, 0));
if (go == null || go.GetComponent<Obstacle>().canEnterFromSide("down"))
{
print(go);
pos.y -= speed;
}
}
transform.position = Vector2.MoveTowards(transform.position, pos, speed);
}
void OnTriggerEnter2D(Collider2D col)
{
if (col.CompareTag("obstacle"))
{
col.gameObject.GetComponent<Obstacle>().Move(true);
print("obstacle");
}
/* else if (col.transform.root.GetComponent<Obstacle>().openSide == "left")
{
}*/
}
}
Obstacle script:
public class Obstacle : MonoBehaviour {
Vector3 pos;
GameObject player;
bool move = false;
public string openSide;
void Start () {
player = GameObject.FindWithTag("Player");
pos = transform.position;
}
public bool Move(bool mo)
{
if(mo)
move = true;
return move;
}
void Update () {
if (openSide == "left" && Input.GetKeyDown(KeyCode.LeftArrow))
move = false;
if (openSide == "right" && Input.GetKeyDown(KeyCode.RightArrow))
move = false;
if (openSide == "up" && Input.GetKeyDown(KeyCode.UpArrow))
move = false;
if (openSide == "down" && Input.GetKeyDown(KeyCode.DownArrow))
move = false;
if (move)
transform.position = player.transform.position;
}
public bool canEnterFromSide(string side)
{
return side == openSide;
}
}
Related
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);
}
}
I am using Destroy(Corazones[0].gameObject); to destroy 5 hearts in an array, but I need to restore them when the player gets another heart. I already have the collider that increases lives +1 and it works, but I do not know how to respawn the heart that represents that life.
The hearts get destroyed when the player gets Hit(); but I also need for the hearts to get restored with Vida(); which increases the live +1
Thanks for your help!
This is the way the hearts look
My code uses spanish words.
PD: I know my code is a mess, but works for the other stuff.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityStandardAssets.CrossPlatformInput;
using UnityEngine.UI;
public class DixonMovement : MonoBehaviour
{
public GameObject PildoraPrefab;
public float Speed;
public float JumpForce;
public AudioClip Golpe;
public AudioClip Salto;
public AudioClip Muerte;
public AudioClip Caida;
public GameObject[] Corazones;
private Rigidbody2D Rigidbody2D;
private Animator Animator;
private float Horizontal;
private bool Grounded;
private float LastShoot;
private int Health = 5;
public bool YaSono = false;
[Header("IFrame Stuff")]
public Color flashColor;
public Color regularColor;
public float flashDuration;
public int numberOfFlashes;
public Collider2D triggerCollider;
public SpriteRenderer mySprite;
float timer;
bool invencible = false;
private void Start()
{
Rigidbody2D = GetComponent<Rigidbody2D>();
Animator = GetComponent<Animator>();
}
// Update is called once per frame
private void Update()
{
timer -= Time.deltaTime;
if (timer <= 0)
{
invencible = false;
}
Horizontal = CrossPlatformInputManager.GetAxis("Horizontal");
if (Horizontal < 0.0f) transform.localScale = new Vector3(-1.0f, 1.0f, 1.0f);
else if (Horizontal > 0.0f) transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
Animator.SetBool("Caminar", Horizontal != 0.0f);
Debug.DrawRay(transform.position, Vector3.down * 0.5f, Color.red);
if (Physics2D.Raycast(transform.position, Vector3.down, 0.5f))
{
Grounded = true;
}
else Grounded = false;
if (CrossPlatformInputManager.GetButtonDown("Jump") && Grounded)
{
Jump();
}
if (Input.GetKeyDown(KeyCode.W) && Grounded)
{
Jump();
}
if (Input.GetKey(KeyCode.Space) && Time.time > LastShoot + 0.25f)
{
Shoot();
LastShoot = Time.time;
}
if (CrossPlatformInputManager.GetButtonDown("Shoot") && Time.time > LastShoot + 0.50f)
{
Shoot();
LastShoot = Time.time;
}
/* if (CrossPlatformInputManager.GetButtonDown("Vertical") && Time.time > LastShoot + 0.50f)
{
Shoot();
LastShoot = Time.time;
}*/
if (transform.position.y <= -2)
{
Fall();
}
}
private void FixedUpdate()
{
Rigidbody2D.velocity = new Vector2(Horizontal * Speed, Rigidbody2D.velocity.y);
}
private void Jump()
{
Rigidbody2D.AddForce(Vector2.up * JumpForce);
Camera.main.GetComponent<AudioSource>().PlayOneShot(Salto);
}
private void Shoot()
{
Vector3 direction;
if (transform.localScale.x == 1.0f) direction = Vector3.right;
else direction = Vector3.left;
GameObject pastilla = Instantiate(PildoraPrefab, transform.position + direction * 0.40f, Quaternion.identity);
pastilla.GetComponent<Pastilla>().SetDirection(direction);
}
**public void Hit()
{
Health -= 1;
if (Health > 0)
{
StartCoroutine(FlashCo());
}
if (Health < 1)
{
Destroy(Corazones[0].gameObject);
}
else if (Health < 2)
{
Destroy(Corazones[1].gameObject);
}
else if (Health < 3)
{
Destroy(Corazones[2].gameObject);
}
else if (Health < 4)
{
Destroy(Corazones[3].gameObject);
}
else if (Health < 5)
{
Destroy(Corazones[4].gameObject);
}
if (Health > 0)
{
Camera.main.GetComponent<AudioSource>().PlayOneShot(Golpe);
}**
if (Health == 0)
{
Camera.main.GetComponent<AudioSource>().PlayOneShot(Muerte);
Animator.SetTrigger("Muerte");
if (Grounded == false)
{
Rigidbody2D.bodyType = RigidbodyType2D.Dynamic;
Rigidbody2D.gravityScale = 2;
}
else
{
Rigidbody2D.bodyType = RigidbodyType2D.Static;
}
}
}
public void Fall()
{
if (transform.position.y <= -1)
{
Rigidbody2D.AddForce(Vector2.up * 60);
if (!YaSono)
{
Camera.main.GetComponent<AudioSource>().PlayOneShot(Caida);
YaSono = true;
}
Animator.SetTrigger("Muerte");
Health = 0;
Destroy(Rigidbody2D, 2);
Destroy(Corazones[0].gameObject);
Destroy(Corazones[1].gameObject);
Destroy(Corazones[2].gameObject);
Destroy(Corazones[3].gameObject);
Destroy(Corazones[4].gameObject);
Invoke("RestartLevel", 2);
}
}
public void Vida()
{
if (Health >=5) { } else { Health += 1; }
}
public void Bounce()
{
Rigidbody2D.AddForce(Vector2.up * 300);
}
void Invencible()
{
timer = 1;
if (timer > 0)
{
invencible = true;
}
}
private IEnumerator FlashCo()
{
int temp = 0;
triggerCollider.enabled = false;
while (temp < numberOfFlashes)
{
mySprite.color = flashColor;
yield return new WaitForSeconds(flashDuration);
mySprite.color = regularColor;
yield return new WaitForSeconds(flashDuration);
temp++;
}
triggerCollider.enabled = true;
}
private void RestartLevel()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
Instead of using Destroy(Corazones[0].gameObject) you could use Corazones[0].gameObject.setActive(false) or simply Corazones[0].setActive(false) since the array already contains GameObjects.
This would preserve the GameObject while all of its components and children would be inactivated including its Renderer which would make it disappear.
Then later when you need it you could reactivate it using Corazones[0].setActive(true).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class loadingcolorful : MonoBehaviour
{
public float speed = 0.0f;
public bool fillAmount = false;
public bool rotate = false;
public bool changeRotationDir = false;
public bool changeFillDir = false;
private RectTransform rectTransform;
private Image imageComp;
// Use this for initialization
void Start()
{
imageComp = GetComponent<RectTransform>().GetComponent<Image>();
rectTransform = transform.parent.gameObject.transform.GetComponent<RectTransform>();
}
// Update is called once per frame
void Update()
{
if (fillAmount == true)
{
if (imageComp.fillAmount != 1f)
{
if (changeFillDir == true)
{
imageComp.fillAmount -= speed;
}
else
{
imageComp.fillAmount += speed;
}
}
else
{
imageComp.fillAmount = 0f;
}
}
else
{
if (imageComp.fillAmount == 0f)
{
imageComp.fillAmount = 0f;
}
else
{
imageComp.fillAmount = 1f;
}
}
if (rotate == true)
{
if (changeRotationDir == true)
{
rectTransform.Rotate(new Vector3(0, 0, -1));
}
else
{
rectTransform.Rotate(new Vector3(0, 0, 1));
}
}
}
}
The problem is at this place :
if (changeFillDir == true)
{
imageComp.fillAmount -= speed;
}
When it will get to 0 it will not continue to fill the image to the other direction just the image will stay empty. My guess is that the values of the FillAmount ragne is between 1 and 0.
Is there a way to make it happen ?
It's a bit of a hack, but you can switch to a negative scale value and start increasing the fillAmout again. This will make it fill in the other direction, taking the 0 point as pivot.
Assuming you are filling horizontally, flipping the scale would look something like this:
transform.localScale = new Vector3(-1, 1, 1);
A working solution like I wanted :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class loadingcolorful : MonoBehaviour
{
public float speed = 0.0f;
public bool fillAmount = false;
public bool rotate = false;
public bool changeRotationDir = false;
public bool changeFillDir = false;
public bool useBackGroundImage = true;
private RectTransform rectTransform;
private Image imageComp;
private Image backGroundImage;
// Use this for initialization
void Start()
{
imageComp = GetComponent<RectTransform>().GetComponent<Image>();
backGroundImage = transform.parent.gameObject.transform.GetComponent<Image>();
UseBackgImage();
}
// Update is called once per frame
void Update()
{
UseBackgImage(useBackGroundImage);
if (fillAmount == true)
{
if (imageComp.fillAmount != 1f)
{
if (changeFillDir == true)
{
if (imageComp.fillAmount == 0)
{
imageComp.fillAmount = 1f;
}
imageComp.fillAmount -= speed;
}
else
{
imageComp.fillAmount += speed;
}
}
else
{
imageComp.fillAmount = 0f;
}
}
else
{
if (imageComp.fillAmount == 0f)
{
imageComp.fillAmount = 0f;
}
else
{
imageComp.fillAmount = 1f;
}
}
if (rotate == true)
{
if (changeRotationDir == true)
{
rectTransform.Rotate(new Vector3(0, 0, -1));
}
else
{
rectTransform.Rotate(new Vector3(0, 0, 1));
}
}
}
private void UseBackgImage()
{
if (useBackGroundImage == true)
{
backGroundImage.enabled = true;
rectTransform = transform.parent.gameObject.transform.GetComponent<RectTransform>();
}
else
{
backGroundImage.enabled = false;
rectTransform = transform.GetComponent<RectTransform>();
}
}
private void UseBackgImage(bool UseBackGroundImage)
{
if (useBackGroundImage == true)
{
backGroundImage.enabled = true;
}
else
{
backGroundImage.enabled = false;
}
}
}
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;
}
}
I am currently learning C# and XNA and I am having some troubles with getting my collision detection to work properly. I wish for my player to disappear when the Enemy object intersects.
Below shows my code within the Obj class
class Obj
{
public Vector2 position;
public float rotation = 0.0f;
public Texture2D spriteIndex;
public string spriteName;
public float speed = 0.0f;
public float scale = 1.0f;
public bool alive = true;
public Rectangle area;
public bool solid = false;
public Obj(Vector2 pos)
{
position = pos;
}
private Obj()
{
}
public virtual void Update()
{
if (!alive) return;
UpdateArea();
pushTo(speed, rotation);
}
public virtual void LoadContent(ContentManager content)
{
spriteIndex = content.Load<Texture2D>("sprites\\" + spriteName);
area = new Rectangle(0, 0, spriteIndex.Width, spriteIndex.Height);
}
public virtual void Draw(SpriteBatch spriteBatch)
{
if (!alive) return;
Rectangle Size;
Vector2 center = new Vector2(spriteIndex.Width / 2, spriteIndex.Height / 2);
spriteBatch.Draw(spriteIndex, position, null, Color.White, MathHelper.ToRadians(rotation), center, scale, SpriteEffects.None, 0);
}
public bool Collision(Vector2 pos, Obj obj)
{
Rectangle newArea = new Rectangle(area.X, area.Y, area.Width, area.Height);
newArea.X += (int)pos.X;
newArea.Y += (int)pos.Y;
foreach (Obj o in Items.objList)
{
if (o.GetType() == obj.GetType() && o.solid)
if (o.area.Intersects(newArea))
return true;
}
return false;
}
public Obj Collision(Obj obj)
{
foreach (Obj o in Items.objList)
{
if (o.GetType() == obj.GetType())
if (o.area.Intersects(area))
return o;
}
return new Obj();
}
public void UpdateArea()
{
area.X = (int)position.X - (spriteIndex.Width / 2);
area.Y = (int)position.Y - (spriteIndex.Height / 2);
}
public T CheckCollisionAgainst<T>() where T : Obj
{
// If collision detected, returns the colliding object; otherwise null.
return Items.objList
.OfType<T>()
.FirstOrDefault(o => o.solid && o.area.Intersects(area));
}
public virtual void pushTo(float pix, float dir)
{
float newX = (float)Math.Cos(MathHelper.ToRadians(dir));
float newY = (float)Math.Sin(MathHelper.ToRadians(dir));
position.X += pix * (float)newX;
position.Y += pix * (float)newY;
}
}
I am cycling through each Item in my objList to see if they intersect with each other, in this case, I want my Player to disappear if the Enemy intersects with them but this is not happening.
This code is from my Player class
class Player : Obj
{
KeyboardState keyboard;
KeyboardState prevKeyboard;
float spd;
public static Player player;
public Player(Vector2 pos)
: base(pos)
{
position = pos;
spd = 4;
spriteName = "WhiteBall";
solid = false;
player = this;
}
public override void Update()
{
player = this;
//If the player is NOT alive, end.
if (!alive) return;
keyboard = Keyboard.GetState();
//Keyboard controls for game
if(keyboard.IsKeyDown(Keys.W) && !Collision(new Vector2(0, -spd), new Enemy(new Vector2(0, 0))))
{
position.Y -= spd;
}
if (keyboard.IsKeyDown(Keys.A) && !Collision(new Vector2(-spd, 0), new Enemy(new Vector2(0, 0))))
{
position.X -= spd;
}
if (keyboard.IsKeyDown(Keys.S) && !Collision(new Vector2(0, spd), new Enemy(new Vector2(0, 0))))
{
position.Y += spd;
}
if (keyboard.IsKeyDown(Keys.D) && !Collision(new Vector2(spd, 0), new Enemy(new Vector2(0, 0))))
{
position.X += spd;
}
prevKeyboard = keyboard;
//Collision with enemy
Enemy enemy = CheckCollisionAgainst<Enemy>();
if (enemy != null)
{
alive = false;
}
base.Update();
}
public override void Draw(SpriteBatch spriteBatch)
{
spriteBatch.DrawString(Game1.font, "Pick Up The Crew", new Vector2(350, 0), Color.White);
base.Draw(spriteBatch);
}
}
If it intersects with the Enemy, it should disappear but this doesnt seem to be happening.
Based on the comments you provided, I'm taking a shot here and providing a possible solution (ensure UpdateArea is called before calling this):
public T CheckCollisionAgainst<T>() where T : Obj
{
// If collision detected, returns the colliding object; otherwise null.
return Items.objList
.OfType<T>()
.FirstOrDefault(o => o.area.Intersects(area));
}
Enemy enemy = CheckCollisionAgainst<Enemy>();
if (enemy != null)
{
alive = false;
}