Destroying game object - c#

I have created a simple 2D touch game in Unity and I have spikes spawning at the top of the scene every 3 seconds and when the spikes fall the player will tap the spikes before they hit the characters below, however, when I test the game, when I tap the spike (game object) it destroys all of the spikes (game objects) in the scene. Here is the code:
public GameObject spike;
public float spawnTime1 = 1f;
// Use this for initialization
void Start () {
InvokeRepeating ("SpawnSpike", spawnTime1, spawnTime1);
}
// Update is called once per frame
void Update () {
for (var i = 0; i < Input.touchCount; ++i) {
if (Input.GetTouch(i).phase == TouchPhase.Began) {
Destroy (gameObject);
}
}
}
void SpawnSpike () {
var newSpike = GameObject.Instantiate (spike);
newSpike.transform.position = new Vector3 (Random.Range(-3, 3), 11f, 0f);

It looks like you're destroying this game-manager-like script itself when you run
void Update () {
for (var i = 0; i < Input.touchCount; ++i) {
if (Input.GetTouch(i).phase == TouchPhase.Began) {
Destroy (gameObject);
}
}
}
The line Destroy (gameObject); is destroying its own game-object, which I'm guessing is parented to the spikes that are instantiated(?); hence destroying all the spikes at once.
I suggest using raycasts to find out if any spike is tapped on and/or which spike is tapped on, and then destroying only the game-object of that spike. Here's a good reference. I also suggest looking for tutorials regarding the same if you're still finding it hard to understand.
I hope that helps!
UPDATE:
Here's some sample code to get you going:
if (Input.GetTouch(i).phase == TouchPhase.Began) {
Vector3 pos = Camera.main.ScreenToWorldPoint (Input.GetTouch(i).position);
RaycastHit2D hit = Physics2D.Raycast(pos, Vector2.zero);
if (hit != null && hit.gameObject.CompareTag("spike") && hit.collider != null) {
Debug.Log ("I'm tapping "+hit.gameObject.name);
Destroy(hit.gameObject);
}
}
This specific code would require that your spike prefab (template) has the tag "spike". I also suggest you place this code in some kind of a global "game-manager" script's Update() (rather than in the Spike script), so that you don't over-process the touches.

Related

Ball shaking upon increasing its speed in Unity

I'm a beginner. I'm making a ball game in Unity, in which ball have to avoid the collision with the obstacle. In the game, I'm increasing the ball speed in every 3 seconds. Everything's working fine, but in the middle of game, I noticed the ball starts shaking, the speed decreases, and the camera can't catch the ball. I attached physics material to all gameobjects, and made all frictions zero, but the ball is still shaking.
Here is the link of the my game and the problem. Have a look: https://youtu.be/TR4M5whweTk
Here is the script attached to the ball:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
public Text gameOverText;
public Text scoreText;
public bool isGameOver;
public float speeder;
public float Score;
Touch touch;
public float speedmodifier ;
public float speed = 5;
// Start is called before the first frame update
private void Awake()
{
isGameOver = false;
Score = 0;
if(PlayerPrefs.GetFloat("HighScore") == 0)
{
PlayerPrefs.SetFloat("HighScore", 0);
}
PlayerPrefs.SetFloat("Score", Score);
}
void Start()
{
speeder = 4f;
gameOverText.enabled = false;
speedmodifier = 0.01f;
// GetComponent<Rigidbody>().velocity = new Vector3(0,0,speed);
}
// Update is called once per frame
void Update()
{ if(speeder >= 0)
{
speeder -= Time.deltaTime;
}
if (speeder<= 0 && speed < 50)
{
speed++;
speeder = 4f;
}
Debug.Log(speed);
if (isGameOver == false)
{
Score++;
}
scoreText.text = "Score : " + Score ;
if (Input.touchCount >0 && transform.position.x >= -3.5f && transform.position.x <= 3.5f)
{
touch = Input.GetTouch(0);
transform.Translate(touch.deltaPosition.x * speedmodifier,0,0);
}
else if(transform.position.x > 3.5f)
{
transform.position = new Vector3(3.49f,transform.position.y,transform.position.z);
}
else if(transform.position.x < -3.5f)
{
transform.position = new Vector3(-3.49f,transform.position.y,transform.position.z) ;
}
if (Input.GetKey(KeyCode.RightArrow) && transform.position.x < 3.5f)
{
transform.Translate(Vector3.right*speed* Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftArrow) && transform.position.x >-3.5f)
{
transform.Translate(Vector3.left*speed* Time.deltaTime);
}
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
private void OnTriggerEnter(Collider other)
{
if(other.gameObject.tag == "enemy")
{
isGameOver = true;
StartCoroutine("Wait");
GetComponent<MeshRenderer>().enabled = false;
gameObject.GetComponentInChildren<TrailRenderer>().enabled = false;
gameOverText.enabled = true;
if(PlayerPrefs.GetFloat("HighScore") < Score)
{
PlayerPrefs.SetFloat("HighScore", Score);
PlayerPrefs.SetFloat("Score", Score);
}
else
{
PlayerPrefs.SetFloat("Score", Score);
}
}
}
IEnumerator Wait()
{
Debug.Log(" My HighScore is : " + PlayerPrefs.GetFloat("HighScore"));
Debug.Log(" Score is : " + PlayerPrefs.GetFloat("Score"));
yield return new WaitForSeconds(3f);
SceneManager.LoadScene(1);
}
}
As BugFinder pointed out you are actually not moving the ball with physics, but just teleporting the ball with Transform.Translate which might be affecting the shacking issue, the other possible problem is that your ball speed might be varying due to a collision with the road, have you tried making the road RigidBody to Kinematic? so it won't affect the speed of the ball
OK you SHOULD NOT be using unity phsyics for this.
It's a "raster" game (and that's fun).
remove all physics everything. completely remove rigidbody, collider, etc
simply move the ball and/or scenery using a calculation each time.
(It's basically just frame time * speed, obviously.)
(Note, you can use strictly triggers - if you want - simply to know if the "ball" is near a "stick". But you can do that with 1 line of code, really no need for colliders/etc.)
Your Question
I just want to make sure that I am understanding your question correctly first, I believe you are asking for a way to prevent the ball from shaking during the game. (Let me know if this is incorrect, if so I apologize). From what I have gathered, this does not seem like a code based issue
Collision Detection
In unity, the rigidbody component has a field named 'Collision Detection' and this is set to discrete by default. This means that unity will look in direction of travel for a possible collider every now and again. That is an okay method to use when trying to save computer resources, however when in constant contact or at high velocities it is best to use the 'continuous' mode. This will check for a collision every physics update which occurs every physics time-step.
Colliders
Colliders in unity are a little finicky. Most notorious are mesh colliders as they have to be more heavenly processed/calculated. Using a box collider for your ground might give more accurate physics results.
Other Solutions
Whilst looking at your game video you published on YouTube, it looks like using physics may not be able to work. Since you are only traveling left, right, and forward globally, I would suggest implementing a movement script that uses an object's transform component instead of physics. This will be less resource intensive and will save further debugging headaches in the long run.

Physics OverlapSphere does not respond correctly

I can't quite understand how Physics.OverlapSphere works at this point. As shown below in the code, if the player enters the overlapsphere then it should return true, but I keep getting false when the player enters the sphere.
This is the script that call the method
void Update()
{
float distance = Vector3.Distance(target.position, transform.position);
if (distance <= lookRadius)
{
agent.SetDestination(target.position);
if (distance <= agent.stoppingDistance)
{
CharacterStats targetStats = target.GetComponent<CharacterStats>();
Debug.Log(enemy.onPlayerEnter());
if (targetStats != null && enemy.onPlayerEnter())
{//if player exist and the player enters the attack area
Combat.Attack(targetStats);
}
FaceTarget();
}
}
animator.SetFloat("speed", agent.velocity.magnitude);
this is the script of the method:
public bool onPlayerEnter()
{
Collider[] hitColliders = Physics.OverlapSphere(interactionTransform.transform.localPosition, radius);
//Debug.Log(interactionTransform.transform.localPosition);
for(int i = 0; i < hitColliders.Length; i++)
{
if(LayerMask.LayerToName(hitColliders[i].gameObject.layer) == "Player")
{
Debug.Log("Player enter");
return true;
}
}
return false;
}
//visualize the overlapsphere
private void OnDrawGizmosSelected()
{
if (interactionTransform == null) interactionTransform = transform;
Gizmos.color = Color.cyan;
Gizmos.DrawWireSphere(interactionTransform.position, radius);
}
collider with monster
[Collide with player[][1]][2]
https://i.stack.imgur.com/8Fgh0.png
https://i.stack.imgur.com/jnubp.png
For unknown reason, I found that the overlapsphere works at certain position in the map, but the rest of the position does not work at all. I think this probably is a bug in Unity.
weird position
Your sphere gizmo and actual sphere are different: for drawing gizmo you use transform.position, but for overlap sphere - transform.transform.localPosition (no need to double like transform.transform, and position and localPosition can be very different). I think, this is the answer.
Its easy to get mess with LayerMask, its a good approach, but for testing you better use tag, or gameObject.InstanceID, or even gameObject.name. But its minor, in general it looks like you deal with layers right.
Be sure that your agent.StoppingDistance not set too small
It`s a bad practice to use GetComponent every frame, as you do for get targetStats.

How do I make my bomb destroy all enemies in a certain radius?

So I'm making a game where you evade enemies and trigger certain powerups that has various effects on the enemies. One of them is a bomb that explodes 4 seconds after the player collides with it, destroying all enemies within its radius as it explodes.
I think I've got everything figured out except the actual destroying of the enemy. I feel like the solution is so obvious but I just never learned the method. At this point the bomb object is destroyed upon explosion instead of the enemies, which I expected to happen, because Destroy(other.gameObject) just doesn't work in this context! What do I do??
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
Debug.Log("player");
StartCoroutine(BombCountdownRoutine());
}
}
IEnumerator BombCountdownRoutine()
{
bombAudio.PlayOneShot(bombSound, 0.8f);
yield return new WaitForSeconds(4);
Collider[] hitColliders = Physics.OverlapSphere(transform.position, 10);
for (int i = 0; i < hitColliders.Length; i++)
{
if (hitColliders[i].gameObject.tag == "Enemy")
{
Destroy(gameObject);
}
}
}

Unity C# float value not decreasing on "OnCollisionEnter2d"

First have a look at my code
using UnityEngine;
using System.Collections;
public class Layer : MonoBehaviour {
public float health=150f;
void OnCollisionEnter2D(Collision2D beam){
if (beam.gameObject.tag == "Box") {
Destroy (gameObject);
}
Projectile enemyship = beam.gameObject.GetComponent<Projectile> (); // Retrieving enemyship
if (enemyship) {
Destroy (gameObject);
health = health - 100f; // its value is decreasing only once
Debug.Log (health);
if (health < 0f || health == 0f) {
Destroy (enemyship.gameObject); // this line not executing
}
}
}
}
In my above code the value of health is decreasing only once but OnCollisionEnter2D is working properly. That means on first collision the health value decreases by 100f and it becomes 50f but when it collides second time it's value is still 50f. And I have been looking since 3 hour for this solution. Please help me
I am adding little more thing. I am firing a projectile(laser) when I pressed space. So when laser hits twice object was supposed to be destroyed
Okay so first thing you're doing wrong is that your collision logic makes no sense at all. Your colliding object is "let's say a mortal object" which has to "die" whenever it's health is lower or equal to 0 but you're destroying it every time it collides with anything that has tag Box or has component of type Projectile.
To fix this first reduce the health based on these condition and then check if you want to destroy that object or not.
example code:
public float health = 150f;
void OnCollisionEnter2D(Collision2D beam)
{
float damage = 0f; // current damage...
if (beam.gameObject.tag == "Box")
{
// Destroy (gameObject); // do not destroy, just remove health
damage = health; // reduce health to 0
}
else
{
Projectile enemyship = beam.gameObject.GetComponent<Projectile> ();
if (enemyship)
{
// Destroy (gameObject); // again do not destroy.. just reduce health
damage = 100f;
}
}
health -= damage;
Debug.Log (health); // print your health
// check if dead
if (health < 0f || health == 0f) {
Destroy (gameObject); // this line not executing
}
}

Destroy Game Object after a few seconds of activating child

This is my code
void Update ()
{
if (Input.touchCount > 0 && Input.GetTouch (0).phase == TouchPhase.Began)
{
if ( Physics.Raycast(ray, out hit, 1000f ) )
{
for(int i=0; i< hit.collider.transform.childCount; i++)
{
var child = hit.collider.transform.GetChild(i).gameObject;
if(child != null)
child.SetActive(true);
}
hit.collider.gameObject.GetComponent<SpriteRenderer>().enabled = false;
//Debug.Log(hit.transform.gameObject.name);
}
}
}
This code sits on my camera in my scene. What it does is allows me to touch a game object and destroy. The first object I touch is a 2D sprite and I've turn off its sprite renderer and turn on its childs, sprite renderer.
However, I need a way to destroy the game object once this is done. I'm truly at a loss as to how I can achieve this.
Destroy (gameObject, 5);will destroy in 5 seconds.
Also you can use in the OnMouseDown() and spare all the for loop and raycast stuff in update
If you do want the OnMouseDown() you would of course need the script on the object prefab and not the camera though.

Categories