Destroy Gameobject according to distance value - unity3d

I have a script that generates objects in the scene from a prefab, and I have a moveable cube. I want a script that gets the name of the object if the distance between the cube and the cloned object is < 0.3f.
I have this UnityScript:
var distance1 = Vector3.Distance(Food.transform.position, cube1.transform.position);
Debug.Log(distance1);
if(distance1 < 0.3f)
{
//Destroy nearest object
}

In this case I think is better to use Collision Detection as recommended by Barış Çırıka... but if you want to get it by distance I think you can do something like
var MyCube = GameObject.FindGameObjectsWithTag("MyCube");
LateUpdate(){
var distance = Vector3.Distance(this.gameObject.transform.position, MyCube.transform.position);
if(distance < 0.3f)
{
Destroy(this.gameObject);
}
}
this script should be attached to every object you instantiate.

If you know which object is near. You can use Destroy.
Destroy(cloneObject);
If you don't know which objects are near, you can use List to add clone objects
and check it is near.(When you create clone you need to add clone to the list.)
You need to add using System.Collections.Generic; for using List.
Example code: (It's C# code but you can understand logic)
....
using System.Collections.Generic;
public List<GameObject>cloneObjectList;
private void cloneObject(){
GameObject cloneObject = Instantiate(originalPrefab,position,rotation);
cloneObjectList.add(cloneObject);
}
private void checkDistance(){
foreach(GameObject cloneObject in cloneObjectList){
float distance = Vector3.Distance(Food.transform.position, cloneObject.transform.position);
if(distance <0.3f){
cloneObjectList.Remove(cloneObject);
Destroy(cloneObject);
}
}
}
Moreover you can use Collision detection system.

Related

Generate a path based on placed shapes and make a Gameobject walk the path

I am making a game where the player place shapes to make a path that connects a Starting point to a Destination point and make a wagon walk on that path.
I am stuck on how to make the path and force the wagon respect the switch points even if the Destination point is not in that direction. I tried NavmeshSurface on the path and made the wagon a Navmesh agent, it walks on the path and make it to the destination point but it ignores the switch point. I have no idea how to make this works, please help me with your suggestions and ideas on how to generate a path according to the shapes placed and make the wagon follow that path thank you in advance :)
Step 1: Create 2 new scripts
Step 2: Attach one to the wagon you wish to move. This script will be for pathfinding.
Step 3: Copy-paste this code into the script you attached to the wagon:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
`public class Pathfinder : MonoBehaviour
{
WaveConfigSO waveConfig;
List<Transform> waypoints;
int waypointIndex = 0;
void Start()
{
waypoints = waveConfig.GetWayPoints();
transform.position = waypoints[waypointIndex].position;
}
void Update()
{
FollowPath();
}
void FollowPath()
{
if (waypointIndex < waypoints.Count)
{
Vector3 targetPosition = waypoints[waypointIndex].position;
float delta = waveConfig.GetMoveSpeed() * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, targetPosition, delta);
if (transform.position == targetPosition)
{
waypointIndex++;
}
}
}
}
Step 4: Copy-paste this code into the other script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "Path Config", fileName = "New Path Config")]
public class WaveConfigSO : ScriptableObject
{
[SerializeField] Transform pathPrefab;
[SerializeField] float moveSpeed = 5f;
public List<Transform> GetWayPoints()
{
List<Transform> waypoints = new List<Transform>();
foreach(Transform child in pathPrefab)
{
waypoints.Add(child);
}
return waypoints;
}
public float GetMoveSpeed()
{
return moveSpeed;
}
}
Step 4: Make an empty gameObject in your hierarchy. This gameObject will hold the waypoints for your path
Step 5: Make another empty game object that is inside the previous one. Name it "Waypoint (0)". The parentheses are important so that when you duplicate the waypoints the index automatically gets incremented.
Step 6: Change its icon so that you can visualize the waypoints
Step 7: Duplicate the waypoint as many times as you wish.
Step 8: Arrange the waypoints for your wagon to follow on the track
Step 9: Prefab the path and create a new scriptable object. Set the speed to whatever you want and attach the path prefab to the variable slot on the scriptable object.
Step 10: Go to your wagon and set up the scriptable object as the variable needed for the pathfinding script that the wagon has.
Step 11: Enjoy
So I did a couple of changes relative to my case, which means there's a good chance this setup won't work from the get-go. If that happens just answer here with the problem and I will help you debug it if needed.
One other thing: this setup is purely for testing purposes. As for giving control to the player, you will obviously have to make some other changes. For example, when a new tile track is placed, instantiate a new waypoint for the path right on top of it. If you have trouble with that too, let me know, I might be able to help on that case as well.
Vlad

Unity 2D - how to check if my gameobject/sprite is below ceratin Y lvl?

I've been trying to get a script working to check if my player is below a certain Y lvl, for a platformer. so it can be respawned to the beginning, But how do I put the y lvl inside a variable to check it? i cant figure it out lol
In the Update() run something like:
if(player.transform.position.y < 1)
{
//do something
}
where 'player' is the GameObject in question.
I am assuming you want to just want to compare (==, <=, >=, all that jazz is what I mean by comparing just in case you were not aware) the Y value to something like 10 for example. This is easy and you don't even need a variable necessarily for this.
//For the object position relative to the world
if(transform.position.y == 10) //"transform" gives you acces to the transform component
{ //of the object the script is attached to
Debug.Log("MILK GANG");
}
//For the object position relative to its Parent Object
if(transform.localPosition.y == 10)
{
Debug.Log("MILK GANG");
}
If you want to change the value of the position of your object then
transform.position = new Vector2(6, 9)//Nice
//BTW new Vector2 can be used if you dont
//want to assign a completely new variable
However, if you want to get a reference (Basically a variable that tells the code your talking about this component) to it.
private Transform Trans;
void Awake() //Awake is called/being executed before the first frame so its
{ //better than void Start in this case
Trans = GetComponent<Transform>();
Trans.position = new Vector2(69, 420); //Nice
}
This is the code way of doing it but there's another way that uses Unity
[SerializeField] private Transform Trans;
//[SerializeField] makes the variable changeable in Unity even if it is private so you
//can just drag and drop on to this and you good to go
Hope this help
if it doesn't
then welp I tried lel
You can use a script added to gameobject to check transform.position of the object.
if(transform.position.y < ylvl)
{
//do something
}
where ylvl is the integer of the height you want to check

Instantiate GameObjects and change Material when it hits on the ground

There is a code for instantiate cube into the list and change a Material of each clone when it hits on the ground
The following code works but not in Real-Time. Update function works like a Start function for a Foreach method
How to get a value of item.transform.position.y in the Update function Real-Time?
public GameObject cubePrefab;
public Material RedMat;
public float GroudLevel = 0.5f;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
List<GameObject> cloneList = new List<GameObject>();
//instantiate clones into the list
for (int i = 0; i < 10; i++)
{
var clone = Instantiate (cubePrefab,new Vector3(Random.Range(-3f, 3f),
Random.Range(4f, 10.5f),Random.Range(-3f, 3f)), Quaternion.identity);
cloneList.Add(clone);
}
//if clone is grounded change a Material for each clone
foreach (var item in cloneList)
{
//Debug.Log(item.transform.position.y);
//check if clone is on the ground
if(item.transform.position.y < GroudLevel)
{
item.GetComponent<Renderer>().material = RedMat;
}
}
}
}
There is a screenshot for a GroudLevel = 7
The reason this function isn't working is because the pivot (transform.position) of your item is always in the center of the object. This isn't something you can change in Unity (nor would you necessarily want to).
On top of this, you're checking if the item is under the ground, and not on it when you use < insteaad of <=, because the position needs to be less than groundLevel to return true.
There are several solutions here.
The simplest would involve moving all of this logic to an OnCollisionEnter or OnTriggerEnter method. For more information on this, check the Unity documentation.
Another solution would be to find a way tthe size of the object, divide it by two, and check if
item.transform.position - halfSize <= groundLevel;
This seems really cumbersome and overly complex, however. You'd be better off using Unity's built-in collision system, unless you have a reason not to.

Spawn sprites on action

I'm trying to make a Pinata GameObject, that when clicked bursts and gives a variable number of Gift GameObjects with various images and behaviors in them.
I'm also not sure what the unity vocabulary for this is so as to look this up in unity docs.
Can anyone please lend me a hand here? Thanks!
There are several ways to handle this.
The simple way is to use Object.Instantiate, Object Instantiation is the vocab you're after.
This will create a copy of a predefined Unity object, this can be a gameobject or any other object derived from UnityEngine.Object, check the docs for more info https://docs.unity3d.com/ScriptReference/Object.Instantiate.html.
In your case, your Pinata would have an array, or list, of prefabs. These prefabs are created by you with a certain behaviour and sprite for each one. When the Pinata bursts, you instantiate random prefabs at random positions surrounding the Pinata, up to you how to position these objects.
Something along these lines should do the trick:
class Pinata : Monobehaviour
{
public GameObject[] pickupPrefabs;
public int numberOfItemsToSpawn; //This can be random
//any other variables that influence spawning
//Other methods
public void Burst()
{
for(int i = 0; i < numberOfItemsToSpawn; i++)
{
//Length - 1 because the range is inclusive, may return
//the length of the array otherwise, and throw exceptions
int randomItem = Random.Range(0, pickupPrefabs.Length - 1);
GameObject pickup = (GameObject)Instantiate(pickupPrefabs[randomItem]);
pickup.transform.position = transform.position;
//the position can be randomised, you can also do other cool effects like apply an explosive force or something
}
}
}
Bare in mind, if you want the game to be consistent, then each behaviour prefab would have there own predefined sprite, this would not be randomised. The only thing randomised would be the spawning and positioning.
If you did want to randomise the sprites for the behaviours then you'd have to add this to the Pinata class:
public class Pinata : Monobehaviour
{
//An array of all possible sprites
public Sprite[] objectSprites;
public void Burst()
{
//the stuff I mentioned earlier
int randomSprite = Random.Range(0, objectSprites.Length - 1);
SpriteRenderer renderer = pickup.GetComponent<SpriteRenderer>();
//Set the sprite of the renderer to a random one
renderer.sprite = objectSprites[randomSprite];
float flip = Random.value;
//not essential, but can make it more random
if(flip > 0.5)
{
renderer.flipX = true;
}
}
}
You can use Unity random for all your random needs, https://docs.unity3d.com/ScriptReference/Random.html
Hopefully this'll lead you in the right direction.

how to randomly initialize particles system in different places of scene in unity3d

I recently tried asking this question but I realized it was not a sufficient question. In my game the player is a fire fighter learner and i want to broke out fire randomly in my game (like not predictable by player), but i did not know how to implement this.
So far i have done this but nothing goes good.(I have a empty object called t in unity which have 3 to 5 particles systems, and all are set to dont awake at start)
code is here :
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
public ParticleSystem[] particles;
public int numOn = 3;
public int j;
void Start() {
for (int i = 0; i < particles.Length - 1; i++) {
j = Random.Range(i + 1, particles.Length - 1);
ParticleSystem t = particles[j];
particles[j] = particles[i];
particles[i] = t;
}
for (j = 0; j < numOn; j++ )
{
particles[j].Play();
}
}
}
help will be appreciated :-)
You could try using prefabs. Create a game object in the editor that has any particle systems and scripts your fire objects need. Once it's good, drag the object from the hierarchy into your project. This will create a prefab (you can now remove it from the scene). Now, on your spawning script, add a field of type GameObject and drag the prefab you made before into it. Now, when you need to create one, just call Instantiate(prefabVar) to create a copy of your prefab.
Edit:
For your specific case, since you only want one fire to be instantiated in a random location, you could have your spawning script look something like this:
public Transform[] SpawnPoints;
public GameObject FirePrefab;
void Start() {
Transform selectedSpawnPoint = SpawnPoints[(int)Random.Range(0, SpawnPoints.Count - 1)];
Instantiate(FirePrefab, selectedSpawnPoint.position, selectedSpawnPoint.rotation);
}
This solution would allow for you to potentially spawn more than one fire object if you needed. An alternative would be if you will only ever have exactly one fire object in the scene at all. Instead of instantiating from a prefab, the object is already in the scene and you just move it to one of your spawn points at the start of the scene. An example script on the fire object itself:
public Transform[] SpawnPoints;
void Start() {
Transform selectedSpawnPoint = SpawnPoints[(int)Random.Range(0, SpawnPoints.Count - 1)];
transform.position = selectedSpawnPoint.position;
transform.rotation = selectedSpawnPoint.rotation;
}